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