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