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