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