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