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