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