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