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