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