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