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