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