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