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