[IOT-921]Return correct resource type in /oic/d
[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             return OCREP_PROP_DOUBLE;
513         case CborBooleanType:
514             return OCREP_PROP_BOOL;
515         case CborTextStringType:
516             return OCREP_PROP_STRING;
517         case CborByteStringType:
518             return OCREP_PROP_BYTE_STRING;
519         case CborMapType:
520             return OCREP_PROP_OBJECT;
521         case CborArrayType:
522             return OCREP_PROP_ARRAY;
523         default:
524             return OCREP_PROP_NULL;
525     }
526 }
527 static CborError OCParseArrayFindDimensionsAndType(const CborValue *parent,
528         size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType *type)
529 {
530     CborValue insideArray;
531     *type = OCREP_PROP_NULL;
532     dimensions[0] = dimensions[1] = dimensions[2] = 0;
533
534     CborError err = cbor_value_enter_container(parent, &insideArray);
535     VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
536
537     while (cbor_value_is_valid(&insideArray))
538     {
539         OCRepPayloadPropType tempType = DecodeCborType(cbor_value_get_type(&insideArray));
540
541         if (tempType == OCREP_PROP_ARRAY)
542         {
543             size_t subdim[MAX_REP_ARRAY_DEPTH];
544             tempType = OCREP_PROP_NULL;
545             err = OCParseArrayFindDimensionsAndType(&insideArray, subdim, &tempType);
546             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse array");
547
548             if (subdim[2] != 0)
549             {
550                 OIC_LOG(ERROR, TAG, "Parse array helper, sub-array too deep");
551             }
552
553             dimensions[1] = dimensions[1] >= subdim[0] ? dimensions[1] : subdim[0];
554             dimensions[2] = dimensions[2] >= subdim[1] ? dimensions[2] : subdim[1];
555
556             if (*type != OCREP_PROP_NULL && tempType != OCREP_PROP_NULL && *type != tempType)
557             {
558                 OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed (subtype)");
559                 return CborUnknownError;
560             }
561             else if (*type == OCREP_PROP_NULL)
562             {
563                 // We don't know the type of this array yet, so the assignment is OK
564                 *type = tempType;
565             }
566         }
567         else if (*type == OCREP_PROP_NULL)
568         {
569             // We don't know the type of this array yet, so the assignment is OK
570             *type = tempType;
571         }
572         // tempType is allowed to be NULL, since it might now know the answer yet
573         else if (tempType != OCREP_PROP_NULL && *type != tempType)
574         {
575             // this is an invalid situation!
576             OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed");
577             return CborUnknownError;
578         }
579
580         ++dimensions[0];
581         err = cbor_value_advance(&insideArray);
582         VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance array");
583     }
584
585 exit:
586     return err;
587 }
588
589 static size_t getAllocSize(OCRepPayloadPropType type)
590 {
591     switch (type)
592     {
593         case OCREP_PROP_INT:
594             return sizeof (int64_t);
595         case OCREP_PROP_DOUBLE:
596             return sizeof (double);
597         case OCREP_PROP_BOOL:
598             return sizeof (bool);
599         case OCREP_PROP_STRING:
600             return sizeof (char*);
601         case OCREP_PROP_BYTE_STRING:
602             return sizeof (OCByteString);
603         case OCREP_PROP_OBJECT:
604             return sizeof (OCRepPayload*);
605         default:
606             return 0;
607     }
608 }
609
610 static size_t arrayStep(size_t dimensions[MAX_REP_ARRAY_DEPTH], size_t elementNum)
611 {
612     return
613         (dimensions[1] == 0 ? 1 : dimensions[1]) *
614         (dimensions[2] == 0 ? 1 : dimensions[2]) *
615         elementNum;
616 }
617
618 static CborError OCParseArrayFillArray(const CborValue *parent,
619         size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType type, void *targetArray)
620 {
621     CborValue insideArray;
622
623     size_t i = 0;
624     char *tempStr = NULL;
625     OCByteString ocByteStr = { .bytes = NULL, .len = 0};
626     size_t tempLen = 0;
627     OCRepPayload *tempPl = NULL;
628
629     size_t newdim[MAX_REP_ARRAY_DEPTH];
630     newdim[0] = dimensions[1];
631     newdim[1] = dimensions[2];
632     newdim[2] = 0;
633
634     CborError err = cbor_value_enter_container(parent, &insideArray);
635     VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
636
637     while (!err && i < dimensions[0] && cbor_value_is_valid(&insideArray))
638     {
639         bool noAdvance = false;
640         if (cbor_value_get_type(&insideArray) != CborNullType)
641         {
642             switch (type)
643             {
644                 case OCREP_PROP_INT:
645                     if (dimensions[1] == 0)
646                     {
647                         err = cbor_value_get_int64(&insideArray, &(((int64_t*)targetArray)[i]));
648                     }
649                     else
650                     {
651                         err = OCParseArrayFillArray(&insideArray, newdim, type,
652                             &(((int64_t*)targetArray)[arrayStep(dimensions, i)]));
653                     }
654                     break;
655                 case OCREP_PROP_DOUBLE:
656                     if (dimensions[1] == 0)
657                     {
658                         err = cbor_value_get_double(&insideArray, &(((double*)targetArray)[i]));
659                     }
660                     else
661                     {
662                         err = OCParseArrayFillArray(&insideArray, newdim, type,
663                             &(((double*)targetArray)[arrayStep(dimensions, i)]));
664                     }
665                     break;
666                 case OCREP_PROP_BOOL:
667                     if (dimensions[1] == 0)
668                     {
669                         err = cbor_value_get_boolean(&insideArray, &(((bool*)targetArray)[i]));
670                     }
671                     else
672                     {
673                         err = OCParseArrayFillArray(&insideArray, newdim, type,
674                             &(((bool*)targetArray)[arrayStep(dimensions, i)]));
675                     }
676                     break;
677                 case OCREP_PROP_STRING:
678                     if (dimensions[1] == 0)
679                     {
680                         err = cbor_value_dup_text_string(&insideArray, &tempStr, &tempLen, NULL);
681                         ((char**)targetArray)[i] = tempStr;
682                         tempStr = NULL;
683                     }
684                     else
685                     {
686                         err = OCParseArrayFillArray(&insideArray, newdim, type,
687                             &(((char**)targetArray)[arrayStep(dimensions, i)]));
688                     }
689                     break;
690                 case OCREP_PROP_BYTE_STRING:
691                     if (dimensions[1] == 0)
692                     {
693                         err = cbor_value_dup_byte_string(&insideArray, &(ocByteStr.bytes),
694                                 &(ocByteStr.len), NULL);
695                         ((OCByteString*)targetArray)[i] = ocByteStr;
696                     }
697                     else
698                     {
699                         err = OCParseArrayFillArray(&insideArray, newdim, type,
700                                 &(((OCByteString*)targetArray)[arrayStep(dimensions, i)]));
701                     }
702                     break;
703                 case OCREP_PROP_OBJECT:
704                     if (dimensions[1] == 0)
705                     {
706                         err = OCParseSingleRepPayload(&tempPl, &insideArray, false);
707                         ((OCRepPayload**)targetArray)[i] = tempPl;
708                         tempPl = NULL;
709                         noAdvance = true;
710                     }
711                     else
712                     {
713                         err = OCParseArrayFillArray(&insideArray, newdim, type,
714                             &(((OCRepPayload**)targetArray)[arrayStep(dimensions, i)]));
715                     }
716                     break;
717                 default:
718                     OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
719                     err = CborErrorUnknownType;
720                     break;
721             }
722             VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting repPayload");
723         }
724         ++i;
725         if (!noAdvance && cbor_value_is_valid(&insideArray))
726         {
727             err = cbor_value_advance(&insideArray);
728             VERIFY_CBOR_SUCCESS(TAG, err, "Failed advnce insideArray");
729         }
730     }
731
732 exit:
733     return err;
734 }
735
736 static CborError OCParseArray(OCRepPayload *out, const char *name, CborValue *container)
737 {
738     void *arr = NULL;
739     OCRepPayloadPropType type;
740     size_t dimensions[MAX_REP_ARRAY_DEPTH];
741     size_t dimTotal = 0;
742     size_t allocSize = 0;
743     bool res = true;
744     CborError err = OCParseArrayFindDimensionsAndType(container, dimensions, &type);
745     VERIFY_CBOR_SUCCESS(TAG, err, "Array details weren't clear");
746
747     if (type == OCREP_PROP_NULL)
748     {
749         res = OCRepPayloadSetNull(out, name);
750         err = (CborError) !res;
751         VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
752         err = cbor_value_advance(container);
753         VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing container");
754         return err;
755     }
756
757     dimTotal = calcDimTotal(dimensions);
758     allocSize = getAllocSize(type);
759     arr = OICCalloc(dimTotal, allocSize);
760     VERIFY_PARAM_NON_NULL(TAG, arr, "Array Parse allocation failed");
761
762     res = OCParseArrayFillArray(container, dimensions, type, arr);
763     VERIFY_CBOR_SUCCESS(TAG, err, "Failed parse array");
764
765     switch (type)
766     {
767         case OCREP_PROP_INT:
768             res = OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t *)arr, dimensions);
769             break;
770         case OCREP_PROP_DOUBLE:
771             res = OCRepPayloadSetDoubleArrayAsOwner(out, name, (double *)arr, dimensions);
772             break;
773         case OCREP_PROP_BOOL:
774             res = OCRepPayloadSetBoolArrayAsOwner(out, name, (bool *)arr, dimensions);
775             break;
776         case OCREP_PROP_STRING:
777             res = OCRepPayloadSetStringArrayAsOwner(out, name, (char **)arr, dimensions);
778             break;
779         case OCREP_PROP_BYTE_STRING:
780             res = OCRepPayloadSetByteStringArrayAsOwner(out, name, (OCByteString *)arr, dimensions);
781             break;
782         case OCREP_PROP_OBJECT:
783             res = OCRepPayloadSetPropObjectArrayAsOwner(out, name, (OCRepPayload**)arr, dimensions);
784             break;
785         default:
786             OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
787             break;
788     }
789     err = (CborError) !res;
790     VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting array parameter");
791     return CborNoError;
792 exit:
793     if (type == OCREP_PROP_STRING)
794     {
795         for(size_t i = 0; i < dimTotal; ++i)
796         {
797             OICFree(((char**)arr)[i]);
798         }
799     }
800     if (type == OCREP_PROP_BYTE_STRING)
801     {
802         for(size_t i = 0; i < dimTotal; ++i)
803         {
804             OICFree(((OCByteString*)arr)[i].bytes);
805         }
806     }
807     if (type == OCREP_PROP_OBJECT)
808     {
809         for(size_t i = 0; i < dimTotal; ++i)
810         {
811             OCRepPayloadDestroy(((OCRepPayload**)arr)[i]);
812         }
813     }
814     OICFree(arr);
815     return err;
816 }
817
818 static CborError OCParseSingleRepPayload(OCRepPayload **outPayload, CborValue *objMap, bool isRoot)
819 {
820     CborError err = CborUnknownError;
821     char *name = NULL;
822     bool res = false;
823     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
824     VERIFY_PARAM_NON_NULL(TAG, objMap, "Invalid Parameter objMap");
825
826     if (cbor_value_is_map(objMap))
827     {
828         if (!*outPayload)
829         {
830             *outPayload = OCRepPayloadCreate();
831             if (!*outPayload)
832             {
833                 return CborErrorOutOfMemory;
834             }
835         }
836
837         OCRepPayload *curPayload = *outPayload;
838
839         size_t len = 0;
840         CborValue repMap;
841         err = cbor_value_enter_container(objMap, &repMap);
842         VERIFY_CBOR_SUCCESS(TAG, err, "Failed entering repMap");
843
844         while (!err && cbor_value_is_valid(&repMap))
845         {
846             if (cbor_value_is_text_string(&repMap))
847             {
848                 err = cbor_value_dup_text_string(&repMap, &name, &len, NULL);
849                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding tag name in the map");
850                 err = cbor_value_advance(&repMap);
851                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing rootMap");
852                 if (name &&
853                     isRoot &&
854                     ((0 == strcmp(OC_RSRVD_HREF, name)) ||
855                      (0 == strcmp(OC_RSRVD_RESOURCE_TYPE, name)) ||
856                     (0 == strcmp(OC_RSRVD_INTERFACE, name))))
857                 {
858                     err = cbor_value_advance(&repMap);
859                     OICFree(name);
860                     continue;
861                 }
862             }
863             CborType type = cbor_value_get_type(&repMap);
864             switch (type)
865             {
866                 case CborNullType:
867                     res = OCRepPayloadSetNull(curPayload, name);
868                     break;
869                 case CborIntegerType:
870                     {
871                         int64_t intval = 0;
872                         err = cbor_value_get_int64(&repMap, &intval);
873                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting int value");
874                         res = OCRepPayloadSetPropInt(curPayload, name, intval);
875                     }
876                     break;
877                 case CborDoubleType:
878                     {
879                         double doubleval = 0;
880                         err = cbor_value_get_double(&repMap, &doubleval);
881                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting double value");
882                         res = OCRepPayloadSetPropDouble(curPayload, name, doubleval);
883                     }
884                     break;
885                 case CborBooleanType:
886                     {
887                         bool boolval = false;
888                         err = cbor_value_get_boolean(&repMap, &boolval);
889                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting boolean value");
890                         res = OCRepPayloadSetPropBool(curPayload, name, boolval);
891                     }
892                     break;
893                 case CborTextStringType:
894                     {
895                         char *strval = NULL;
896                         err = cbor_value_dup_text_string(&repMap, &strval, &len, NULL);
897                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting string value");
898                         res = OCRepPayloadSetPropStringAsOwner(curPayload, name, strval);
899                     }
900                     break;
901                 case CborByteStringType:
902                     {
903                         uint8_t* bytestrval = NULL;
904                         err = cbor_value_dup_byte_string(&repMap, &bytestrval, &len, NULL);
905                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting byte string value");
906                         OCByteString tmp = {.bytes = bytestrval, .len = len};
907                         res = OCRepPayloadSetPropByteStringAsOwner(curPayload, name, &tmp);
908                     }
909                     break;
910                 case CborMapType:
911                     {
912                         OCRepPayload *pl = NULL;
913                         err = OCParseSingleRepPayload(&pl, &repMap, false);
914                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting parse single rep");
915                         res = OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl);
916                     }
917                     break;
918                 case CborArrayType:
919                     err = OCParseArray(curPayload, name, &repMap);
920                     break;
921                 default:
922                     OIC_LOG_V(ERROR, TAG, "Parsing rep property, unknown type %d", repMap.type);
923                     res = false;
924             }
925             if (type != CborArrayType)
926             {
927                 err = (CborError) !res;
928             }
929             VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
930
931             if (type != CborMapType && cbor_value_is_valid(&repMap))
932             {
933                 err = cbor_value_advance(&repMap);
934                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advance repMap");
935             }
936             OICFree(name);
937             name = NULL;
938         }
939         if (cbor_value_is_container(objMap))
940         {
941             err = cbor_value_leave_container(objMap, &repMap);
942             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to leave container");
943         }
944         return err;
945     }
946
947 exit:
948     OICFree(name);
949     OCRepPayloadDestroy(*outPayload);
950     *outPayload = NULL;
951     return err;
952 }
953
954 static OCStackResult OCParseRepPayload(OCPayload **outPayload, CborValue *root)
955 {
956     OCStackResult ret = OC_STACK_INVALID_PARAM;
957     CborError err;
958     OCRepPayload *temp = NULL;
959     OCRepPayload *rootPayload = NULL;
960     OCRepPayload *curPayload = NULL;
961     CborValue rootMap = *root;
962     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
963     VERIFY_PARAM_NON_NULL(TAG, root, "Invalid Parameter root");
964
965     *outPayload = NULL;
966     if (cbor_value_is_array(root))
967     {
968         err = cbor_value_enter_container(root, &rootMap);
969     }
970     while (cbor_value_is_valid(&rootMap))
971     {
972         temp = OCRepPayloadCreate();
973         ret = OC_STACK_NO_MEMORY;
974         VERIFY_PARAM_NON_NULL(TAG, temp, "Failed allocating memory");
975
976         CborValue curVal;
977         ret = OC_STACK_MALFORMED_RESPONSE;
978
979         if (cbor_value_is_map(&rootMap))
980         {
981             err = cbor_value_map_find_value(&rootMap, OC_RSRVD_HREF, &curVal);
982             if (cbor_value_is_valid(&curVal))
983             {
984                 size_t len = 0;
985                 err = cbor_value_dup_text_string(&curVal, &temp->uri, &len, NULL);
986                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find uri");
987             }
988         }
989         // Resource types
990         if (cbor_value_is_map(&rootMap))
991         {
992             if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal))
993             {
994                 err =  OCParseStringLL(&rootMap, OC_RSRVD_RESOURCE_TYPE, &temp->types);
995                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find rt type tag/value");
996             }
997         }
998
999         // Interface Types
1000         if (cbor_value_is_map(&rootMap))
1001         {
1002             if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_INTERFACE, &curVal))
1003             {
1004                 err =  OCParseStringLL(&rootMap, OC_RSRVD_INTERFACE, &temp->interfaces);
1005                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
1006             }
1007         }
1008
1009         if (cbor_value_is_map(&rootMap))
1010         {
1011             err = OCParseSingleRepPayload(&temp, &rootMap, true);
1012             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse single rep payload");
1013         }
1014         if(rootPayload == NULL)
1015         {
1016             rootPayload = temp;
1017             curPayload = temp;
1018         }
1019         else
1020         {
1021             curPayload->next = temp;
1022             curPayload = curPayload->next;
1023         }
1024
1025         if (cbor_value_is_array(&rootMap))
1026         {
1027             err = cbor_value_advance(&rootMap);
1028             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance single rep payload");
1029         }
1030     }
1031     *outPayload = (OCPayload *)rootPayload;
1032     return OC_STACK_OK;
1033
1034 exit:
1035     OCRepPayloadDestroy(temp);
1036     OCRepPayloadDestroy(rootPayload);
1037     OIC_LOG(ERROR, TAG, "CBOR error in ParseRepPayload");
1038     return ret;
1039 }
1040
1041 static OCStackResult OCParsePresencePayload(OCPayload **outPayload, CborValue *rootValue)
1042 {
1043     OCStackResult ret = OC_STACK_INVALID_PARAM;
1044     OCPresencePayload *payload = NULL;
1045     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
1046
1047     *outPayload = NULL;
1048
1049     payload = (OCPresencePayload *)OICCalloc(1, sizeof(OCPresencePayload));
1050     ret = OC_STACK_NO_MEMORY;
1051     VERIFY_PARAM_NON_NULL(TAG, payload, "Failed allocating presence payload");
1052     payload->base.type = PAYLOAD_TYPE_PRESENCE;
1053     ret = OC_STACK_MALFORMED_RESPONSE;
1054
1055     if (cbor_value_is_map(rootValue))
1056     {
1057         CborValue curVal;
1058
1059         // Sequence Number
1060         CborError err = cbor_value_map_find_value(rootValue, OC_RSRVD_NONCE, &curVal);
1061         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce tag");
1062         err = cbor_value_get_uint64(&curVal, (uint64_t *)&payload->sequenceNumber);
1063         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce value");
1064
1065         // Max Age
1066         err = cbor_value_map_find_value(rootValue, OC_RSRVD_TTL, &curVal);
1067         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl tag");
1068         err = cbor_value_get_uint64(&curVal, (uint64_t *)&payload->maxAge);
1069         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl value");
1070
1071         // Trigger
1072         err = cbor_value_map_find_value(rootValue, OC_RSRVD_TRIGGER, &curVal);
1073         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger tag");
1074         err = cbor_value_get_simple_type(&curVal, (uint8_t *)&payload->trigger);
1075         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger value");
1076
1077         // Resource type name
1078         err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
1079         if (cbor_value_is_valid(&curVal))
1080         {
1081             size_t len = 0;
1082             err = cbor_value_dup_text_string(&curVal, &payload->resourceType, &len, NULL);
1083             VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding resource type value");
1084         }
1085
1086         err = cbor_value_advance(rootValue);
1087         VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing root value");
1088
1089         *outPayload = (OCPayload *)payload;
1090         return OC_STACK_OK;
1091     }
1092 exit:
1093     OIC_LOG(ERROR, TAG, "CBOR error Parse Presence Payload");
1094     OCPresencePayloadDestroy(payload);
1095     return ret;
1096 }