Change DEVICE 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     if(cbor_value_is_map(rootValue))
476     {
477         uint8_t* sid = NULL;
478         char* dname = NULL;
479         char* specVer = NULL;
480         char* dmVer = NULL;
481
482         CborValue repVal;
483         // Device ID
484         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_DEVICE_ID, &repVal);
485         size_t len;
486         if(cbor_value_is_valid(&repVal))
487         {
488             err = err || cbor_value_dup_byte_string(&repVal, &sid, &len, NULL);
489         }
490         // Device Name
491         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_DEVICE_NAME, &repVal);
492         if(cbor_value_is_valid(&repVal))
493         {
494             err = err || cbor_value_dup_text_string(&repVal, &dname, &len, NULL);
495         }
496         // Device Spec Version
497         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_SPEC_VERSION, &repVal);
498         if(cbor_value_is_valid(&repVal))
499         {
500             err = err || cbor_value_dup_text_string(&repVal, &specVer, &len, NULL);
501         }
502
503         // Data Model Version
504         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_DATA_MODEL_VERSION, &repVal);
505         if (cbor_value_is_valid(&repVal))
506         {
507             err = err || cbor_value_dup_text_string(&repVal, &dmVer, &len, NULL);
508         }
509
510         err = err || cbor_value_advance(rootValue);
511
512         if(err)
513         {
514             OICFree(sid);
515             OICFree(dname);
516             OICFree(specVer);
517             OICFree(dmVer);
518             OC_LOG_V(ERROR, TAG, "CBOR in error condition %d", err);
519             return OC_STACK_MALFORMED_RESPONSE;
520         }
521
522         *outPayload = (OCPayload*)OCDevicePayloadCreate(sid, dname, specVer, dmVer);
523
524         OICFree(sid);
525         OICFree(dname);
526         OICFree(specVer);
527         OICFree(dmVer);
528         if(!*outPayload)
529         {
530             return OC_STACK_NO_MEMORY;
531         }
532
533         return OC_STACK_OK;
534     }
535     else
536     {
537         OC_LOG(ERROR, TAG, "Root device node was not a map");
538         return OC_STACK_MALFORMED_RESPONSE;
539     }
540
541 }
542
543 static OCStackResult OCParsePlatformPayload(OCPayload** outPayload, CborValue* rootValue)
544 {
545     if (!outPayload)
546     {
547         return OC_STACK_INVALID_PARAM;
548     }
549
550     bool err = false;
551
552     if(cbor_value_is_map(rootValue))
553     {
554         OCPlatformInfo info = {0};
555
556         CborValue repVal;
557         size_t len;
558         // Platform ID
559         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_ID, &repVal);
560         if(cbor_value_is_valid(&repVal))
561          {
562              err = err || cbor_value_dup_text_string(&repVal, &(info.platformID), &len, NULL);
563          }
564
565          // MFG Name
566          err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_NAME, &repVal);
567          if(cbor_value_is_valid(&repVal))
568          {
569              err = err || cbor_value_dup_text_string(&repVal, &(info.manufacturerName), &len, NULL);
570          }
571
572         // MFG URL
573         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_URL, &repVal);
574         if(cbor_value_is_valid(&repVal))
575         {
576              err = err || cbor_value_dup_text_string(&repVal, &(info.manufacturerUrl), &len, NULL);
577         }
578
579         // Model Num
580         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_MODEL_NUM, &repVal);
581         if(cbor_value_is_valid(&repVal))
582         {
583              err = err || cbor_value_dup_text_string(&repVal, &(info.modelNumber), &len, NULL);
584         }
585
586         // Date of Mfg
587         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_DATE, &repVal);
588         if(cbor_value_is_valid(&repVal))
589         {
590              err = err || cbor_value_dup_text_string(&repVal, &(info.dateOfManufacture), &len,
591                     NULL);
592         }
593
594         // Platform Version
595         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_VERSION, &repVal);
596         if(cbor_value_is_valid(&repVal))
597         {
598              err = err || cbor_value_dup_text_string(&repVal, &(info.platformVersion), &len, NULL);
599         }
600
601         // OS Version
602         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_OS_VERSION, &repVal);
603         if(cbor_value_is_valid(&repVal))
604         {
605              err = err || cbor_value_dup_text_string(&repVal, &(info.operatingSystemVersion),
606                     &len, NULL);
607         }
608
609         // Hardware Version
610         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_HARDWARE_VERSION, &repVal);
611         if(cbor_value_is_valid(&repVal))
612         {
613              err = err || cbor_value_dup_text_string(&repVal, &(info.hardwareVersion), &len,
614                     NULL);
615         }
616
617         // Firmware Version
618         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_FIRMWARE_VERSION, &repVal);
619         if(cbor_value_is_valid(&repVal))
620         {
621              err = err || cbor_value_dup_text_string(&repVal, &(info.firmwareVersion), &len,
622                     NULL);
623         }
624
625         // Support URL
626         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_SUPPORT_URL, &repVal);
627         if(cbor_value_is_valid(&repVal))
628         {
629              err = err || cbor_value_dup_text_string(&repVal, &(info.supportUrl), &len, NULL);
630         }
631
632         // System Time
633         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_SYSTEM_TIME, &repVal);
634         if(cbor_value_is_valid(&repVal))
635         {
636              err = err || cbor_value_dup_text_string(&repVal, &(info.systemTime), &len, NULL);
637         }
638
639         err = err || cbor_value_advance(rootValue);
640
641         if(err)
642         {
643             OICFree(info.dateOfManufacture);
644             OICFree(info.firmwareVersion);
645             OICFree(info.hardwareVersion);
646             OICFree(info.manufacturerName);
647             OICFree(info.manufacturerUrl);
648             OICFree(info.modelNumber);
649             OICFree(info.operatingSystemVersion);
650             OICFree(info.platformID);
651             OICFree(info.platformVersion);
652             OICFree(info.supportUrl);
653             OICFree(info.systemTime);
654             OC_LOG(ERROR, TAG, "CBOR error In ParsePlatformPayload");
655             return OC_STACK_MALFORMED_RESPONSE;
656         }
657
658         *outPayload = (OCPayload*)OCPlatformPayloadCreateAsOwner(&info);
659
660         if(!*outPayload)
661         {
662             return OC_STACK_NO_MEMORY;
663         }
664
665         return OC_STACK_OK;
666     }
667     else
668     {
669         OC_LOG(ERROR, TAG, "Root device node was not a map");
670         return OC_STACK_MALFORMED_RESPONSE;
671     }
672 }
673
674 static OCRepPayloadPropType DecodeCborType(CborType type)
675 {
676     switch (type)
677     {
678             case CborNullType:
679                 return OCREP_PROP_NULL;
680             case CborIntegerType:
681                 return OCREP_PROP_INT;
682             case CborDoubleType:
683                 return OCREP_PROP_DOUBLE;
684             case CborBooleanType:
685                 return OCREP_PROP_BOOL;
686             case CborTextStringType:
687                 return OCREP_PROP_STRING;
688             case CborByteStringType:
689                 return OCREP_PROP_BYTE_STRING;
690             case CborMapType:
691                 return OCREP_PROP_OBJECT;
692             case CborArrayType:
693                 return OCREP_PROP_ARRAY;
694             default:
695                 return OCREP_PROP_NULL;
696     }
697 }
698 static bool OCParseArrayFindDimensionsAndType(const CborValue* parent, size_t dimensions[MAX_REP_ARRAY_DEPTH],
699         OCRepPayloadPropType* type)
700 {
701     bool err = false;
702     CborValue insideArray;
703     *type = OCREP_PROP_NULL;
704     dimensions[0] = dimensions[1] = dimensions[2] = 0;
705
706     err = err || cbor_value_enter_container(parent, &insideArray);
707
708     while (cbor_value_is_valid(&insideArray))
709     {
710         OCRepPayloadPropType tempType = DecodeCborType(cbor_value_get_type(&insideArray));
711
712         if (tempType == OCREP_PROP_ARRAY)
713         {
714             size_t subdim[MAX_REP_ARRAY_DEPTH];
715             tempType = OCREP_PROP_NULL;
716             err = err || OCParseArrayFindDimensionsAndType(&insideArray, subdim, &tempType);
717
718             if (subdim[2] != 0)
719             {
720                 OC_LOG(ERROR, TAG, "Parse array helper, sub-array too deep");
721             }
722
723             dimensions[1] = dimensions[1] >= subdim[0] ? dimensions[1] : subdim[0];
724             dimensions[2] = dimensions[2] >= subdim[1] ? dimensions[2] : subdim[1];
725
726             if (*type != OCREP_PROP_NULL && tempType != OCREP_PROP_NULL
727                     && *type != tempType)
728             {
729                 OC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed (subtype)");
730                 return true;
731             }
732             else if (*type == OCREP_PROP_NULL)
733             {
734                 // We don't know the type of this array yet, so the assignment is OK
735                 *type = tempType;
736             }
737         }
738         else if (*type == OCREP_PROP_NULL)
739         {
740             // We don't know the type of this array yet, so the assignment is OK
741             *type = tempType;
742         }
743         // tempType is allowed to be NULL, since it might now know the answer yet
744         else if (tempType != OCREP_PROP_NULL && *type != tempType)
745         {
746             // this is an invalid situation!
747             OC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed");
748             return true;
749         }
750
751         ++dimensions[0];
752         cbor_value_advance(&insideArray);
753     }
754
755     return err;
756 }
757
758 static size_t getAllocSize(OCRepPayloadPropType type)
759 {
760     switch (type)
761     {
762         case OCREP_PROP_INT:
763             return sizeof (int64_t);
764         case OCREP_PROP_DOUBLE:
765             return sizeof (double);
766         case OCREP_PROP_BOOL:
767             return sizeof (bool);
768         case OCREP_PROP_STRING:
769             return sizeof (char*);
770         case OCREP_PROP_BYTE_STRING:
771             return sizeof (OCByteString);
772         case OCREP_PROP_OBJECT:
773             return sizeof (OCRepPayload*);
774         default:
775             return 0;
776     }
777 }
778
779 static size_t arrayStep(size_t dimensions[MAX_REP_ARRAY_DEPTH], size_t elementNum)
780 {
781     return
782         (dimensions[1] == 0 ? 1 : dimensions[1]) *
783         (dimensions[2] == 0 ? 1 : dimensions[2]) *
784         elementNum;
785 }
786
787 static bool OCParseArrayFillArray(const CborValue* parent, size_t dimensions[MAX_REP_ARRAY_DEPTH],
788         OCRepPayloadPropType type, void* targetArray)
789 {
790     bool err = false;
791     CborValue insideArray;
792
793     err = err || cbor_value_enter_container(parent, &insideArray);
794
795     size_t i = 0;
796     char* tempStr = NULL;
797     OCByteString ocByteStr = { .bytes = NULL, .len = 0};
798     size_t tempLen = 0;
799     OCRepPayload* tempPl = NULL;
800
801     size_t newdim[MAX_REP_ARRAY_DEPTH];
802     newdim[0] = dimensions[1];
803     newdim[1] = dimensions[2];
804     newdim[2] = 0;
805
806     while (!err && i < dimensions[0] && cbor_value_is_valid(&insideArray))
807     {
808         bool noAdvance = false;
809         if (cbor_value_get_type(&insideArray) != CborNullType)
810         {
811             switch (type)
812             {
813                 case OCREP_PROP_INT:
814                     if (dimensions[1] == 0)
815                     {
816                         err = err || cbor_value_get_int64(&insideArray,
817                                 &(((int64_t*)targetArray)[i]));
818                     }
819                     else
820                     {
821                         err = err || OCParseArrayFillArray(&insideArray, newdim,
822                             type,
823                             &(((int64_t*)targetArray)[arrayStep(dimensions, i)])
824                             );
825                     }
826                     break;
827                 case OCREP_PROP_DOUBLE:
828                     if (dimensions[1] == 0)
829                     {
830                         err = err || cbor_value_get_double(&insideArray,
831                                 &(((double*)targetArray)[i]));
832                     }
833                     else
834                     {
835                         err = err || OCParseArrayFillArray(&insideArray, newdim,
836                             type,
837                             &(((double*)targetArray)[arrayStep(dimensions, i)])
838                             );
839                     }
840                     break;
841                 case OCREP_PROP_BOOL:
842                     if (dimensions[1] == 0)
843                     {
844                         err = err || cbor_value_get_boolean(&insideArray,
845                                 &(((bool*)targetArray)[i]));
846                     }
847                     else
848                     {
849                         err = err || OCParseArrayFillArray(&insideArray, newdim,
850                             type,
851                             &(((bool*)targetArray)[arrayStep(dimensions, i)])
852                             );
853                     }
854                     break;
855                 case OCREP_PROP_STRING:
856                     if (dimensions[1] == 0)
857                     {
858                         err = err || cbor_value_dup_text_string(&insideArray,
859                                 &tempStr, &tempLen, NULL);
860                         ((char**)targetArray)[i] = tempStr;
861                         tempStr = NULL;
862                     }
863                     else
864                     {
865                         err = err || OCParseArrayFillArray(&insideArray, newdim,
866                             type,
867                             &(((char**)targetArray)[arrayStep(dimensions, i)])
868                             );
869                     }
870                     break;
871                 case OCREP_PROP_BYTE_STRING:
872                     if (dimensions[1] == 0)
873                     {
874                         err = err || cbor_value_dup_byte_string(&insideArray,
875                                 &(ocByteStr.bytes), &(ocByteStr.len), NULL);
876                         ((OCByteString*)targetArray)[i] = ocByteStr;
877                     }
878                     else
879                     {
880                         err = err || OCParseArrayFillArray(&insideArray, newdim,
881                                 type,
882                                 &(((OCByteString*)targetArray)[arrayStep(dimensions, i)])
883                                 );
884                     }
885                     break;
886                 case OCREP_PROP_OBJECT:
887                     if (dimensions[1] == 0)
888                     {
889                         err = err || OCParseSingleRepPayload(&tempPl, &insideArray);
890                         ((OCRepPayload**)targetArray)[i] = tempPl;
891                         tempPl = NULL;
892                         noAdvance = true;
893                     }
894                     else
895                     {
896                         err = err || OCParseArrayFillArray(&insideArray, newdim,
897                             type,
898                             &(((OCRepPayload**)targetArray)[arrayStep(dimensions, i)])
899                             );
900                     }
901                     break;
902                 default:
903                     OC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
904                     err = true;
905                     break;
906             }
907         }
908         ++i;
909         if (!noAdvance && cbor_value_is_valid(&insideArray))
910         {
911             err = err || cbor_value_advance(&insideArray);
912         }
913     }
914
915     return err;
916 }
917
918 static bool OCParseArray(OCRepPayload* out, const char* name, CborValue* container)
919 {
920     OCRepPayloadPropType type;
921     size_t dimensions[MAX_REP_ARRAY_DEPTH];
922     bool err = OCParseArrayFindDimensionsAndType(container, dimensions, &type);
923
924     if (err)
925     {
926         OC_LOG(ERROR, TAG, "Array details weren't clear");
927         return err;
928     }
929
930     if (type == OCREP_PROP_NULL)
931     {
932         err = err || OCRepPayloadSetNull(out, name);
933         err = err || cbor_value_advance(container);
934         return err;
935     }
936
937     size_t dimTotal = calcDimTotal(dimensions);
938     size_t allocSize = getAllocSize(type);
939     void* arr = OICCalloc(dimTotal, allocSize);
940
941     if (!arr)
942     {
943         OC_LOG(ERROR, TAG, "Array Parse allocation failed");
944         return true;
945     }
946
947     err = err || OCParseArrayFillArray(container, dimensions, type, arr);
948
949     switch (type)
950     {
951         case OCREP_PROP_INT:
952             if (err || !OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t*)arr, dimensions))
953             {
954                 OICFree(arr);
955                 err = true;
956             }
957             break;
958         case OCREP_PROP_DOUBLE:
959             if (err || !OCRepPayloadSetDoubleArrayAsOwner(out, name, (double*)arr, dimensions))
960             {
961                 OICFree(arr);
962                 err = true;
963             }
964             break;
965         case OCREP_PROP_BOOL:
966             if (err || !OCRepPayloadSetBoolArrayAsOwner(out, name, (bool*)arr, dimensions))
967             {
968                 OICFree(arr);
969                 err = true;
970             }
971             break;
972         case OCREP_PROP_STRING:
973             if (err || !OCRepPayloadSetStringArrayAsOwner(out, name, (char**)arr, dimensions))
974             {
975                 for(size_t i = 0; i < dimTotal; ++i)
976                 {
977                     OICFree(((char**)arr)[i]);
978                 }
979                 OICFree(arr);
980                 err = true;
981             }
982             break;
983         case OCREP_PROP_BYTE_STRING:
984             if (err || !OCRepPayloadSetByteStringArrayAsOwner(out, name, (OCByteString*)arr, dimensions))
985             {
986                 for (size_t i = 0; i < dimTotal; ++i)
987                 {
988                     OICFree(((OCByteString*)arr)[i].bytes);
989                 }
990                 OICFree(arr);
991                 err = true;
992             }
993             break;
994         case OCREP_PROP_OBJECT:
995             if (err || !OCRepPayloadSetPropObjectArrayAsOwner(out, name, (OCRepPayload**)arr, dimensions))
996             {
997                 for(size_t i = 0; i < dimTotal; ++i)
998                 {
999                     OCRepPayloadDestroy(((OCRepPayload**)arr)[i]);
1000                 }
1001                 OICFree(arr);
1002                 err = true;
1003             }
1004             break;
1005         default:
1006             OC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
1007             err = true;
1008             break;
1009     }
1010
1011     return err;
1012 }
1013
1014 static bool OCParseSingleRepPayload(OCRepPayload** outPayload, CborValue *objMap)
1015 {
1016     if (!outPayload)
1017     {
1018         return false;
1019     }
1020
1021     bool err = false;
1022
1023     if (cbor_value_is_map(objMap))
1024     {
1025         if (!*outPayload)
1026         {
1027             *outPayload = OCRepPayloadCreate();
1028             if(!*outPayload)
1029             {
1030                 return CborErrorOutOfMemory;
1031             }
1032         }
1033
1034         OCRepPayload* curPayload = *outPayload;
1035
1036         size_t len;
1037         CborValue repMap;
1038         err = err || cbor_value_enter_container(objMap, &repMap);
1039
1040         while(!err && cbor_value_is_valid(&repMap))
1041         {
1042             char* name;
1043             err = err || cbor_value_dup_text_string(&repMap, &name, &len, NULL);
1044             err = err || cbor_value_advance(&repMap);
1045
1046             CborType type = cbor_value_get_type(&repMap);
1047             switch(type)
1048             {
1049                 case CborNullType:
1050                     err = !OCRepPayloadSetNull(curPayload, name);
1051                     break;
1052                 case CborIntegerType:
1053                     {
1054                         int64_t intval = 0;
1055                         err = err || cbor_value_get_int64(&repMap, &intval);
1056                         if (!err)
1057                         {
1058                             err = !OCRepPayloadSetPropInt(curPayload, name, intval);
1059                         }
1060                     }
1061                     break;
1062                 case CborDoubleType:
1063                     {
1064                         double doubleval = 0;
1065                         err = err || cbor_value_get_double(&repMap, &doubleval);
1066                         if (!err)
1067                         {
1068                             err = !OCRepPayloadSetPropDouble(curPayload, name, doubleval);
1069                         }
1070                     }
1071                     break;
1072                 case CborBooleanType:
1073                     {
1074                         bool boolval = false;
1075                         err = err || cbor_value_get_boolean(&repMap, &boolval);
1076                         if (!err)
1077                         {
1078                             err = !OCRepPayloadSetPropBool(curPayload, name, boolval);
1079                         }
1080                     }
1081                     break;
1082                 case CborTextStringType:
1083                     {
1084                         char* strval = NULL;
1085                         err = err || cbor_value_dup_text_string(&repMap, &strval, &len, NULL);
1086                         if (!err)
1087                         {
1088                             err = !OCRepPayloadSetPropStringAsOwner(curPayload, name, strval);
1089                         }
1090                     }
1091                     break;
1092                 case CborByteStringType:
1093                     {
1094                         uint8_t* bytestrval = NULL;
1095                         err = err || cbor_value_dup_byte_string(&repMap, &bytestrval, &len, NULL);
1096                         if (!err)
1097                         {
1098                             OCByteString tmp = {.bytes = bytestrval, .len = len};
1099                             err = !OCRepPayloadSetPropByteStringAsOwner(curPayload, name, &tmp);
1100                         }
1101                     }
1102                     break;
1103                 case CborMapType:
1104                     {
1105                         OCRepPayload *pl = NULL;
1106                         err = err || OCParseSingleRepPayload(&pl, &repMap);
1107                         if (!err)
1108                         {
1109                             err = !OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl);
1110                         }
1111                     }
1112                     break;
1113                 case CborArrayType:
1114                     err = err || OCParseArray(curPayload, name, &repMap);
1115                     break;
1116                 default:
1117                     OC_LOG_V(ERROR, TAG, "Parsing rep property, unknown type %d", repMap.type);
1118                     err = true;
1119             }
1120
1121             if (type != CborMapType && cbor_value_is_valid(&repMap))
1122             {
1123                 err = err || cbor_value_advance(&repMap);
1124             }
1125             OICFree(name);
1126         }
1127
1128         err = err || cbor_value_leave_container(objMap, &repMap);
1129
1130         if(err)
1131         {
1132             OCRepPayloadDestroy(*outPayload);
1133             *outPayload = NULL;
1134         }
1135     }
1136
1137     return err;
1138 }
1139
1140 static OCStackResult OCParseRepPayload(OCPayload** outPayload, CborValue* rootMap)
1141 {
1142     if (!outPayload)
1143     {
1144         return OC_STACK_INVALID_PARAM;
1145     }
1146
1147     OCRepPayload *rootPayload = NULL;
1148     OCRepPayload *curPayload = NULL;
1149     OCRepPayload *temp = OCRepPayloadCreate();
1150     if (!temp)
1151     {
1152         return OC_STACK_NO_MEMORY;
1153     }
1154
1155     CborValue curVal;
1156     bool err = false;
1157     size_t len;
1158     err = err || cbor_value_map_find_value(rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal);
1159     if(cbor_value_is_text_string(&curVal))
1160     {
1161         char* allRt = NULL;
1162         err = err || cbor_value_dup_text_string(&curVal, &allRt, &len, NULL);
1163         if (allRt)
1164         {
1165             char* savePtr;
1166             char* curPtr = strtok_r(allRt, " ", &savePtr);
1167             while (curPtr)
1168             {
1169                 char* trimmed = InPlaceStringTrim(curPtr);
1170                 if (trimmed[0] != '\0')
1171                 {
1172                     OCRepPayloadAddResourceType(temp, curPtr);
1173                 }
1174                 curPtr = strtok_r(NULL, " ", &savePtr);
1175             }
1176         }
1177         OICFree(allRt);
1178     }
1179
1180     err = err || cbor_value_map_find_value(rootMap, OC_RSRVD_INTERFACE, &curVal);
1181     if(cbor_value_is_text_string(&curVal))
1182     {
1183         char* allIf = NULL;
1184         err = err || cbor_value_dup_text_string(&curVal, &allIf, &len, NULL);
1185         if (allIf)
1186         {
1187             char* savePtr;
1188             char* curPtr = strtok_r(allIf, " ", &savePtr);
1189             while (curPtr)
1190             {
1191                 char* trimmed = InPlaceStringTrim(curPtr);
1192                 if (trimmed[0] != '\0')
1193                 {
1194                     OCRepPayloadAddInterface(temp, curPtr);
1195                 }
1196                 curPtr = strtok_r(NULL, " ", &savePtr);
1197             }
1198         }
1199         OICFree(allIf);
1200     }
1201
1202     while (!err && cbor_value_is_map(rootMap))
1203     {
1204          err = err || OCParseSingleRepPayload(&temp, rootMap);
1205
1206         if(rootPayload == NULL)
1207         {
1208             rootPayload = temp;
1209             curPayload = temp;
1210         }
1211         else
1212         {
1213             curPayload->next = temp;
1214             curPayload = curPayload->next;
1215         }
1216
1217         if (cbor_value_is_valid(rootMap))
1218         {
1219             err = err || cbor_value_advance(rootMap);
1220         }
1221
1222         if(err)
1223         {
1224             OCRepPayloadDestroy(rootPayload);
1225             OC_LOG(ERROR, TAG, "CBOR error in ParseRepPayload");
1226             return OC_STACK_MALFORMED_RESPONSE;
1227         }
1228     }
1229
1230     *outPayload = (OCPayload*)rootPayload;
1231
1232     return OC_STACK_OK;
1233 }
1234
1235 static OCStackResult OCParsePresencePayload(OCPayload** outPayload, CborValue* rootValue)
1236 {
1237     if (!outPayload)
1238     {
1239         return OC_STACK_INVALID_PARAM;
1240     }
1241
1242     bool err = false;
1243     CborValue arrayVal;
1244     err = err || cbor_value_enter_container(rootValue, &arrayVal);
1245
1246     if(cbor_value_is_map(&arrayVal))
1247     {
1248         uint64_t seqNum = 0;
1249         uint64_t maxAge = 0;
1250         OCPresenceTrigger trigger = OC_PRESENCE_TRIGGER_CREATE;
1251         char* tempStr = NULL;
1252         size_t len = 0;
1253
1254         CborValue curVal;
1255         // Sequence Number
1256         err = err || cbor_value_map_find_value(&arrayVal, OC_RSRVD_NONCE, &curVal);
1257         err = err || cbor_value_get_uint64(&curVal, &seqNum);
1258
1259         // Max Age
1260         err = err || cbor_value_map_find_value(&arrayVal, OC_RSRVD_TTL, &curVal);
1261         err = err || cbor_value_get_uint64(&curVal, &maxAge);
1262
1263         // Trigger
1264         err = err || cbor_value_map_find_value(&arrayVal, OC_RSRVD_TRIGGER, &curVal);
1265         err = err || cbor_value_dup_text_string(&curVal, &tempStr, &len, NULL);
1266         trigger = convertTriggerStringToEnum(tempStr);
1267         OICFree(tempStr);
1268         tempStr = NULL;
1269
1270         // Resource type name
1271          err = err || cbor_value_map_find_value(&arrayVal, OC_RSRVD_RESOURCE_TYPE, &curVal);
1272         if(cbor_value_is_valid(&curVal))
1273         {
1274              err = err || cbor_value_dup_text_string(&curVal, &tempStr, &len, NULL);
1275         }
1276
1277         err = err || cbor_value_advance(&arrayVal);
1278         err = err || cbor_value_leave_container(rootValue, &arrayVal);
1279
1280         if(!err)
1281         {
1282             *outPayload = (OCPayload*)OCPresencePayloadCreate(seqNum, maxAge, trigger, tempStr);
1283         }
1284         OICFree(tempStr);
1285
1286         if(err)
1287         {
1288             OCPayloadDestroy(*outPayload);
1289             OC_LOG(ERROR, TAG, "CBOR error Parse Presence Payload");
1290             return OC_STACK_MALFORMED_RESPONSE;
1291         }
1292
1293         if(!*outPayload)
1294         {
1295             return OC_STACK_NO_MEMORY;
1296         }
1297
1298         return OC_STACK_OK;
1299     }
1300     else
1301     {
1302         OC_LOG(ERROR, TAG, "Root presence node was not a map");
1303         return OC_STACK_MALFORMED_RESPONSE;
1304     }
1305 }