Parse integers and single-precision floats in incoming CBOR streams
[platform/upstream/iotivity.git] / resource / csdk / stack / src / ocpayloadparse.c
1 //******************************************************************
2 //
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
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
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
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.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
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
29 #include <string.h>
30 #include <stdlib.h>
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"
38
39 #define TAG "OIC_RI_PAYLOADPARSE"
40
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);
48
49 OCStackResult OCParsePayload(OCPayload **outPayload, OCPayloadType payloadType,
50         const uint8_t *payload, size_t payloadSize)
51 {
52     OCStackResult result = OC_STACK_MALFORMED_RESPONSE;
53     CborError err;
54
55     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Conversion of outPayload failed");
56     VERIFY_PARAM_NON_NULL(TAG, payload, "Invalid cbor payload value");
57
58     OIC_LOG_V(INFO, TAG, "CBOR Parsing size: %zu", payloadSize);
59
60     CborParser parser;
61     CborValue rootValue;
62
63     err = cbor_parser_init(payload, payloadSize, 0, &parser, &rootValue);
64     VERIFY_CBOR_SUCCESS(TAG, err, "Failed initializing init value")
65
66     switch(payloadType)
67     {
68         case PAYLOAD_TYPE_DISCOVERY:
69             result = OCParseDiscoveryPayload(outPayload, &rootValue);
70             break;
71         case PAYLOAD_TYPE_DEVICE:
72             result = OCParseDevicePayload(outPayload, &rootValue);
73             break;
74         case PAYLOAD_TYPE_PLATFORM:
75             result = OCParsePlatformPayload(outPayload, &rootValue);
76             break;
77         case PAYLOAD_TYPE_REPRESENTATION:
78             result = OCParseRepPayload(outPayload, &rootValue);
79             break;
80         case PAYLOAD_TYPE_PRESENCE:
81             result = OCParsePresencePayload(outPayload, &rootValue);
82             break;
83         case PAYLOAD_TYPE_SECURITY:
84             result = OCParseSecurityPayload(outPayload, payload, payloadSize);
85             break;
86         case PAYLOAD_TYPE_RD:
87             result = OCRDCborToPayload(&rootValue, outPayload);
88             break;
89         default:
90             OIC_LOG_V(ERROR, TAG, "ParsePayload Type default: %d", payloadType);
91             result = OC_STACK_INVALID_PARAM;
92             break;
93     }
94
95     OIC_LOG_V(INFO, TAG, "Finished parse payload, result is %d", result);
96
97 exit:
98     return result;
99 }
100
101 void OCFreeOCStringLL(OCStringLL* ll);
102
103 static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, const uint8_t *payload,
104         size_t size)
105 {
106     if (size > 0)
107     {
108         *outPayload = (OCPayload *)OCSecurityPayloadCBORCreate(payload, size);
109     }
110     else
111     {
112         *outPayload = NULL;
113     }
114     return OC_STACK_OK;
115 }
116
117 static char* InPlaceStringTrim(char* str)
118 {
119     while (str[0] == ' ')
120     {
121         ++str;
122     }
123
124     size_t lastchar = strlen(str);
125
126     while (str[lastchar] == ' ')
127     {
128         str[lastchar] = '\0';
129         --lastchar;
130     }
131
132     return str;
133 }
134
135 static CborError OCParseStringLL(CborValue *map, char *type, OCStringLL **resource)
136 {
137     CborValue val;
138     CborError err = cbor_value_map_find_value(map, type, &val);
139     VERIFY_CBOR_SUCCESS(TAG, err, "to find StringLL TAG");
140
141     if (cbor_value_is_text_string(&val))
142     {
143         char *input = NULL;
144         char *savePtr = NULL;
145         size_t len = 0;
146
147         err = cbor_value_dup_text_string(&val, &input, &len, NULL);
148         VERIFY_CBOR_SUCCESS(TAG, err, "to find StringLL value");
149
150         if (input)
151         {
152             char *curPtr = strtok_r(input, " ", &savePtr);
153             while (curPtr)
154             {
155                 char *trimmed = InPlaceStringTrim(curPtr);
156                 if (trimmed[0] !='\0')
157                 {
158                     if (!OCResourcePayloadAddStringLL(resource, trimmed))
159                     {
160                         return CborErrorOutOfMemory;
161                     }
162                 }
163                 curPtr = strtok_r(NULL, " ", &savePtr);
164             }
165             OICFree(input);
166         }
167     }
168 exit:
169     return err;
170 }
171
172 static OCStackResult OCParseDiscoveryPayload(OCPayload **outPayload, CborValue *rootValue)
173 {
174     OCStackResult ret = OC_STACK_INVALID_PARAM;
175     OCResourcePayload *resource = NULL;
176     OCDiscoveryPayload *out = NULL;
177     size_t len = 0;
178     CborError err = CborNoError;
179     *outPayload = NULL;
180
181     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
182     VERIFY_PARAM_NON_NULL(TAG, rootValue, "Invalid Parameter rootValue");
183
184     // Root value is already inside the main root array
185     CborValue rootMap;
186     ret = OC_STACK_NO_MEMORY;
187     out = OCDiscoveryPayloadCreate();
188     VERIFY_PARAM_NON_NULL(TAG, out, "Failed error initializing discovery payload");
189
190     // Enter the main root map
191     ret = OC_STACK_MALFORMED_RESPONSE;
192     err = cbor_value_enter_container(rootValue, &rootMap);
193     VERIFY_CBOR_SUCCESS(TAG, err, "to enter root map container");
194
195     // Look for DI
196     CborValue curVal;
197     err = cbor_value_map_find_value(&rootMap, OC_RSRVD_DEVICE_ID, &curVal);
198     VERIFY_CBOR_SUCCESS(TAG, err, "to find device id tag");
199     if (cbor_value_is_valid(&curVal))
200     {
201         if (cbor_value_is_byte_string(&curVal))
202         {
203             err = cbor_value_dup_byte_string(&curVal, (uint8_t **)&(out->sid), &len, NULL);
204             VERIFY_CBOR_SUCCESS(TAG, err, "to copy device id value");
205         }
206         else if (cbor_value_is_text_string(&curVal))
207         {
208             err = cbor_value_dup_text_string(&curVal, &(out->sid), &len, NULL);
209             VERIFY_CBOR_SUCCESS(TAG, err, "to copy device id value");
210         }
211     }
212
213     // BaseURI - Not a mandatory field
214     err = cbor_value_map_find_value(&rootMap, OC_RSRVD_BASE_URI, &curVal);
215     if (cbor_value_is_valid(&curVal))
216     {
217         err = cbor_value_dup_text_string(&curVal, &(out->baseURI), &len, NULL);
218         VERIFY_CBOR_SUCCESS(TAG, err, "to find base uri value");
219     }
220
221     // Look for Links which will have an array as the value
222     CborValue linkMap;
223     err = cbor_value_map_find_value(&rootMap, OC_RSRVD_LINKS, &linkMap);
224     VERIFY_CBOR_SUCCESS(TAG, err, "to find links tag");
225
226     // Enter the links array and start iterating through the array processing
227     // each resource which shows up as a map.
228     CborValue resourceMap;
229     err = cbor_value_enter_container(&linkMap, &resourceMap);
230     VERIFY_CBOR_SUCCESS(TAG, err, "to enter link map");
231
232     while (cbor_value_is_map(&resourceMap))
233     {
234         resource = (OCResourcePayload *)OICCalloc(1, sizeof(OCResourcePayload));
235         VERIFY_PARAM_NON_NULL(TAG, resource, "Failed allocating resource payload");
236
237         // Uri
238         err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_HREF, &curVal);
239         VERIFY_CBOR_SUCCESS(TAG, err, "to find href tag");
240         err = cbor_value_dup_text_string(&curVal, &(resource->uri), &len, NULL);
241         VERIFY_CBOR_SUCCESS(TAG, err, "to find href value");
242
243         // ResourceTypes
244         err =  OCParseStringLL(&resourceMap, OC_RSRVD_RESOURCE_TYPE, &resource->types);
245         VERIFY_CBOR_SUCCESS(TAG, err, "to find resource type tag/value");
246
247         // Interface Types
248         err =  OCParseStringLL(&resourceMap, OC_RSRVD_INTERFACE, &resource->interfaces);
249         if (CborNoError != err)
250         {
251             if (!OCResourcePayloadAddStringLL(&resource->interfaces, OC_RSRVD_INTERFACE_LL))
252             {
253                 err = CborErrorOutOfMemory;
254             }
255         }
256
257         // Policy
258         CborValue policyMap;
259         err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_POLICY, &policyMap);
260         VERIFY_CBOR_SUCCESS(TAG, err, "to find policy tag");
261
262         // Bitmap
263         err = cbor_value_map_find_value(&policyMap, OC_RSRVD_BITMAP, &curVal);
264         VERIFY_CBOR_SUCCESS(TAG, err, "to find bitmap tag");
265         err = cbor_value_get_int(&curVal, (int *)&resource->bitmap);
266         VERIFY_CBOR_SUCCESS(TAG, err, "to find bitmap value");
267
268         // Secure Flag
269         err = cbor_value_map_find_value(&policyMap, OC_RSRVD_SECURE, &curVal);
270         if (cbor_value_is_valid(&curVal))
271         {
272             err = cbor_value_get_boolean(&curVal, &(resource->secure));
273             VERIFY_CBOR_SUCCESS(TAG, err, "to find secure value");
274         }
275
276         // Port
277         err = cbor_value_map_find_value(&policyMap, OC_RSRVD_HOSTING_PORT, &curVal);
278         if (cbor_value_is_valid(&curVal))
279         {
280             err = cbor_value_get_int(&curVal, (int *)&resource->port);
281             VERIFY_CBOR_SUCCESS(TAG, err, "to find port value");
282         }
283
284         err = cbor_value_advance(&resourceMap);
285         VERIFY_CBOR_SUCCESS(TAG, err, "to advance resource map");
286
287         OCDiscoveryPayloadAddNewResource(out, resource);
288     }
289
290     err = cbor_value_leave_container(rootValue, &resourceMap);
291     VERIFY_CBOR_SUCCESS(TAG, err, "to advance resource map");
292
293     *outPayload = (OCPayload *)out;
294     return OC_STACK_OK;
295
296 exit:
297     OCDiscoveryResourceDestroy(resource);
298     OCDiscoveryPayloadDestroy(out);
299     return ret;
300 }
301
302 static OCStackResult OCParseDevicePayload(OCPayload **outPayload, CborValue *rootValue)
303 {
304     OCStackResult ret = OC_STACK_INVALID_PARAM;
305     CborError err = CborNoError;
306     OCDevicePayload *out = NULL;
307     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid param outPayload");
308     VERIFY_PARAM_NON_NULL(TAG, rootValue, "Invalid param rootValue");
309
310     *outPayload = NULL;
311
312     out = (OCDevicePayload *)OICCalloc(1, sizeof(OCDevicePayload));
313     VERIFY_PARAM_NON_NULL(TAG, out, "Failed allocating device payload")
314     out->base.type = PAYLOAD_TYPE_DEVICE;
315     ret = OC_STACK_MALFORMED_RESPONSE;
316
317     if (cbor_value_is_map(rootValue))
318     {
319         CborValue curVal;
320         // Resource Type
321         err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
322         if (cbor_value_is_valid(&curVal))
323         {
324             err =  OCParseStringLL(rootValue, OC_RSRVD_RESOURCE_TYPE, &out->types);
325             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find rt type tag/value");
326         }
327         // Device ID
328         size_t len = 0;
329         err = cbor_value_map_find_value(rootValue, OC_RSRVD_DEVICE_ID, &curVal);
330         if (cbor_value_is_valid(&curVal))
331         {
332             if (cbor_value_is_byte_string(&curVal))
333             {
334                 err = cbor_value_dup_byte_string(&curVal, (uint8_t **)&out->sid, &len, NULL);
335                 VERIFY_CBOR_SUCCESS(TAG, err, "to find device id in device payload");
336             }
337             else if (cbor_value_is_text_string(&curVal))
338             {
339                 err = cbor_value_dup_text_string(&curVal, &out->sid, &len, NULL);
340                 VERIFY_CBOR_SUCCESS(TAG, err, "to find device id in device payload");
341             }
342         }
343         // Device Name
344         err = cbor_value_map_find_value(rootValue, OC_RSRVD_DEVICE_NAME, &curVal);
345         if (cbor_value_is_valid(&curVal))
346         {
347             err = cbor_value_dup_text_string(&curVal, &out->deviceName, &len, NULL);
348             VERIFY_CBOR_SUCCESS(TAG, err, "to find device name in device payload");
349         }
350         // Device Spec Version
351         err = cbor_value_map_find_value(rootValue, OC_RSRVD_SPEC_VERSION, &curVal);
352         if (cbor_value_is_valid(&curVal))
353         {
354             err = cbor_value_dup_text_string(&curVal, &out->specVersion, &len, NULL);
355             VERIFY_CBOR_SUCCESS(TAG, err, "to find spec version in device payload");
356         }
357         // Data Model Version
358         err = cbor_value_map_find_value(rootValue, OC_RSRVD_DATA_MODEL_VERSION, &curVal);
359         if (cbor_value_is_valid(&curVal))
360         {
361             err = cbor_value_dup_text_string(&curVal, &out->dataModelVersion, &len, NULL);
362             VERIFY_CBOR_SUCCESS(TAG, err, "to find data model version in device payload");
363         }
364         err = cbor_value_advance(rootValue);
365         VERIFY_CBOR_SUCCESS(TAG, err, "to advance device payload");
366
367         *outPayload = (OCPayload *)out;
368         return OC_STACK_OK;
369     }
370
371 exit:
372     OCDevicePayloadDestroy(out);
373     return ret;
374 }
375
376 static OCStackResult OCParsePlatformPayload(OCPayload **outPayload, CborValue *rootValue)
377 {
378     OCStackResult ret = OC_STACK_INVALID_PARAM;
379     CborError err = CborNoError;
380     OCPlatformInfo info = {0};
381     char* rt = NULL;
382     OCStringLL* interfaces = NULL;
383     OCPlatformPayload* out = NULL;
384
385     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
386
387     if (cbor_value_is_map(rootValue))
388     {
389         CborValue repVal;
390         size_t len = 0;
391         ret = OC_STACK_MALFORMED_RESPONSE;
392
393         // Platform ID
394         err = cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_ID, &repVal);
395         if (cbor_value_is_valid(&repVal))
396         {
397             err = cbor_value_dup_text_string(&repVal, &(info.platformID), &len, NULL);
398             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find platformID in the platform payload");
399         }
400          // MFG Name
401         err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_NAME, &repVal);
402         if (cbor_value_is_valid(&repVal))
403         {
404             err = cbor_value_dup_text_string(&repVal, &(info.manufacturerName), &len, NULL);
405             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find manufactureName in the platform payload");
406         }
407         // MFG URL
408         err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_URL, &repVal);
409         if (cbor_value_is_valid(&repVal))
410         {
411             err = cbor_value_dup_text_string(&repVal, &(info.manufacturerUrl), &len, NULL);
412             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find manufactureUrl in the platform payload");
413         }
414         // Model Num
415         err = cbor_value_map_find_value(rootValue, OC_RSRVD_MODEL_NUM, &repVal);
416         if (cbor_value_is_valid(&repVal))
417         {
418             err = cbor_value_dup_text_string(&repVal, &(info.modelNumber), &len, NULL);
419             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find modelNumber in the platform payload");
420         }
421         // Date of Mfg
422         err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_DATE, &repVal);
423         if (cbor_value_is_valid(&repVal))
424         {
425             err = cbor_value_dup_text_string(&repVal, &(info.dateOfManufacture), &len, NULL);
426             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find dateOfManufacture in the platform payload");
427         }
428         // Platform Version
429         err = cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_VERSION, &repVal);
430         if (cbor_value_is_valid(&repVal))
431         {
432             err = cbor_value_dup_text_string(&repVal, &(info.platformVersion), &len, NULL);
433             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find platformVersion in the platform payload");
434         }
435         // OS Version
436         err = cbor_value_map_find_value(rootValue, OC_RSRVD_OS_VERSION, &repVal);
437         if (cbor_value_is_valid(&repVal))
438         {
439             err = cbor_value_dup_text_string(&repVal, &(info.operatingSystemVersion), &len, NULL);
440             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find OSVersion in the platform payload");
441         }
442         // Hardware Version
443         err = cbor_value_map_find_value(rootValue, OC_RSRVD_HARDWARE_VERSION, &repVal);
444         if(cbor_value_is_valid(&repVal))
445         {
446             err = cbor_value_dup_text_string(&repVal, &(info.hardwareVersion), &len, NULL);
447             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find HWVersion in the platform payload");
448         }
449         // Firmware Version
450         err = cbor_value_map_find_value(rootValue, OC_RSRVD_FIRMWARE_VERSION, &repVal);
451         if(cbor_value_is_valid(&repVal))
452         {
453             err = cbor_value_dup_text_string(&repVal, &(info.firmwareVersion), &len, NULL);
454             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find firmwareVersion in the platform payload");
455         }
456         // Support URL
457         err = cbor_value_map_find_value(rootValue, OC_RSRVD_SUPPORT_URL, &repVal);
458         if(cbor_value_is_valid(&repVal))
459         {
460             err = cbor_value_dup_text_string(&repVal, &(info.supportUrl), &len, NULL);
461             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find supportUrl in the platform payload");
462         }
463         // System Time
464         err = cbor_value_map_find_value(rootValue, OC_RSRVD_SYSTEM_TIME, &repVal);
465         if(cbor_value_is_valid(&repVal))
466         {
467             err = cbor_value_dup_text_string(&repVal, &(info.systemTime), &len, NULL);
468             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find systemTume in the platform payload");
469         }
470
471         // Resource type
472         err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &repVal);
473         if(cbor_value_is_valid(&repVal))
474         {
475             err = cbor_value_dup_text_string(&repVal, &rt, &len, NULL);
476             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find resource type in the platform payload");
477         }
478
479         // Interface Types
480         err = cbor_value_map_find_value(rootValue, OC_RSRVD_INTERFACE, &repVal);
481         if(cbor_value_is_valid(&repVal))
482         {
483             err =  OCParseStringLL(rootValue, OC_RSRVD_INTERFACE, &interfaces);
484             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
485         }
486
487         err = cbor_value_advance(rootValue);
488         VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find supportUrl in the platform payload");
489
490        out = (OCPlatformPayload *)OCPlatformPayloadCreateAsOwner(&info);
491        out->rt = rt;
492        out->interfaces = interfaces;
493        *outPayload = (OCPayload *)out;
494        return OC_STACK_OK;
495     }
496
497 exit:
498     OCPlatformInfoDestroy(&info);
499     OIC_LOG(ERROR, TAG, "CBOR error In ParsePlatformPayload");
500     return ret;
501 }
502
503 static OCRepPayloadPropType DecodeCborType(CborType type)
504 {
505     switch (type)
506     {
507         case CborNullType:
508             return OCREP_PROP_NULL;
509         case CborIntegerType:
510             return OCREP_PROP_INT;
511         case CborDoubleType:
512         case CborFloatType:
513             return OCREP_PROP_DOUBLE;
514         case CborBooleanType:
515             return OCREP_PROP_BOOL;
516         case CborTextStringType:
517             return OCREP_PROP_STRING;
518         case CborByteStringType:
519             return OCREP_PROP_BYTE_STRING;
520         case CborMapType:
521             return OCREP_PROP_OBJECT;
522         case CborArrayType:
523             return OCREP_PROP_ARRAY;
524         default:
525             return OCREP_PROP_NULL;
526     }
527 }
528 static CborError OCParseArrayFindDimensionsAndType(const CborValue *parent,
529         size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType *type)
530 {
531     CborValue insideArray;
532     *type = OCREP_PROP_NULL;
533     dimensions[0] = dimensions[1] = dimensions[2] = 0;
534
535     CborError err = cbor_value_enter_container(parent, &insideArray);
536     VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
537
538     while (cbor_value_is_valid(&insideArray))
539     {
540         OCRepPayloadPropType tempType = DecodeCborType(cbor_value_get_type(&insideArray));
541
542         if (tempType == OCREP_PROP_ARRAY)
543         {
544             size_t subdim[MAX_REP_ARRAY_DEPTH];
545             tempType = OCREP_PROP_NULL;
546             err = OCParseArrayFindDimensionsAndType(&insideArray, subdim, &tempType);
547             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse array");
548
549             if (subdim[2] != 0)
550             {
551                 OIC_LOG(ERROR, TAG, "Parse array helper, sub-array too deep");
552             }
553
554             dimensions[1] = dimensions[1] >= subdim[0] ? dimensions[1] : subdim[0];
555             dimensions[2] = dimensions[2] >= subdim[1] ? dimensions[2] : subdim[1];
556
557             if (*type != OCREP_PROP_NULL && tempType != OCREP_PROP_NULL && *type != tempType)
558             {
559                 OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed (subtype)");
560                 return CborUnknownError;
561             }
562             else if (*type == OCREP_PROP_NULL)
563             {
564                 // We don't know the type of this array yet, so the assignment is OK
565                 *type = tempType;
566             }
567         }
568         else if (*type == OCREP_PROP_NULL)
569         {
570             // We don't know the type of this array yet, so the assignment is OK
571             *type = tempType;
572         }
573         // tempType is allowed to be NULL, since it might now know the answer yet
574         else if (tempType != OCREP_PROP_NULL && *type != tempType)
575         {
576             // this is an invalid situation!
577             OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed");
578             return CborUnknownError;
579         }
580
581         ++dimensions[0];
582         err = cbor_value_advance(&insideArray);
583         VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance array");
584     }
585
586 exit:
587     return err;
588 }
589
590 static size_t getAllocSize(OCRepPayloadPropType type)
591 {
592     switch (type)
593     {
594         case OCREP_PROP_INT:
595             return sizeof (int64_t);
596         case OCREP_PROP_DOUBLE:
597             return sizeof (double);
598         case OCREP_PROP_BOOL:
599             return sizeof (bool);
600         case OCREP_PROP_STRING:
601             return sizeof (char*);
602         case OCREP_PROP_BYTE_STRING:
603             return sizeof (OCByteString);
604         case OCREP_PROP_OBJECT:
605             return sizeof (OCRepPayload*);
606         default:
607             return 0;
608     }
609 }
610
611 static size_t arrayStep(size_t dimensions[MAX_REP_ARRAY_DEPTH], size_t elementNum)
612 {
613     return
614         (dimensions[1] == 0 ? 1 : dimensions[1]) *
615         (dimensions[2] == 0 ? 1 : dimensions[2]) *
616         elementNum;
617 }
618
619 static CborError OCParseArrayFillArray(const CborValue *parent,
620         size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType type, void *targetArray)
621 {
622     CborValue insideArray;
623
624     size_t i = 0;
625     char *tempStr = NULL;
626     OCByteString ocByteStr = { .bytes = NULL, .len = 0};
627     size_t tempLen = 0;
628     OCRepPayload *tempPl = NULL;
629
630     size_t newdim[MAX_REP_ARRAY_DEPTH];
631     newdim[0] = dimensions[1];
632     newdim[1] = dimensions[2];
633     newdim[2] = 0;
634
635     CborError err = cbor_value_enter_container(parent, &insideArray);
636     VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
637
638     while (!err && i < dimensions[0] && cbor_value_is_valid(&insideArray))
639     {
640         bool noAdvance = false;
641         if (cbor_value_get_type(&insideArray) != CborNullType)
642         {
643             switch (type)
644             {
645                 case OCREP_PROP_INT:
646                     if (dimensions[1] == 0)
647                     {
648                         err = cbor_value_get_int64(&insideArray, &(((int64_t*)targetArray)[i]));
649                     }
650                     else
651                     {
652                         err = OCParseArrayFillArray(&insideArray, newdim, type,
653                             &(((int64_t*)targetArray)[arrayStep(dimensions, i)]));
654                     }
655                     break;
656                 case OCREP_PROP_DOUBLE:
657                     if (dimensions[1] == 0)
658                     {
659                         double *d = &(((double*)targetArray)[i]);
660                         if (cbor_value_get_type(&insideArray) == CborDoubleType)
661                         {
662                             err = cbor_value_get_double(&insideArray, d);
663                         }
664                         else
665                         {
666                             /* must be float */
667                             float f;
668                             err = cbor_value_get_float(&insideArray, &f);
669                             if (!err)
670                                 *d = f;
671                         }
672                     }
673                     else
674                     {
675                         err = OCParseArrayFillArray(&insideArray, newdim, type,
676                             &(((double*)targetArray)[arrayStep(dimensions, i)]));
677                     }
678                     break;
679                 case OCREP_PROP_BOOL:
680                     if (dimensions[1] == 0)
681                     {
682                         err = cbor_value_get_boolean(&insideArray, &(((bool*)targetArray)[i]));
683                     }
684                     else
685                     {
686                         err = OCParseArrayFillArray(&insideArray, newdim, type,
687                             &(((bool*)targetArray)[arrayStep(dimensions, i)]));
688                     }
689                     break;
690                 case OCREP_PROP_STRING:
691                     if (dimensions[1] == 0)
692                     {
693                         err = cbor_value_dup_text_string(&insideArray, &tempStr, &tempLen, NULL);
694                         ((char**)targetArray)[i] = tempStr;
695                         tempStr = NULL;
696                     }
697                     else
698                     {
699                         err = OCParseArrayFillArray(&insideArray, newdim, type,
700                             &(((char**)targetArray)[arrayStep(dimensions, i)]));
701                     }
702                     break;
703                 case OCREP_PROP_BYTE_STRING:
704                     if (dimensions[1] == 0)
705                     {
706                         err = cbor_value_dup_byte_string(&insideArray, &(ocByteStr.bytes),
707                                 &(ocByteStr.len), NULL);
708                         ((OCByteString*)targetArray)[i] = ocByteStr;
709                     }
710                     else
711                     {
712                         err = OCParseArrayFillArray(&insideArray, newdim, type,
713                                 &(((OCByteString*)targetArray)[arrayStep(dimensions, i)]));
714                     }
715                     break;
716                 case OCREP_PROP_OBJECT:
717                     if (dimensions[1] == 0)
718                     {
719                         err = OCParseSingleRepPayload(&tempPl, &insideArray, false);
720                         ((OCRepPayload**)targetArray)[i] = tempPl;
721                         tempPl = NULL;
722                         noAdvance = true;
723                     }
724                     else
725                     {
726                         err = OCParseArrayFillArray(&insideArray, newdim, type,
727                             &(((OCRepPayload**)targetArray)[arrayStep(dimensions, i)]));
728                     }
729                     break;
730                 default:
731                     OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
732                     err = CborErrorUnknownType;
733                     break;
734             }
735             VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting repPayload");
736         }
737         ++i;
738         if (!noAdvance && cbor_value_is_valid(&insideArray))
739         {
740             err = cbor_value_advance(&insideArray);
741             VERIFY_CBOR_SUCCESS(TAG, err, "Failed advnce insideArray");
742         }
743     }
744
745 exit:
746     return err;
747 }
748
749 static CborError OCParseArray(OCRepPayload *out, const char *name, CborValue *container)
750 {
751     void *arr = NULL;
752     OCRepPayloadPropType type;
753     size_t dimensions[MAX_REP_ARRAY_DEPTH];
754     size_t dimTotal = 0;
755     size_t allocSize = 0;
756     bool res = true;
757     CborError err = OCParseArrayFindDimensionsAndType(container, dimensions, &type);
758     VERIFY_CBOR_SUCCESS(TAG, err, "Array details weren't clear");
759
760     if (type == OCREP_PROP_NULL)
761     {
762         res = OCRepPayloadSetNull(out, name);
763         err = (CborError) !res;
764         VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
765         err = cbor_value_advance(container);
766         VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing container");
767         return err;
768     }
769
770     dimTotal = calcDimTotal(dimensions);
771     allocSize = getAllocSize(type);
772     arr = OICCalloc(dimTotal, allocSize);
773     VERIFY_PARAM_NON_NULL(TAG, arr, "Array Parse allocation failed");
774
775     res = OCParseArrayFillArray(container, dimensions, type, arr);
776     VERIFY_CBOR_SUCCESS(TAG, err, "Failed parse array");
777
778     switch (type)
779     {
780         case OCREP_PROP_INT:
781             res = OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t *)arr, dimensions);
782             break;
783         case OCREP_PROP_DOUBLE:
784             res = OCRepPayloadSetDoubleArrayAsOwner(out, name, (double *)arr, dimensions);
785             break;
786         case OCREP_PROP_BOOL:
787             res = OCRepPayloadSetBoolArrayAsOwner(out, name, (bool *)arr, dimensions);
788             break;
789         case OCREP_PROP_STRING:
790             res = OCRepPayloadSetStringArrayAsOwner(out, name, (char **)arr, dimensions);
791             break;
792         case OCREP_PROP_BYTE_STRING:
793             res = OCRepPayloadSetByteStringArrayAsOwner(out, name, (OCByteString *)arr, dimensions);
794             break;
795         case OCREP_PROP_OBJECT:
796             res = OCRepPayloadSetPropObjectArrayAsOwner(out, name, (OCRepPayload**)arr, dimensions);
797             break;
798         default:
799             OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
800             break;
801     }
802     err = (CborError) !res;
803     VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting array parameter");
804     return CborNoError;
805 exit:
806     if (type == OCREP_PROP_STRING)
807     {
808         for(size_t i = 0; i < dimTotal; ++i)
809         {
810             OICFree(((char**)arr)[i]);
811         }
812     }
813     if (type == OCREP_PROP_BYTE_STRING)
814     {
815         for(size_t i = 0; i < dimTotal; ++i)
816         {
817             OICFree(((OCByteString*)arr)[i].bytes);
818         }
819     }
820     if (type == OCREP_PROP_OBJECT)
821     {
822         for(size_t i = 0; i < dimTotal; ++i)
823         {
824             OCRepPayloadDestroy(((OCRepPayload**)arr)[i]);
825         }
826     }
827     OICFree(arr);
828     return err;
829 }
830
831 static CborError OCParseSingleRepPayload(OCRepPayload **outPayload, CborValue *objMap, bool isRoot)
832 {
833     CborError err = CborUnknownError;
834     char *name = NULL;
835     bool res = false;
836     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
837     VERIFY_PARAM_NON_NULL(TAG, objMap, "Invalid Parameter objMap");
838
839     if (cbor_value_is_map(objMap))
840     {
841         if (!*outPayload)
842         {
843             *outPayload = OCRepPayloadCreate();
844             if (!*outPayload)
845             {
846                 return CborErrorOutOfMemory;
847             }
848         }
849
850         OCRepPayload *curPayload = *outPayload;
851
852         size_t len = 0;
853         CborValue repMap;
854         err = cbor_value_enter_container(objMap, &repMap);
855         VERIFY_CBOR_SUCCESS(TAG, err, "Failed entering repMap");
856
857         while (!err && cbor_value_is_valid(&repMap))
858         {
859             if (cbor_value_is_text_string(&repMap))
860             {
861                 err = cbor_value_dup_text_string(&repMap, &name, &len, NULL);
862                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding tag name in the map");
863                 err = cbor_value_advance(&repMap);
864                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing rootMap");
865                 if (name &&
866                     isRoot &&
867                     ((0 == strcmp(OC_RSRVD_HREF, name)) ||
868                      (0 == strcmp(OC_RSRVD_RESOURCE_TYPE, name)) ||
869                     (0 == strcmp(OC_RSRVD_INTERFACE, name))))
870                 {
871                     err = cbor_value_advance(&repMap);
872                     OICFree(name);
873                     continue;
874                 }
875             }
876             CborType type = cbor_value_get_type(&repMap);
877             switch (type)
878             {
879                 case CborNullType:
880                     res = OCRepPayloadSetNull(curPayload, name);
881                     break;
882                 case CborIntegerType:
883                     {
884                         int64_t intval = 0;
885                         err = cbor_value_get_int64(&repMap, &intval);
886                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting int value");
887                         res = OCRepPayloadSetPropInt(curPayload, name, intval);
888                     }
889                     break;
890                 case CborDoubleType:
891                     {
892                         double doubleval = 0;
893                         err = cbor_value_get_double(&repMap, &doubleval);
894                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting double value");
895                         res = OCRepPayloadSetPropDouble(curPayload, name, doubleval);
896                     }
897                     break;
898                 case CborBooleanType:
899                     {
900                         bool boolval = false;
901                         err = cbor_value_get_boolean(&repMap, &boolval);
902                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting boolean value");
903                         res = OCRepPayloadSetPropBool(curPayload, name, boolval);
904                     }
905                     break;
906                 case CborTextStringType:
907                     {
908                         char *strval = NULL;
909                         err = cbor_value_dup_text_string(&repMap, &strval, &len, NULL);
910                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting string value");
911                         res = OCRepPayloadSetPropStringAsOwner(curPayload, name, strval);
912                     }
913                     break;
914                 case CborByteStringType:
915                     {
916                         uint8_t* bytestrval = NULL;
917                         err = cbor_value_dup_byte_string(&repMap, &bytestrval, &len, NULL);
918                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting byte string value");
919                         OCByteString tmp = {.bytes = bytestrval, .len = len};
920                         res = OCRepPayloadSetPropByteStringAsOwner(curPayload, name, &tmp);
921                     }
922                     break;
923                 case CborMapType:
924                     {
925                         OCRepPayload *pl = NULL;
926                         err = OCParseSingleRepPayload(&pl, &repMap, false);
927                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting parse single rep");
928                         res = OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl);
929                     }
930                     break;
931                 case CborArrayType:
932                     err = OCParseArray(curPayload, name, &repMap);
933                     break;
934                 default:
935                     OIC_LOG_V(ERROR, TAG, "Parsing rep property, unknown type %d", repMap.type);
936                     res = false;
937             }
938             if (type != CborArrayType)
939             {
940                 err = (CborError) !res;
941             }
942             VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
943
944             if (type != CborMapType && cbor_value_is_valid(&repMap))
945             {
946                 err = cbor_value_advance(&repMap);
947                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advance repMap");
948             }
949             OICFree(name);
950             name = NULL;
951         }
952         if (cbor_value_is_container(objMap))
953         {
954             err = cbor_value_leave_container(objMap, &repMap);
955             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to leave container");
956         }
957         return err;
958     }
959
960 exit:
961     OICFree(name);
962     OCRepPayloadDestroy(*outPayload);
963     *outPayload = NULL;
964     return err;
965 }
966
967 static OCStackResult OCParseRepPayload(OCPayload **outPayload, CborValue *root)
968 {
969     OCStackResult ret = OC_STACK_INVALID_PARAM;
970     CborError err;
971     OCRepPayload *temp = NULL;
972     OCRepPayload *rootPayload = NULL;
973     OCRepPayload *curPayload = NULL;
974     CborValue rootMap = *root;
975     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
976     VERIFY_PARAM_NON_NULL(TAG, root, "Invalid Parameter root");
977
978     *outPayload = NULL;
979     if (cbor_value_is_array(root))
980     {
981         err = cbor_value_enter_container(root, &rootMap);
982     }
983     while (cbor_value_is_valid(&rootMap))
984     {
985         temp = OCRepPayloadCreate();
986         ret = OC_STACK_NO_MEMORY;
987         VERIFY_PARAM_NON_NULL(TAG, temp, "Failed allocating memory");
988
989         CborValue curVal;
990         ret = OC_STACK_MALFORMED_RESPONSE;
991
992         if (cbor_value_is_map(&rootMap))
993         {
994             err = cbor_value_map_find_value(&rootMap, OC_RSRVD_HREF, &curVal);
995             if (cbor_value_is_valid(&curVal))
996             {
997                 size_t len = 0;
998                 err = cbor_value_dup_text_string(&curVal, &temp->uri, &len, NULL);
999                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find uri");
1000             }
1001         }
1002         // Resource types
1003         if (cbor_value_is_map(&rootMap))
1004         {
1005             if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal))
1006             {
1007                 err =  OCParseStringLL(&rootMap, OC_RSRVD_RESOURCE_TYPE, &temp->types);
1008                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find rt type tag/value");
1009             }
1010         }
1011
1012         // Interface Types
1013         if (cbor_value_is_map(&rootMap))
1014         {
1015             if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_INTERFACE, &curVal))
1016             {
1017                 err =  OCParseStringLL(&rootMap, OC_RSRVD_INTERFACE, &temp->interfaces);
1018                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
1019             }
1020         }
1021
1022         if (cbor_value_is_map(&rootMap))
1023         {
1024             err = OCParseSingleRepPayload(&temp, &rootMap, true);
1025             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse single rep payload");
1026         }
1027         if(rootPayload == NULL)
1028         {
1029             rootPayload = temp;
1030             curPayload = temp;
1031         }
1032         else
1033         {
1034             curPayload->next = temp;
1035             curPayload = curPayload->next;
1036         }
1037
1038         if (cbor_value_is_array(&rootMap))
1039         {
1040             err = cbor_value_advance(&rootMap);
1041             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance single rep payload");
1042         }
1043     }
1044     *outPayload = (OCPayload *)rootPayload;
1045     return OC_STACK_OK;
1046
1047 exit:
1048     OCRepPayloadDestroy(temp);
1049     OCRepPayloadDestroy(rootPayload);
1050     OIC_LOG(ERROR, TAG, "CBOR error in ParseRepPayload");
1051     return ret;
1052 }
1053
1054 static OCStackResult OCParsePresencePayload(OCPayload **outPayload, CborValue *rootValue)
1055 {
1056     OCStackResult ret = OC_STACK_INVALID_PARAM;
1057     OCPresencePayload *payload = NULL;
1058     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
1059
1060     *outPayload = NULL;
1061
1062     payload = (OCPresencePayload *)OICCalloc(1, sizeof(OCPresencePayload));
1063     ret = OC_STACK_NO_MEMORY;
1064     VERIFY_PARAM_NON_NULL(TAG, payload, "Failed allocating presence payload");
1065     payload->base.type = PAYLOAD_TYPE_PRESENCE;
1066     ret = OC_STACK_MALFORMED_RESPONSE;
1067
1068     if (cbor_value_is_map(rootValue))
1069     {
1070         CborValue curVal;
1071
1072         // Sequence Number
1073         CborError err = cbor_value_map_find_value(rootValue, OC_RSRVD_NONCE, &curVal);
1074         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce tag");
1075         err = cbor_value_get_uint64(&curVal, (uint64_t *)&payload->sequenceNumber);
1076         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce value");
1077
1078         // Max Age
1079         err = cbor_value_map_find_value(rootValue, OC_RSRVD_TTL, &curVal);
1080         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl tag");
1081         err = cbor_value_get_uint64(&curVal, (uint64_t *)&payload->maxAge);
1082         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl value");
1083
1084         // Trigger
1085         err = cbor_value_map_find_value(rootValue, OC_RSRVD_TRIGGER, &curVal);
1086         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger tag");
1087         err = cbor_value_get_simple_type(&curVal, (uint8_t *)&payload->trigger);
1088         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger value");
1089
1090         // Resource type name
1091         err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
1092         if (cbor_value_is_valid(&curVal))
1093         {
1094             size_t len = 0;
1095             err = cbor_value_dup_text_string(&curVal, &payload->resourceType, &len, NULL);
1096             VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding resource type value");
1097         }
1098
1099         err = cbor_value_advance(rootValue);
1100         VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing root value");
1101
1102         *outPayload = (OCPayload *)payload;
1103         return OC_STACK_OK;
1104     }
1105 exit:
1106     OIC_LOG(ERROR, TAG, "CBOR error Parse Presence Payload");
1107     OCPresencePayloadDestroy(payload);
1108     return ret;
1109 }