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