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