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