[IOT-995] Fix memory reallocation for security resources
[platform/upstream/iotivity.git] / resource / csdk / stack / src / ocpayloadparse.c
1 //******************************************************************
2 //
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 // Defining _POSIX_C_SOURCE macro with 200112L (or greater) as value
22 // causes header files to expose definitions
23 // corresponding to the POSIX.1-2001 base
24 // specification (excluding the XSI extension).
25 // For POSIX.1-2001 base specification,
26 // Refer http://pubs.opengroup.org/onlinepubs/009695399/
27 // Required for strok_r
28 #define _POSIX_C_SOURCE 200112L
29 #include <string.h>
30 #include <stdlib.h>
31 #include "oic_string.h"
32 #include "oic_malloc.h"
33 #include "ocpayload.h"
34 #include "ocpayloadcbor.h"
35 #include "ocstackinternal.h"
36 #include "payload_logging.h"
37 #include "rdpayload.h"
38
39 #define TAG "OIC_RI_PAYLOADPARSE"
40
41 static OCStackResult OCParseDiscoveryPayload(OCPayload **outPayload, CborValue *arrayVal);
42 static OCStackResult OCParseDevicePayload(OCPayload **outPayload, CborValue *arrayVal);
43 static OCStackResult OCParsePlatformPayload(OCPayload **outPayload, CborValue *arrayVal);
44 static CborError OCParseSingleRepPayload(OCRepPayload **outPayload, CborValue *repParent, bool isRoot);
45 static OCStackResult OCParseRepPayload(OCPayload **outPayload, CborValue *arrayVal);
46 static OCStackResult OCParsePresencePayload(OCPayload **outPayload, CborValue *arrayVal);
47 static OCStackResult OCParseSecurityPayload(OCPayload **outPayload, const uint8_t *payload, size_t size);
48
49 OCStackResult OCParsePayload(OCPayload **outPayload, OCPayloadType payloadType,
50         const uint8_t *payload, size_t payloadSize)
51 {
52     OCStackResult result = OC_STACK_MALFORMED_RESPONSE;
53     CborError err;
54
55     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Conversion of outPayload failed");
56     VERIFY_PARAM_NON_NULL(TAG, payload, "Invalid cbor payload value");
57
58     OIC_LOG_V(INFO, TAG, "CBOR Parsing size: %zu of Payload Type: %d, Payload:",
59             payloadSize, payloadType);
60     OIC_LOG_BUFFER(DEBUG, TAG, payload, payloadSize);
61
62     CborParser parser;
63     CborValue rootValue;
64
65     err = cbor_parser_init(payload, payloadSize, 0, &parser, &rootValue);
66     VERIFY_CBOR_SUCCESS(TAG, err, "Failed initializing init value")
67
68     switch(payloadType)
69     {
70         case PAYLOAD_TYPE_DISCOVERY:
71             result = OCParseDiscoveryPayload(outPayload, &rootValue);
72             break;
73         case PAYLOAD_TYPE_DEVICE:
74             result = OCParseDevicePayload(outPayload, &rootValue);
75             break;
76         case PAYLOAD_TYPE_PLATFORM:
77             result = OCParsePlatformPayload(outPayload, &rootValue);
78             break;
79         case PAYLOAD_TYPE_REPRESENTATION:
80             result = OCParseRepPayload(outPayload, &rootValue);
81             break;
82         case PAYLOAD_TYPE_PRESENCE:
83             result = OCParsePresencePayload(outPayload, &rootValue);
84             break;
85         case PAYLOAD_TYPE_SECURITY:
86             result = OCParseSecurityPayload(outPayload, payload, payloadSize);
87             break;
88         case PAYLOAD_TYPE_RD:
89             result = OCRDCborToPayload(&rootValue, outPayload);
90             break;
91         default:
92             OIC_LOG_V(ERROR, TAG, "ParsePayload Type default: %d", payloadType);
93             result = OC_STACK_INVALID_PARAM;
94             break;
95     }
96
97     OIC_LOG_V(INFO, TAG, "Finished parse payload, result is %d", result);
98
99 exit:
100     return result;
101 }
102
103 void OCFreeOCStringLL(OCStringLL* ll);
104
105 static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, const uint8_t *payload,
106         size_t size)
107 {
108     if (size > 0)
109     {
110         *outPayload = (OCPayload *)OCSecurityPayloadCBORCreate(payload, size);
111     }
112     else
113     {
114         *outPayload = NULL;
115     }
116     return OC_STACK_OK;
117 }
118
119 static char* InPlaceStringTrim(char* str)
120 {
121     while (str[0] == ' ')
122     {
123         ++str;
124     }
125
126     size_t lastchar = strlen(str);
127
128     while (str[lastchar] == ' ')
129     {
130         str[lastchar] = '\0';
131         --lastchar;
132     }
133
134     return str;
135 }
136
137 static CborError OCParseStringLL(CborValue *map, char *type, OCStringLL **resource)
138 {
139     CborValue val;
140     CborError err = cbor_value_map_find_value(map, type, &val);
141     VERIFY_CBOR_SUCCESS(TAG, err, "to find StringLL TAG");
142
143     if (cbor_value_is_text_string(&val))
144     {
145         char *input = NULL;
146         char *savePtr = NULL;
147         size_t len = 0;
148
149         err = cbor_value_dup_text_string(&val, &input, &len, NULL);
150         VERIFY_CBOR_SUCCESS(TAG, err, "to find StringLL value");
151
152         if (input)
153         {
154             char *curPtr = strtok_r(input, " ", &savePtr);
155             while (curPtr)
156             {
157                 char *trimmed = InPlaceStringTrim(curPtr);
158                 if (trimmed[0] !='\0')
159                 {
160                     if (!OCResourcePayloadAddStringLL(resource, trimmed))
161                     {
162                         return CborErrorOutOfMemory;
163                     }
164                 }
165                 curPtr = strtok_r(NULL, " ", &savePtr);
166             }
167             OICFree(input);
168         }
169     }
170 exit:
171     return err;
172 }
173
174 static OCStackResult OCParseDiscoveryPayload(OCPayload **outPayload, CborValue *rootValue)
175 {
176     OCStackResult ret = OC_STACK_INVALID_PARAM;
177     OCResourcePayload *resource = NULL;
178     OCDiscoveryPayload *out = NULL;
179     size_t len = 0;
180     CborError err = CborNoError;
181     *outPayload = NULL;
182
183     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
184     VERIFY_PARAM_NON_NULL(TAG, rootValue, "Invalid Parameter rootValue");
185
186     // Root value is already inside the main root array
187     CborValue rootMap;
188     ret = OC_STACK_NO_MEMORY;
189     out = OCDiscoveryPayloadCreate();
190     VERIFY_PARAM_NON_NULL(TAG, out, "Failed error initializing discovery payload");
191
192     // Enter the main root map
193     ret = OC_STACK_MALFORMED_RESPONSE;
194     err = cbor_value_enter_container(rootValue, &rootMap);
195     VERIFY_CBOR_SUCCESS(TAG, err, "to enter root map container");
196
197     // Look for DI
198     CborValue curVal;
199     err = cbor_value_map_find_value(&rootMap, OC_RSRVD_DEVICE_ID, &curVal);
200     VERIFY_CBOR_SUCCESS(TAG, err, "to find device id tag");
201     if (cbor_value_is_valid(&curVal))
202     {
203         if (cbor_value_is_byte_string(&curVal))
204         {
205             err = cbor_value_dup_byte_string(&curVal, (uint8_t **)&(out->sid), &len, NULL);
206             VERIFY_CBOR_SUCCESS(TAG, err, "to copy device id value");
207         }
208         else if (cbor_value_is_text_string(&curVal))
209         {
210             err = cbor_value_dup_text_string(&curVal, &(out->sid), &len, NULL);
211             VERIFY_CBOR_SUCCESS(TAG, err, "to copy device id value");
212         }
213     }
214
215     // BaseURI - Not a mandatory field
216     err = cbor_value_map_find_value(&rootMap, OC_RSRVD_BASE_URI, &curVal);
217     if (cbor_value_is_valid(&curVal))
218     {
219         err = cbor_value_dup_text_string(&curVal, &(out->baseURI), &len, NULL);
220         VERIFY_CBOR_SUCCESS(TAG, err, "to find base uri value");
221     }
222
223     // Look for Links which will have an array as the value
224     CborValue linkMap;
225     err = cbor_value_map_find_value(&rootMap, OC_RSRVD_LINKS, &linkMap);
226     VERIFY_CBOR_SUCCESS(TAG, err, "to find links tag");
227
228     // Enter the links array and start iterating through the array processing
229     // each resource which shows up as a map.
230     CborValue resourceMap;
231     err = cbor_value_enter_container(&linkMap, &resourceMap);
232     VERIFY_CBOR_SUCCESS(TAG, err, "to enter link map");
233
234     while (cbor_value_is_map(&resourceMap))
235     {
236         resource = (OCResourcePayload *)OICCalloc(1, sizeof(OCResourcePayload));
237         VERIFY_PARAM_NON_NULL(TAG, resource, "Failed allocating resource payload");
238
239         // Uri
240         err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_HREF, &curVal);
241         VERIFY_CBOR_SUCCESS(TAG, err, "to find href tag");
242         err = cbor_value_dup_text_string(&curVal, &(resource->uri), &len, NULL);
243         VERIFY_CBOR_SUCCESS(TAG, err, "to find href value");
244
245         // ResourceTypes
246         err =  OCParseStringLL(&resourceMap, OC_RSRVD_RESOURCE_TYPE, &resource->types);
247         VERIFY_CBOR_SUCCESS(TAG, err, "to find resource type tag/value");
248
249         // Interface Types
250         err =  OCParseStringLL(&resourceMap, OC_RSRVD_INTERFACE, &resource->interfaces);
251         if (CborNoError != err)
252         {
253             if (!OCResourcePayloadAddStringLL(&resource->interfaces, OC_RSRVD_INTERFACE_LL))
254             {
255                 err = CborErrorOutOfMemory;
256             }
257         }
258
259         // Policy
260         CborValue policyMap;
261         err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_POLICY, &policyMap);
262         VERIFY_CBOR_SUCCESS(TAG, err, "to find policy tag");
263
264         // Bitmap
265         err = cbor_value_map_find_value(&policyMap, OC_RSRVD_BITMAP, &curVal);
266         VERIFY_CBOR_SUCCESS(TAG, err, "to find bitmap tag");
267         err = cbor_value_get_int(&curVal, (int *)&resource->bitmap);
268         VERIFY_CBOR_SUCCESS(TAG, err, "to find bitmap value");
269
270         // Secure Flag
271         err = cbor_value_map_find_value(&policyMap, OC_RSRVD_SECURE, &curVal);
272         if (cbor_value_is_valid(&curVal))
273         {
274             err = cbor_value_get_boolean(&curVal, &(resource->secure));
275             VERIFY_CBOR_SUCCESS(TAG, err, "to find secure value");
276         }
277
278         // Port
279         err = cbor_value_map_find_value(&policyMap, OC_RSRVD_HOSTING_PORT, &curVal);
280         if (cbor_value_is_valid(&curVal))
281         {
282             err = cbor_value_get_int(&curVal, (int *)&resource->port);
283             VERIFY_CBOR_SUCCESS(TAG, err, "to find port value");
284         }
285
286         err = cbor_value_advance(&resourceMap);
287         VERIFY_CBOR_SUCCESS(TAG, err, "to advance resource map");
288
289         OCDiscoveryPayloadAddNewResource(out, resource);
290     }
291
292     err = cbor_value_leave_container(rootValue, &resourceMap);
293     VERIFY_CBOR_SUCCESS(TAG, err, "to advance resource map");
294
295     *outPayload = (OCPayload *)out;
296     return OC_STACK_OK;
297
298 exit:
299     OCDiscoveryResourceDestroy(resource);
300     OCDiscoveryPayloadDestroy(out);
301     return ret;
302 }
303
304 static OCStackResult OCParseDevicePayload(OCPayload **outPayload, CborValue *rootValue)
305 {
306     OCStackResult ret = OC_STACK_INVALID_PARAM;
307     CborError err = CborNoError;
308     OCDevicePayload *out = NULL;
309     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid param outPayload");
310     VERIFY_PARAM_NON_NULL(TAG, rootValue, "Invalid param rootValue");
311
312     *outPayload = NULL;
313
314     out = (OCDevicePayload *)OICCalloc(1, sizeof(OCDevicePayload));
315     VERIFY_PARAM_NON_NULL(TAG, out, "Failed allocating device payload")
316     out->base.type = PAYLOAD_TYPE_DEVICE;
317     ret = OC_STACK_MALFORMED_RESPONSE;
318
319     if (cbor_value_is_map(rootValue))
320     {
321         CborValue curVal;
322         // Resource Type
323         err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
324         if (cbor_value_is_valid(&curVal))
325         {
326             err =  OCParseStringLL(rootValue, OC_RSRVD_RESOURCE_TYPE, &out->types);
327             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find rt type tag/value");
328         }
329         // Device ID
330         size_t len = 0;
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     char* rt = NULL;
384     OCStringLL* interfaces = NULL;
385     OCPlatformPayload* out = NULL;
386
387     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
388
389     if (cbor_value_is_map(rootValue))
390     {
391         CborValue repVal;
392         size_t len = 0;
393         ret = OC_STACK_MALFORMED_RESPONSE;
394
395         // Platform ID
396         err = cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_ID, &repVal);
397         if (cbor_value_is_valid(&repVal))
398         {
399             err = cbor_value_dup_text_string(&repVal, &(info.platformID), &len, NULL);
400             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find platformID in the platform payload");
401         }
402          // MFG Name
403         err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_NAME, &repVal);
404         if (cbor_value_is_valid(&repVal))
405         {
406             err = cbor_value_dup_text_string(&repVal, &(info.manufacturerName), &len, NULL);
407             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find manufactureName in the platform payload");
408         }
409         // MFG URL
410         err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_URL, &repVal);
411         if (cbor_value_is_valid(&repVal))
412         {
413             err = cbor_value_dup_text_string(&repVal, &(info.manufacturerUrl), &len, NULL);
414             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find manufactureUrl in the platform payload");
415         }
416         // Model Num
417         err = cbor_value_map_find_value(rootValue, OC_RSRVD_MODEL_NUM, &repVal);
418         if (cbor_value_is_valid(&repVal))
419         {
420             err = cbor_value_dup_text_string(&repVal, &(info.modelNumber), &len, NULL);
421             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find modelNumber in the platform payload");
422         }
423         // Date of Mfg
424         err = cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_DATE, &repVal);
425         if (cbor_value_is_valid(&repVal))
426         {
427             err = cbor_value_dup_text_string(&repVal, &(info.dateOfManufacture), &len, NULL);
428             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find dateOfManufacture in the platform payload");
429         }
430         // Platform Version
431         err = cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_VERSION, &repVal);
432         if (cbor_value_is_valid(&repVal))
433         {
434             err = cbor_value_dup_text_string(&repVal, &(info.platformVersion), &len, NULL);
435             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find platformVersion in the platform payload");
436         }
437         // OS Version
438         err = cbor_value_map_find_value(rootValue, OC_RSRVD_OS_VERSION, &repVal);
439         if (cbor_value_is_valid(&repVal))
440         {
441             err = cbor_value_dup_text_string(&repVal, &(info.operatingSystemVersion), &len, NULL);
442             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find OSVersion in the platform payload");
443         }
444         // Hardware Version
445         err = cbor_value_map_find_value(rootValue, OC_RSRVD_HARDWARE_VERSION, &repVal);
446         if(cbor_value_is_valid(&repVal))
447         {
448             err = cbor_value_dup_text_string(&repVal, &(info.hardwareVersion), &len, NULL);
449             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find HWVersion in the platform payload");
450         }
451         // Firmware Version
452         err = cbor_value_map_find_value(rootValue, OC_RSRVD_FIRMWARE_VERSION, &repVal);
453         if(cbor_value_is_valid(&repVal))
454         {
455             err = cbor_value_dup_text_string(&repVal, &(info.firmwareVersion), &len, NULL);
456             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find firmwareVersion in the platform payload");
457         }
458         // Support URL
459         err = cbor_value_map_find_value(rootValue, OC_RSRVD_SUPPORT_URL, &repVal);
460         if(cbor_value_is_valid(&repVal))
461         {
462             err = cbor_value_dup_text_string(&repVal, &(info.supportUrl), &len, NULL);
463             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find supportUrl in the platform payload");
464         }
465         // System Time
466         err = cbor_value_map_find_value(rootValue, OC_RSRVD_SYSTEM_TIME, &repVal);
467         if(cbor_value_is_valid(&repVal))
468         {
469             err = cbor_value_dup_text_string(&repVal, &(info.systemTime), &len, NULL);
470             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find systemTume in the platform payload");
471         }
472
473         // Resource type
474         err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &repVal);
475         if(cbor_value_is_valid(&repVal))
476         {
477             err = cbor_value_dup_text_string(&repVal, &rt, &len, NULL);
478             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find resource type in the platform payload");
479         }
480
481         // Interface Types
482         err = cbor_value_map_find_value(rootValue, OC_RSRVD_INTERFACE, &repVal);
483         if(cbor_value_is_valid(&repVal))
484         {
485             err =  OCParseStringLL(rootValue, OC_RSRVD_INTERFACE, &interfaces);
486             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
487         }
488
489         err = cbor_value_advance(rootValue);
490         VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find supportUrl in the platform payload");
491
492        out = (OCPlatformPayload *)OCPlatformPayloadCreateAsOwner(&info);
493        out->rt = rt;
494        out->interfaces = interfaces;
495        *outPayload = (OCPayload *)out;
496        return OC_STACK_OK;
497     }
498
499 exit:
500     OCPlatformInfoDestroy(&info);
501     OIC_LOG(ERROR, TAG, "CBOR error In ParsePlatformPayload");
502     return ret;
503 }
504
505 static OCRepPayloadPropType DecodeCborType(CborType type)
506 {
507     switch (type)
508     {
509         case CborNullType:
510             return OCREP_PROP_NULL;
511         case CborIntegerType:
512             return OCREP_PROP_INT;
513         case CborDoubleType:
514         case CborFloatType:
515             return OCREP_PROP_DOUBLE;
516         case CborBooleanType:
517             return OCREP_PROP_BOOL;
518         case CborTextStringType:
519             return OCREP_PROP_STRING;
520         case CborByteStringType:
521             return OCREP_PROP_BYTE_STRING;
522         case CborMapType:
523             return OCREP_PROP_OBJECT;
524         case CborArrayType:
525             return OCREP_PROP_ARRAY;
526         default:
527             return OCREP_PROP_NULL;
528     }
529 }
530 static CborError OCParseArrayFindDimensionsAndType(const CborValue *parent,
531         size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType *type)
532 {
533     CborValue insideArray;
534     *type = OCREP_PROP_NULL;
535     dimensions[0] = dimensions[1] = dimensions[2] = 0;
536
537     CborError err = cbor_value_enter_container(parent, &insideArray);
538     VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
539
540     while (cbor_value_is_valid(&insideArray))
541     {
542         OCRepPayloadPropType tempType = DecodeCborType(cbor_value_get_type(&insideArray));
543
544         if (tempType == OCREP_PROP_ARRAY)
545         {
546             size_t subdim[MAX_REP_ARRAY_DEPTH];
547             tempType = OCREP_PROP_NULL;
548             err = OCParseArrayFindDimensionsAndType(&insideArray, subdim, &tempType);
549             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse array");
550
551             if (subdim[2] != 0)
552             {
553                 OIC_LOG(ERROR, TAG, "Parse array helper, sub-array too deep");
554             }
555
556             dimensions[1] = dimensions[1] >= subdim[0] ? dimensions[1] : subdim[0];
557             dimensions[2] = dimensions[2] >= subdim[1] ? dimensions[2] : subdim[1];
558
559             if (*type != OCREP_PROP_NULL && tempType != OCREP_PROP_NULL && *type != tempType)
560             {
561                 OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed (subtype)");
562                 return CborUnknownError;
563             }
564             else if (*type == OCREP_PROP_NULL)
565             {
566                 // We don't know the type of this array yet, so the assignment is OK
567                 *type = tempType;
568             }
569         }
570         else if (*type == OCREP_PROP_NULL)
571         {
572             // We don't know the type of this array yet, so the assignment is OK
573             *type = tempType;
574         }
575         // tempType is allowed to be NULL, since it might now know the answer yet
576         else if (tempType != OCREP_PROP_NULL && *type != tempType)
577         {
578             // this is an invalid situation!
579             OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed");
580             return CborUnknownError;
581         }
582
583         ++dimensions[0];
584         err = cbor_value_advance(&insideArray);
585         VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance array");
586     }
587
588 exit:
589     return err;
590 }
591
592 static size_t getAllocSize(OCRepPayloadPropType type)
593 {
594     switch (type)
595     {
596         case OCREP_PROP_INT:
597             return sizeof (int64_t);
598         case OCREP_PROP_DOUBLE:
599             return sizeof (double);
600         case OCREP_PROP_BOOL:
601             return sizeof (bool);
602         case OCREP_PROP_STRING:
603             return sizeof (char*);
604         case OCREP_PROP_BYTE_STRING:
605             return sizeof (OCByteString);
606         case OCREP_PROP_OBJECT:
607             return sizeof (OCRepPayload*);
608         default:
609             return 0;
610     }
611 }
612
613 static size_t arrayStep(size_t dimensions[MAX_REP_ARRAY_DEPTH], size_t elementNum)
614 {
615     return
616         (dimensions[1] == 0 ? 1 : dimensions[1]) *
617         (dimensions[2] == 0 ? 1 : dimensions[2]) *
618         elementNum;
619 }
620
621 static CborError OCParseArrayFillArray(const CborValue *parent,
622         size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType type, void *targetArray)
623 {
624     CborValue insideArray;
625
626     size_t i = 0;
627     char *tempStr = NULL;
628     OCByteString ocByteStr = { .bytes = NULL, .len = 0};
629     size_t tempLen = 0;
630     OCRepPayload *tempPl = NULL;
631
632     size_t newdim[MAX_REP_ARRAY_DEPTH];
633     newdim[0] = dimensions[1];
634     newdim[1] = dimensions[2];
635     newdim[2] = 0;
636
637     CborError err = cbor_value_enter_container(parent, &insideArray);
638     VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
639
640     while (!err && i < dimensions[0] && cbor_value_is_valid(&insideArray))
641     {
642         bool noAdvance = false;
643         if (cbor_value_get_type(&insideArray) != CborNullType)
644         {
645             switch (type)
646             {
647                 case OCREP_PROP_INT:
648                     if (dimensions[1] == 0)
649                     {
650                         err = cbor_value_get_int64(&insideArray, &(((int64_t*)targetArray)[i]));
651                     }
652                     else
653                     {
654                         err = OCParseArrayFillArray(&insideArray, newdim, type,
655                             &(((int64_t*)targetArray)[arrayStep(dimensions, i)]));
656                     }
657                     break;
658                 case OCREP_PROP_DOUBLE:
659                     if (dimensions[1] == 0)
660                     {
661                         double *d = &(((double*)targetArray)[i]);
662                         if (cbor_value_get_type(&insideArray) == CborDoubleType)
663                         {
664                             err = cbor_value_get_double(&insideArray, d);
665                         }
666                         else
667                         {
668                             /* must be float */
669                             float f;
670                             err = cbor_value_get_float(&insideArray, &f);
671                             if (!err)
672                                 *d = f;
673                         }
674                     }
675                     else
676                     {
677                         err = OCParseArrayFillArray(&insideArray, newdim, type,
678                             &(((double*)targetArray)[arrayStep(dimensions, i)]));
679                     }
680                     break;
681                 case OCREP_PROP_BOOL:
682                     if (dimensions[1] == 0)
683                     {
684                         err = cbor_value_get_boolean(&insideArray, &(((bool*)targetArray)[i]));
685                     }
686                     else
687                     {
688                         err = OCParseArrayFillArray(&insideArray, newdim, type,
689                             &(((bool*)targetArray)[arrayStep(dimensions, i)]));
690                     }
691                     break;
692                 case OCREP_PROP_STRING:
693                     if (dimensions[1] == 0)
694                     {
695                         err = cbor_value_dup_text_string(&insideArray, &tempStr, &tempLen, NULL);
696                         ((char**)targetArray)[i] = tempStr;
697                         tempStr = NULL;
698                     }
699                     else
700                     {
701                         err = OCParseArrayFillArray(&insideArray, newdim, type,
702                             &(((char**)targetArray)[arrayStep(dimensions, i)]));
703                     }
704                     break;
705                 case OCREP_PROP_BYTE_STRING:
706                     if (dimensions[1] == 0)
707                     {
708                         err = cbor_value_dup_byte_string(&insideArray, &(ocByteStr.bytes),
709                                 &(ocByteStr.len), NULL);
710                         ((OCByteString*)targetArray)[i] = ocByteStr;
711                     }
712                     else
713                     {
714                         err = OCParseArrayFillArray(&insideArray, newdim, type,
715                                 &(((OCByteString*)targetArray)[arrayStep(dimensions, i)]));
716                     }
717                     break;
718                 case OCREP_PROP_OBJECT:
719                     if (dimensions[1] == 0)
720                     {
721                         err = OCParseSingleRepPayload(&tempPl, &insideArray, false);
722                         ((OCRepPayload**)targetArray)[i] = tempPl;
723                         tempPl = NULL;
724                         noAdvance = true;
725                     }
726                     else
727                     {
728                         err = OCParseArrayFillArray(&insideArray, newdim, type,
729                             &(((OCRepPayload**)targetArray)[arrayStep(dimensions, i)]));
730                     }
731                     break;
732                 default:
733                     OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
734                     err = CborErrorUnknownType;
735                     break;
736             }
737             VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting repPayload");
738         }
739         ++i;
740         if (!noAdvance && cbor_value_is_valid(&insideArray))
741         {
742             err = cbor_value_advance(&insideArray);
743             VERIFY_CBOR_SUCCESS(TAG, err, "Failed advnce insideArray");
744         }
745     }
746
747 exit:
748     return err;
749 }
750
751 static CborError OCParseArray(OCRepPayload *out, const char *name, CborValue *container)
752 {
753     void *arr = NULL;
754     OCRepPayloadPropType type;
755     size_t dimensions[MAX_REP_ARRAY_DEPTH];
756     size_t dimTotal = 0;
757     size_t allocSize = 0;
758     bool res = true;
759     CborError err = OCParseArrayFindDimensionsAndType(container, dimensions, &type);
760     VERIFY_CBOR_SUCCESS(TAG, err, "Array details weren't clear");
761
762     if (type == OCREP_PROP_NULL)
763     {
764         res = OCRepPayloadSetNull(out, name);
765         err = (CborError) !res;
766         VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
767         err = cbor_value_advance(container);
768         VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing container");
769         return err;
770     }
771
772     dimTotal = calcDimTotal(dimensions);
773     allocSize = getAllocSize(type);
774     arr = OICCalloc(dimTotal, allocSize);
775     VERIFY_PARAM_NON_NULL(TAG, arr, "Array Parse allocation failed");
776
777     res = OCParseArrayFillArray(container, dimensions, type, arr);
778     VERIFY_CBOR_SUCCESS(TAG, err, "Failed parse array");
779
780     switch (type)
781     {
782         case OCREP_PROP_INT:
783             res = OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t *)arr, dimensions);
784             break;
785         case OCREP_PROP_DOUBLE:
786             res = OCRepPayloadSetDoubleArrayAsOwner(out, name, (double *)arr, dimensions);
787             break;
788         case OCREP_PROP_BOOL:
789             res = OCRepPayloadSetBoolArrayAsOwner(out, name, (bool *)arr, dimensions);
790             break;
791         case OCREP_PROP_STRING:
792             res = OCRepPayloadSetStringArrayAsOwner(out, name, (char **)arr, dimensions);
793             break;
794         case OCREP_PROP_BYTE_STRING:
795             res = OCRepPayloadSetByteStringArrayAsOwner(out, name, (OCByteString *)arr, dimensions);
796             break;
797         case OCREP_PROP_OBJECT:
798             res = OCRepPayloadSetPropObjectArrayAsOwner(out, name, (OCRepPayload**)arr, dimensions);
799             break;
800         default:
801             OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
802             break;
803     }
804     err = (CborError) !res;
805     VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting array parameter");
806     return CborNoError;
807 exit:
808     if (type == OCREP_PROP_STRING)
809     {
810         for(size_t i = 0; i < dimTotal; ++i)
811         {
812             OICFree(((char**)arr)[i]);
813         }
814     }
815     if (type == OCREP_PROP_BYTE_STRING)
816     {
817         for(size_t i = 0; i < dimTotal; ++i)
818         {
819             OICFree(((OCByteString*)arr)[i].bytes);
820         }
821     }
822     if (type == OCREP_PROP_OBJECT)
823     {
824         for(size_t i = 0; i < dimTotal; ++i)
825         {
826             OCRepPayloadDestroy(((OCRepPayload**)arr)[i]);
827         }
828     }
829     OICFree(arr);
830     return err;
831 }
832
833 static CborError OCParseSingleRepPayload(OCRepPayload **outPayload, CborValue *objMap, bool isRoot)
834 {
835     CborError err = CborUnknownError;
836     char *name = NULL;
837     bool res = false;
838     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
839     VERIFY_PARAM_NON_NULL(TAG, objMap, "Invalid Parameter objMap");
840
841     if (cbor_value_is_map(objMap))
842     {
843         if (!*outPayload)
844         {
845             *outPayload = OCRepPayloadCreate();
846             if (!*outPayload)
847             {
848                 return CborErrorOutOfMemory;
849             }
850         }
851
852         OCRepPayload *curPayload = *outPayload;
853
854         size_t len = 0;
855         CborValue repMap;
856         err = cbor_value_enter_container(objMap, &repMap);
857         VERIFY_CBOR_SUCCESS(TAG, err, "Failed entering repMap");
858
859         while (!err && cbor_value_is_valid(&repMap))
860         {
861             if (cbor_value_is_text_string(&repMap))
862             {
863                 err = cbor_value_dup_text_string(&repMap, &name, &len, NULL);
864                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding tag name in the map");
865                 err = cbor_value_advance(&repMap);
866                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing rootMap");
867                 if (name &&
868                     isRoot &&
869                     ((0 == strcmp(OC_RSRVD_HREF, name)) ||
870                      (0 == strcmp(OC_RSRVD_RESOURCE_TYPE, name)) ||
871                     (0 == strcmp(OC_RSRVD_INTERFACE, name))))
872                 {
873                     err = cbor_value_advance(&repMap);
874                     OICFree(name);
875                     continue;
876                 }
877             }
878             CborType type = cbor_value_get_type(&repMap);
879             switch (type)
880             {
881                 case CborNullType:
882                     res = OCRepPayloadSetNull(curPayload, name);
883                     break;
884                 case CborIntegerType:
885                     {
886                         int64_t intval = 0;
887                         err = cbor_value_get_int64(&repMap, &intval);
888                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting int value");
889                         res = OCRepPayloadSetPropInt(curPayload, name, intval);
890                     }
891                     break;
892                 case CborDoubleType:
893                     {
894                         double doubleval = 0;
895                         err = cbor_value_get_double(&repMap, &doubleval);
896                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting double value");
897                         res = OCRepPayloadSetPropDouble(curPayload, name, doubleval);
898                     }
899                     break;
900                 case CborBooleanType:
901                     {
902                         bool boolval = false;
903                         err = cbor_value_get_boolean(&repMap, &boolval);
904                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting boolean value");
905                         res = OCRepPayloadSetPropBool(curPayload, name, boolval);
906                     }
907                     break;
908                 case CborTextStringType:
909                     {
910                         char *strval = NULL;
911                         err = cbor_value_dup_text_string(&repMap, &strval, &len, NULL);
912                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting string value");
913                         res = OCRepPayloadSetPropStringAsOwner(curPayload, name, strval);
914                     }
915                     break;
916                 case CborByteStringType:
917                     {
918                         uint8_t* bytestrval = NULL;
919                         err = cbor_value_dup_byte_string(&repMap, &bytestrval, &len, NULL);
920                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting byte string value");
921                         OCByteString tmp = {.bytes = bytestrval, .len = len};
922                         res = OCRepPayloadSetPropByteStringAsOwner(curPayload, name, &tmp);
923                     }
924                     break;
925                 case CborMapType:
926                     {
927                         OCRepPayload *pl = NULL;
928                         err = OCParseSingleRepPayload(&pl, &repMap, false);
929                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting parse single rep");
930                         res = OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl);
931                     }
932                     break;
933                 case CborArrayType:
934                     err = OCParseArray(curPayload, name, &repMap);
935                     break;
936                 default:
937                     OIC_LOG_V(ERROR, TAG, "Parsing rep property, unknown type %d", repMap.type);
938                     res = false;
939             }
940             if (type != CborArrayType)
941             {
942                 err = (CborError) !res;
943             }
944             VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
945
946             if (type != CborMapType && cbor_value_is_valid(&repMap))
947             {
948                 err = cbor_value_advance(&repMap);
949                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advance repMap");
950             }
951             OICFree(name);
952             name = NULL;
953         }
954         if (cbor_value_is_container(objMap))
955         {
956             err = cbor_value_leave_container(objMap, &repMap);
957             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to leave container");
958         }
959         return err;
960     }
961
962 exit:
963     OICFree(name);
964     OCRepPayloadDestroy(*outPayload);
965     *outPayload = NULL;
966     return err;
967 }
968
969 static OCStackResult OCParseRepPayload(OCPayload **outPayload, CborValue *root)
970 {
971     OCStackResult ret = OC_STACK_INVALID_PARAM;
972     CborError err;
973     OCRepPayload *temp = NULL;
974     OCRepPayload *rootPayload = NULL;
975     OCRepPayload *curPayload = NULL;
976     CborValue rootMap = *root;
977     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
978     VERIFY_PARAM_NON_NULL(TAG, root, "Invalid Parameter root");
979
980     *outPayload = NULL;
981     if (cbor_value_is_array(root))
982     {
983         err = cbor_value_enter_container(root, &rootMap);
984     }
985     while (cbor_value_is_valid(&rootMap))
986     {
987         temp = OCRepPayloadCreate();
988         ret = OC_STACK_NO_MEMORY;
989         VERIFY_PARAM_NON_NULL(TAG, temp, "Failed allocating memory");
990
991         CborValue curVal;
992         ret = OC_STACK_MALFORMED_RESPONSE;
993
994         if (cbor_value_is_map(&rootMap))
995         {
996             err = cbor_value_map_find_value(&rootMap, OC_RSRVD_HREF, &curVal);
997             if (cbor_value_is_valid(&curVal))
998             {
999                 size_t len = 0;
1000                 err = cbor_value_dup_text_string(&curVal, &temp->uri, &len, NULL);
1001                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find uri");
1002             }
1003         }
1004         // Resource types
1005         if (cbor_value_is_map(&rootMap))
1006         {
1007             if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal))
1008             {
1009                 err =  OCParseStringLL(&rootMap, OC_RSRVD_RESOURCE_TYPE, &temp->types);
1010                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find rt type tag/value");
1011             }
1012         }
1013
1014         // Interface Types
1015         if (cbor_value_is_map(&rootMap))
1016         {
1017             if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_INTERFACE, &curVal))
1018             {
1019                 err =  OCParseStringLL(&rootMap, OC_RSRVD_INTERFACE, &temp->interfaces);
1020                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
1021             }
1022         }
1023
1024         if (cbor_value_is_map(&rootMap))
1025         {
1026             err = OCParseSingleRepPayload(&temp, &rootMap, true);
1027             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse single rep payload");
1028         }
1029         if(rootPayload == NULL)
1030         {
1031             rootPayload = temp;
1032             curPayload = temp;
1033         }
1034         else
1035         {
1036             curPayload->next = temp;
1037             curPayload = curPayload->next;
1038         }
1039
1040         if (cbor_value_is_array(&rootMap))
1041         {
1042             err = cbor_value_advance(&rootMap);
1043             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance single rep payload");
1044         }
1045     }
1046     *outPayload = (OCPayload *)rootPayload;
1047     return OC_STACK_OK;
1048
1049 exit:
1050     OCRepPayloadDestroy(temp);
1051     OCRepPayloadDestroy(rootPayload);
1052     OIC_LOG(ERROR, TAG, "CBOR error in ParseRepPayload");
1053     return ret;
1054 }
1055
1056 static OCStackResult OCParsePresencePayload(OCPayload **outPayload, CborValue *rootValue)
1057 {
1058     OCStackResult ret = OC_STACK_INVALID_PARAM;
1059     OCPresencePayload *payload = NULL;
1060     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
1061
1062     *outPayload = NULL;
1063
1064     payload = (OCPresencePayload *)OICCalloc(1, sizeof(OCPresencePayload));
1065     ret = OC_STACK_NO_MEMORY;
1066     VERIFY_PARAM_NON_NULL(TAG, payload, "Failed allocating presence payload");
1067     payload->base.type = PAYLOAD_TYPE_PRESENCE;
1068     ret = OC_STACK_MALFORMED_RESPONSE;
1069
1070     if (cbor_value_is_map(rootValue))
1071     {
1072         CborValue curVal;
1073
1074         // Sequence Number
1075         CborError err = cbor_value_map_find_value(rootValue, OC_RSRVD_NONCE, &curVal);
1076         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce tag");
1077         err = cbor_value_get_uint64(&curVal, (uint64_t *)&payload->sequenceNumber);
1078         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce value");
1079
1080         // Max Age
1081         err = cbor_value_map_find_value(rootValue, OC_RSRVD_TTL, &curVal);
1082         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl tag");
1083         err = cbor_value_get_uint64(&curVal, (uint64_t *)&payload->maxAge);
1084         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl value");
1085
1086         // Trigger
1087         err = cbor_value_map_find_value(rootValue, OC_RSRVD_TRIGGER, &curVal);
1088         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger tag");
1089         err = cbor_value_get_simple_type(&curVal, (uint8_t *)&payload->trigger);
1090         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger value");
1091
1092         // Resource type name
1093         err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
1094         if (cbor_value_is_valid(&curVal))
1095         {
1096             size_t len = 0;
1097             err = cbor_value_dup_text_string(&curVal, &payload->resourceType, &len, NULL);
1098             VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding resource type value");
1099         }
1100
1101         err = cbor_value_advance(rootValue);
1102         VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing root value");
1103
1104         *outPayload = (OCPayload *)payload;
1105         return OC_STACK_OK;
1106     }
1107 exit:
1108     OIC_LOG(ERROR, TAG, "CBOR error Parse Presence Payload");
1109     OCPresencePayloadDestroy(payload);
1110     return ret;
1111 }