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