replace : iotivity -> iotivity-sec
[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
30 #include <string.h>
31 #include <stdlib.h>
32 #include "oic_string.h"
33 #include "oic_malloc.h"
34 #include "ocpayload.h"
35 #include "ocpayloadcbor.h"
36 #include "ocstackinternal.h"
37 #include "payload_logging.h"
38 #include "platform_features.h"
39
40 #define TAG "OIC_RI_PAYLOADPARSE"
41
42 static OCStackResult OCParseDiscoveryPayload(OCPayload **outPayload, CborValue *arrayVal);
43 static CborError OCParseSingleRepPayload(OCRepPayload **outPayload, CborValue *repParent, bool isRoot);
44 static OCStackResult OCParseRepPayload(OCPayload **outPayload, CborValue *arrayVal);
45 #ifdef WITH_PRESENCE
46 static OCStackResult OCParsePresencePayload(OCPayload **outPayload, CborValue *arrayVal);
47 #endif
48 static OCStackResult OCParseSecurityPayload(OCPayload **outPayload, const uint8_t *payload, size_t size);
49
50 OCStackResult OCParsePayload(OCPayload **outPayload, OCPayloadType payloadType,
51         const uint8_t *payload, size_t payloadSize)
52 {
53     OCStackResult result = OC_STACK_MALFORMED_RESPONSE;
54     CborError err;
55
56     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Conversion of outPayload failed");
57     VERIFY_PARAM_NON_NULL(TAG, payload, "Invalid cbor payload value");
58
59     OIC_LOG_V(INFO, TAG, "CBOR Parsing size: %zu of Payload Type: %d, Payload:",
60             payloadSize, payloadType);
61
62     CborParser parser;
63     CborValue rootValue;
64
65     err = cbor_parser_init(payload, payloadSize, 0, &parser, &rootValue);
66     VERIFY_CBOR_SUCCESS(TAG, err, "Failed initializing init value")
67
68     switch(payloadType)
69     {
70         case PAYLOAD_TYPE_DISCOVERY:
71             result = OCParseDiscoveryPayload(outPayload, &rootValue);
72             break;
73         case PAYLOAD_TYPE_REPRESENTATION:
74             result = OCParseRepPayload(outPayload, &rootValue);
75             break;
76 #ifdef WITH_PRESENCE
77         case PAYLOAD_TYPE_PRESENCE:
78             result = OCParsePresencePayload(outPayload, &rootValue);
79             break;
80 #endif
81         case PAYLOAD_TYPE_SECURITY:
82             result = OCParseSecurityPayload(outPayload, payload, payloadSize);
83             break;
84         default:
85             OIC_LOG_V(ERROR, TAG, "ParsePayload Type default: %d", payloadType);
86             result = OC_STACK_INVALID_PARAM;
87             break;
88     }
89
90     OIC_LOG_V(INFO, TAG, "Finished parse payload, result is %d", result);
91
92 exit:
93     return result;
94 }
95
96 static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, const uint8_t *payload,
97         size_t size)
98 {
99     if (size > 0)
100     {
101         *outPayload = (OCPayload *)OCSecurityPayloadCreate(payload, size);
102     }
103     else
104     {
105         *outPayload = NULL;
106     }
107     return OC_STACK_OK;
108 }
109
110 static char* InPlaceStringTrim(char* str)
111 {
112     while (str[0] == ' ')
113     {
114         ++str;
115     }
116
117     size_t lastchar = strlen(str);
118
119     while (str[lastchar] == ' ')
120     {
121         str[lastchar] = '\0';
122         --lastchar;
123     }
124
125     return str;
126 }
127
128 static CborError OCParseStringLL(CborValue *map, char *type, OCStringLL **resource)
129 {
130     CborValue val;
131     CborError err = cbor_value_map_find_value(map, type, &val);
132     VERIFY_CBOR_SUCCESS(TAG, err, "to find StringLL TAG");
133
134     if (cbor_value_is_array(&val))
135     {
136         CborValue txtStr;
137         err = cbor_value_enter_container(&val, &txtStr);
138         VERIFY_CBOR_SUCCESS(TAG, err, "to enter container");
139         while (cbor_value_is_text_string(&txtStr))
140         {
141             size_t len = 0;
142             char *input = NULL;
143             err = cbor_value_dup_text_string(&txtStr, &input, &len, NULL);
144             VERIFY_CBOR_SUCCESS(TAG, err, "to find StringLL value.");
145             if (input)
146             {
147                 char *savePtr = NULL;
148                 char *curPtr = strtok_r(input, " ", &savePtr);
149                 while (curPtr)
150                 {
151                     char *trimmed = InPlaceStringTrim(curPtr);
152                     if (trimmed && strlen(trimmed) > 0)
153                     {
154                         if (!OCResourcePayloadAddStringLL(resource, trimmed))
155                         {
156                             return CborErrorOutOfMemory;
157                         }
158                     }
159                     curPtr = strtok_r(NULL, " ", &savePtr);
160                 }
161                 OICFree(input);
162             }
163             if (cbor_value_is_text_string(&txtStr))
164             {
165                 err = cbor_value_advance(&txtStr);
166                 VERIFY_CBOR_SUCCESS(TAG, err, "to advance string value");
167             }
168         }
169     }
170 exit:
171     return err;
172 }
173
174 static OCStackResult OCParseDiscoveryPayload(OCPayload **outPayload, CborValue *rootValue)
175 {
176     OCStackResult ret = OC_STACK_INVALID_PARAM;
177     OCResourcePayload *resource = NULL;
178     OCDiscoveryPayload *temp = NULL;
179     OCDiscoveryPayload *rootPayload = NULL;
180     OCDiscoveryPayload *curPayload = NULL;
181     size_t len = 0;
182     CborError err = CborNoError;
183     *outPayload = NULL;
184
185     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
186     VERIFY_PARAM_NON_NULL(TAG, rootValue, "Invalid Parameter rootValue");
187     if (cbor_value_is_array(rootValue))
188     {
189         // Root value is already inside the main root array
190         CborValue rootMap;
191
192         // Enter the main root map
193         ret = OC_STACK_MALFORMED_RESPONSE;
194         err = cbor_value_enter_container(rootValue, &rootMap);
195         VERIFY_CBOR_SUCCESS(TAG, err, "to enter root map container");
196         while (cbor_value_is_map(&rootMap))
197         {
198             ret = OC_STACK_NO_MEMORY;
199             temp = OCDiscoveryPayloadCreate();
200             VERIFY_PARAM_NON_NULL(TAG, temp, "Failed error initializing discovery payload");
201
202             // Look for DI
203             CborValue curVal;
204             err = cbor_value_map_find_value(&rootMap, OC_RSRVD_DEVICE_ID, &curVal);
205             VERIFY_CBOR_SUCCESS(TAG, err, "to find device id tag");
206             if (cbor_value_is_valid(&curVal))
207             {
208                 if (cbor_value_is_byte_string(&curVal))
209                 {
210                     err = cbor_value_dup_byte_string(&curVal, (uint8_t **)&(temp->sid), &len, NULL);
211                     VERIFY_CBOR_SUCCESS(TAG, err, "to copy device id value");
212                 }
213                 else if (cbor_value_is_text_string(&curVal))
214                 {
215                     err = cbor_value_dup_text_string(&curVal, &(temp->sid), &len, NULL);
216                     VERIFY_CBOR_SUCCESS(TAG, err, "to copy device id value");
217                 }
218             }
219
220             // BaseURI - Not a mandatory field
221             err = cbor_value_map_find_value(&rootMap, OC_RSRVD_BASE_URI, &curVal);
222             VERIFY_CBOR_SUCCESS(TAG, err, "to find uri tag");
223             if (cbor_value_is_text_string(&curVal))
224             {
225                 err = cbor_value_dup_text_string(&curVal, &(temp->baseURI), &len, NULL);
226                 VERIFY_CBOR_SUCCESS(TAG, err, "to find base uri value");
227             }
228
229             // RT - Not a mandatory field
230             err = cbor_value_map_find_value(&rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal);
231             if (cbor_value_is_valid(&curVal))
232             {
233                 err = OCParseStringLL(&rootMap, OC_RSRVD_RESOURCE_TYPE, &temp->type);
234                 VERIFY_CBOR_SUCCESS(TAG, err, "to find resource type");
235             }
236
237             // IF - Not a mandatory field
238             err = cbor_value_map_find_value(&rootMap, OC_RSRVD_INTERFACE, &curVal);
239             if (cbor_value_is_valid(&curVal))
240             {
241                 err =  OCParseStringLL(&rootMap, OC_RSRVD_INTERFACE, &temp->iface);
242                 VERIFY_CBOR_SUCCESS(TAG, err, "to find interface");
243             }
244
245             // Name - Not a mandatory field
246             err = cbor_value_map_find_value(&rootMap, OC_RSRVD_DEVICE_NAME, &curVal);
247             if (cbor_value_is_text_string(&curVal))
248             {
249                 err = cbor_value_dup_text_string(&curVal, &temp->name, &len, NULL);
250                 VERIFY_CBOR_SUCCESS(TAG, err, "to find device name");
251             }
252
253             // Look for Links which will have an array as the value
254             CborValue linkMap;
255             err = cbor_value_map_find_value(&rootMap, OC_RSRVD_LINKS, &linkMap);
256             VERIFY_CBOR_SUCCESS(TAG, err, "to find links tag");
257
258             // Enter the links array and start iterating through the array processing
259             // each resource which shows up as a map.
260             CborValue resourceMap;
261             err = cbor_value_enter_container(&linkMap, &resourceMap);
262             VERIFY_CBOR_SUCCESS(TAG, err, "to enter link map");
263
264             while (cbor_value_is_map(&resourceMap))
265             {
266                 int bitmap;
267
268                 resource = (OCResourcePayload *)OICCalloc(1, sizeof(OCResourcePayload));
269                 VERIFY_PARAM_NON_NULL(TAG, resource, "Failed allocating resource payload");
270
271                 // Uri
272                 err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_HREF, &curVal);
273                 VERIFY_CBOR_SUCCESS(TAG, err, "to find href tag");
274                 err = cbor_value_dup_text_string(&curVal, &(resource->uri), &len, NULL);
275                 VERIFY_CBOR_SUCCESS(TAG, err, "to find href value");
276
277                 // ResourceTypes
278                 err =  OCParseStringLL(&resourceMap, OC_RSRVD_RESOURCE_TYPE, &resource->types);
279                 VERIFY_CBOR_SUCCESS(TAG, err, "to find resource type tag/value");
280
281                 // Interface Types
282                 err =  OCParseStringLL(&resourceMap, OC_RSRVD_INTERFACE, &resource->interfaces);
283                 if (CborNoError != err)
284                 {
285                     if (!OCResourcePayloadAddStringLL(&resource->interfaces, OC_RSRVD_INTERFACE_LL))
286                     {
287                         OIC_LOG(ERROR, TAG, "Failed to add string to StringLL");
288                         goto exit;
289                     }
290                 }
291
292                 // Policy
293                 CborValue policyMap;
294                 err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_POLICY, &policyMap);
295                 VERIFY_CBOR_SUCCESS(TAG, err, "to find policy tag");
296
297                 // Bitmap
298                 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_BITMAP, &curVal);
299                 VERIFY_CBOR_SUCCESS(TAG, err, "to find bitmap tag");
300                 err = cbor_value_get_int(&curVal, &bitmap);
301                 VERIFY_CBOR_SUCCESS(TAG, err, "to find bitmap value");
302                 resource->bitmap = (uint8_t)bitmap;
303
304                 // Secure Flag
305                 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_SECURE, &curVal);
306                 VERIFY_CBOR_SUCCESS(TAG, err, "to find secure tag");
307                 if (cbor_value_is_boolean(&curVal))
308                 {
309                     err = cbor_value_get_boolean(&curVal, &(resource->secure));
310                     VERIFY_CBOR_SUCCESS(TAG, err, "to find secure value");
311                 }
312
313                 // Port
314                 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_HOSTING_PORT, &curVal);
315                 VERIFY_CBOR_SUCCESS(TAG, err, "to find port tag");
316                 if (cbor_value_is_integer(&curVal))
317                 {
318                     int port;
319
320                     err = cbor_value_get_int(&curVal, &port);
321                     VERIFY_CBOR_SUCCESS(TAG, err, "to find port value");
322                     resource->port = (uint16_t)port;
323                 }
324
325 #ifdef TCP_ADAPTER
326                 // TCP Port
327                 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_TCP_PORT, &curVal);
328                 if (cbor_value_is_integer(&curVal))
329                 {
330                     int tcpPort;
331
332                     err = cbor_value_get_int(&curVal, &tcpPort);
333                     VERIFY_CBOR_SUCCESS(TAG, err, "to find tcp port value");
334                     resource->tcpPort = (uint16_t)tcpPort;
335                 }
336
337 #ifdef __WITH_TLS__
338                 // TLS Port
339                 err = cbor_value_map_find_value(&policyMap, OC_RSRVD_TLS_PORT, &curVal);
340                 if (cbor_value_is_integer(&curVal))
341                 {
342                     int tlsPort;
343
344                     err = cbor_value_get_int(&curVal, &tlsPort);
345                     VERIFY_CBOR_SUCCESS(TAG, err, "to find tcp tls port value");
346                     resource->tcpPort = (uint16_t)tlsPort;
347                 }
348 #endif
349 #endif
350
351                 err = cbor_value_advance(&resourceMap);
352                 VERIFY_CBOR_SUCCESS(TAG, err, "to advance resource map");
353
354                 OCDiscoveryPayloadAddNewResource(temp, resource);
355             }
356
357             err = cbor_value_leave_container(&linkMap, &resourceMap);
358             VERIFY_CBOR_SUCCESS(TAG, err, "to leave resource map");
359
360             err = cbor_value_advance(&rootMap);
361             VERIFY_CBOR_SUCCESS(TAG, err, "to advance root map");
362
363             if(rootPayload == NULL)
364             {
365                 rootPayload = temp;
366                 curPayload = temp;
367             }
368             else
369             {
370                 curPayload->next = temp;
371                 curPayload = curPayload->next;
372             }
373         }
374
375         err = cbor_value_leave_container(rootValue, &rootMap);
376         VERIFY_CBOR_SUCCESS(TAG, err, "to leave root map");
377
378     }
379     else
380     {
381         OIC_LOG(ERROR, TAG, "Malformed packet ");
382         goto exit;
383     }
384
385     *outPayload = (OCPayload *)rootPayload;
386     OIC_LOG_PAYLOAD(DEBUG, *outPayload);
387
388     return OC_STACK_OK;
389
390 exit:
391     OCDiscoveryResourceDestroy(resource);
392     OCDiscoveryPayloadDestroy(rootPayload);
393     return ret;
394 }
395
396 static OCRepPayloadPropType DecodeCborType(CborType type)
397 {
398     switch (type)
399     {
400         case CborNullType:
401             return OCREP_PROP_NULL;
402         case CborIntegerType:
403             return OCREP_PROP_INT;
404         case CborDoubleType:
405         case CborFloatType:
406             return OCREP_PROP_DOUBLE;
407         case CborBooleanType:
408             return OCREP_PROP_BOOL;
409         case CborTextStringType:
410             return OCREP_PROP_STRING;
411         case CborByteStringType:
412             return OCREP_PROP_BYTE_STRING;
413         case CborMapType:
414             return OCREP_PROP_OBJECT;
415         case CborArrayType:
416             return OCREP_PROP_ARRAY;
417         default:
418             return OCREP_PROP_NULL;
419     }
420 }
421 static CborError OCParseArrayFindDimensionsAndType(const CborValue *parent,
422         size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType *type)
423 {
424     CborValue insideArray;
425     *type = OCREP_PROP_NULL;
426     dimensions[0] = dimensions[1] = dimensions[2] = 0;
427
428     CborError err = cbor_value_enter_container(parent, &insideArray);
429     VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
430
431     while (cbor_value_is_valid(&insideArray))
432     {
433         OCRepPayloadPropType tempType = DecodeCborType(cbor_value_get_type(&insideArray));
434
435         if (tempType == OCREP_PROP_ARRAY)
436         {
437             size_t subdim[MAX_REP_ARRAY_DEPTH];
438             tempType = OCREP_PROP_NULL;
439             err = OCParseArrayFindDimensionsAndType(&insideArray, subdim, &tempType);
440             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse array");
441
442             if (subdim[2] != 0)
443             {
444                 OIC_LOG(ERROR, TAG, "Parse array helper, sub-array too deep");
445             }
446
447             dimensions[1] = dimensions[1] >= subdim[0] ? dimensions[1] : subdim[0];
448             dimensions[2] = dimensions[2] >= subdim[1] ? dimensions[2] : subdim[1];
449
450             if (*type != OCREP_PROP_NULL && tempType != OCREP_PROP_NULL && *type != tempType)
451             {
452                 OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed (subtype)");
453                 return CborUnknownError;
454             }
455             else if (*type == OCREP_PROP_NULL)
456             {
457                 // We don't know the type of this array yet, so the assignment is OK
458                 *type = tempType;
459             }
460         }
461         else if (*type == OCREP_PROP_NULL)
462         {
463             // We don't know the type of this array yet, so the assignment is OK
464             *type = tempType;
465         }
466         // tempType is allowed to be NULL, since it might now know the answer yet
467         else if (tempType != OCREP_PROP_NULL && *type != tempType)
468         {
469             // this is an invalid situation!
470             OIC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed");
471             return CborUnknownError;
472         }
473
474         ++dimensions[0];
475         err = cbor_value_advance(&insideArray);
476         VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance array");
477     }
478
479 exit:
480     return err;
481 }
482
483 static size_t getAllocSize(OCRepPayloadPropType type)
484 {
485     switch (type)
486     {
487         case OCREP_PROP_INT:
488             return sizeof (int64_t);
489         case OCREP_PROP_DOUBLE:
490             return sizeof (double);
491         case OCREP_PROP_BOOL:
492             return sizeof (bool);
493         case OCREP_PROP_STRING:
494             return sizeof (char*);
495         case OCREP_PROP_BYTE_STRING:
496             return sizeof (OCByteString);
497         case OCREP_PROP_OBJECT:
498             return sizeof (OCRepPayload*);
499         default:
500             return 0;
501     }
502 }
503
504 static size_t arrayStep(size_t dimensions[MAX_REP_ARRAY_DEPTH], size_t elementNum)
505 {
506     return
507         (dimensions[1] == 0 ? 1 : dimensions[1]) *
508         (dimensions[2] == 0 ? 1 : dimensions[2]) *
509         elementNum;
510 }
511
512 static CborError OCParseArrayFillArray(const CborValue *parent,
513         size_t dimensions[MAX_REP_ARRAY_DEPTH], OCRepPayloadPropType type, void *targetArray)
514 {
515     CborValue insideArray;
516
517     size_t i = 0;
518     char *tempStr = NULL;
519     OCByteString ocByteStr = { .bytes = NULL, .len = 0};
520     size_t tempLen = 0;
521     OCRepPayload *tempPl = NULL;
522
523     size_t newdim[MAX_REP_ARRAY_DEPTH];
524     newdim[0] = dimensions[1];
525     newdim[1] = dimensions[2];
526     newdim[2] = 0;
527
528     CborError err = cbor_value_enter_container(parent, &insideArray);
529     VERIFY_CBOR_SUCCESS(TAG, err, "Failed to enter container");
530
531     while (!err && i < dimensions[0] && cbor_value_is_valid(&insideArray))
532     {
533         bool noAdvance = false;
534         if (cbor_value_get_type(&insideArray) != CborNullType)
535         {
536             switch (type)
537             {
538                 case OCREP_PROP_INT:
539                     if (dimensions[1] == 0)
540                     {
541                         err = cbor_value_get_int64(&insideArray, &(((int64_t*)targetArray)[i]));
542                     }
543                     else
544                     {
545                         err = OCParseArrayFillArray(&insideArray, newdim, type,
546                             &(((int64_t*)targetArray)[arrayStep(dimensions, i)]));
547                     }
548                     break;
549                 case OCREP_PROP_DOUBLE:
550                     if (dimensions[1] == 0)
551                     {
552                         double *d = &(((double*)targetArray)[i]);
553                         if (cbor_value_get_type(&insideArray) == CborDoubleType)
554                         {
555                             err = cbor_value_get_double(&insideArray, d);
556                         }
557                         else
558                         {
559                             /* must be float */
560                             float f;
561                             err = cbor_value_get_float(&insideArray, &f);
562                             if (!err)
563                                 *d = f;
564                         }
565                     }
566                     else
567                     {
568                         err = OCParseArrayFillArray(&insideArray, newdim, type,
569                             &(((double*)targetArray)[arrayStep(dimensions, i)]));
570                     }
571                     break;
572                 case OCREP_PROP_BOOL:
573                     if (dimensions[1] == 0)
574                     {
575                         err = cbor_value_get_boolean(&insideArray, &(((bool*)targetArray)[i]));
576                     }
577                     else
578                     {
579                         err = OCParseArrayFillArray(&insideArray, newdim, type,
580                             &(((bool*)targetArray)[arrayStep(dimensions, i)]));
581                     }
582                     break;
583                 case OCREP_PROP_STRING:
584                     if (dimensions[1] == 0)
585                     {
586                         err = cbor_value_dup_text_string(&insideArray, &tempStr, &tempLen, NULL);
587                         ((char**)targetArray)[i] = tempStr;
588                         tempStr = NULL;
589                     }
590                     else
591                     {
592                         err = OCParseArrayFillArray(&insideArray, newdim, type,
593                             &(((char**)targetArray)[arrayStep(dimensions, i)]));
594                     }
595                     break;
596                 case OCREP_PROP_BYTE_STRING:
597                     if (dimensions[1] == 0)
598                     {
599                         err = cbor_value_dup_byte_string(&insideArray, &(ocByteStr.bytes),
600                                 &(ocByteStr.len), NULL);
601                         ((OCByteString*)targetArray)[i] = ocByteStr;
602                     }
603                     else
604                     {
605                         err = OCParseArrayFillArray(&insideArray, newdim, type,
606                                 &(((OCByteString*)targetArray)[arrayStep(dimensions, i)]));
607                     }
608                     break;
609                 case OCREP_PROP_OBJECT:
610                     if (dimensions[1] == 0)
611                     {
612                         err = OCParseSingleRepPayload(&tempPl, &insideArray, false);
613                         ((OCRepPayload**)targetArray)[i] = tempPl;
614                         tempPl = NULL;
615                         noAdvance = true;
616                     }
617                     else
618                     {
619                         err = OCParseArrayFillArray(&insideArray, newdim, type,
620                             &(((OCRepPayload**)targetArray)[arrayStep(dimensions, i)]));
621                     }
622                     break;
623                 default:
624                     OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
625                     err = CborErrorUnknownType;
626                     break;
627             }
628             VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting repPayload");
629         }
630         ++i;
631         if (!noAdvance && cbor_value_is_valid(&insideArray))
632         {
633             err = cbor_value_advance(&insideArray);
634             VERIFY_CBOR_SUCCESS(TAG, err, "Failed advnce insideArray");
635         }
636     }
637
638 exit:
639     return err;
640 }
641
642 static CborError OCParseArray(OCRepPayload *out, const char *name, CborValue *container)
643 {
644     void *arr = NULL;
645
646     OCRepPayloadPropType type = OCREP_PROP_NULL;
647     size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
648
649     size_t dimTotal = 0;
650     size_t allocSize = 0;
651     bool res = true;
652     CborError err = OCParseArrayFindDimensionsAndType(container, dimensions, &type);
653     VERIFY_CBOR_SUCCESS(TAG, err, "Array details weren't clear");
654
655     if (type == OCREP_PROP_NULL)
656     {
657         res = OCRepPayloadSetNull(out, name);
658         err = (CborError) !res;
659         VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
660         container = container + 1;
661         return err;
662     }
663
664     dimTotal = calcDimTotal(dimensions);
665     allocSize = getAllocSize(type);
666     arr = OICCalloc(dimTotal, allocSize);
667     VERIFY_PARAM_NON_NULL(TAG, arr, "Array Parse allocation failed");
668
669     res = OCParseArrayFillArray(container, dimensions, type, arr);
670     VERIFY_CBOR_SUCCESS(TAG, err, "Failed parse array");
671
672     switch (type)
673     {
674         case OCREP_PROP_INT:
675             res = OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t *)arr, dimensions);
676             break;
677         case OCREP_PROP_DOUBLE:
678             res = OCRepPayloadSetDoubleArrayAsOwner(out, name, (double *)arr, dimensions);
679             break;
680         case OCREP_PROP_BOOL:
681             res = OCRepPayloadSetBoolArrayAsOwner(out, name, (bool *)arr, dimensions);
682             break;
683         case OCREP_PROP_STRING:
684             res = OCRepPayloadSetStringArrayAsOwner(out, name, (char **)arr, dimensions);
685             break;
686         case OCREP_PROP_BYTE_STRING:
687             res = OCRepPayloadSetByteStringArrayAsOwner(out, name, (OCByteString *)arr, dimensions);
688             break;
689         case OCREP_PROP_OBJECT:
690             res = OCRepPayloadSetPropObjectArrayAsOwner(out, name, (OCRepPayload**)arr, dimensions);
691             break;
692         default:
693             OIC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
694             break;
695     }
696     err = (CborError) !res;
697     VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting array parameter");
698     return CborNoError;
699 exit:
700     if (type == OCREP_PROP_STRING)
701     {
702         for(size_t i = 0; i < dimTotal; ++i)
703         {
704             OICFree(((char**)arr)[i]);
705         }
706     }
707     if (type == OCREP_PROP_BYTE_STRING)
708     {
709         for(size_t i = 0; i < dimTotal; ++i)
710         {
711             OICFree(((OCByteString*)arr)[i].bytes);
712         }
713     }
714     if (type == OCREP_PROP_OBJECT)
715     {
716         for(size_t i = 0; i < dimTotal; ++i)
717         {
718             OCRepPayloadDestroy(((OCRepPayload**)arr)[i]);
719         }
720     }
721     OICFree(arr);
722     return err;
723 }
724
725 static CborError OCParseSingleRepPayload(OCRepPayload **outPayload, CborValue *objMap, bool isRoot)
726 {
727     CborError err = CborUnknownError;
728     char *name = NULL;
729     bool res = false;
730     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
731     VERIFY_PARAM_NON_NULL(TAG, objMap, "Invalid Parameter objMap");
732
733     if (cbor_value_is_map(objMap))
734     {
735         if (!*outPayload)
736         {
737             *outPayload = OCRepPayloadCreate();
738             if (!*outPayload)
739             {
740                 return CborErrorOutOfMemory;
741             }
742         }
743
744         OCRepPayload *curPayload = *outPayload;
745
746         size_t len = 0;
747         CborValue repMap;
748         err = cbor_value_enter_container(objMap, &repMap);
749         VERIFY_CBOR_SUCCESS(TAG, err, "Failed entering repMap");
750
751         while (!err && cbor_value_is_valid(&repMap))
752         {
753             if (cbor_value_is_text_string(&repMap))
754             {
755                 err = cbor_value_dup_text_string(&repMap, &name, &len, NULL);
756                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding tag name in the map");
757                 err = cbor_value_advance(&repMap);
758                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing rootMap");
759                 if (name &&
760                     isRoot &&
761                     ((0 == strcmp(OC_RSRVD_HREF, name)) ||
762                      (0 == strcmp(OC_RSRVD_RESOURCE_TYPE, name)) ||
763                     (0 == strcmp(OC_RSRVD_INTERFACE, name))))
764                 {
765                     err = cbor_value_advance(&repMap);
766                     OICFree(name);
767                     name = NULL;
768                     continue;
769                 }
770             }
771             CborType type = cbor_value_get_type(&repMap);
772             switch (type)
773             {
774                 case CborNullType:
775                     res = OCRepPayloadSetNull(curPayload, name);
776                     break;
777                 case CborIntegerType:
778                     {
779                         int64_t intval = 0;
780                         err = cbor_value_get_int64(&repMap, &intval);
781                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting int value");
782                         res = OCRepPayloadSetPropInt(curPayload, name, intval);
783                     }
784                     break;
785                 case CborDoubleType:
786                     {
787                         double doubleval = 0;
788                         err = cbor_value_get_double(&repMap, &doubleval);
789                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting double value");
790                         res = OCRepPayloadSetPropDouble(curPayload, name, doubleval);
791                     }
792                     break;
793                 case CborBooleanType:
794                     {
795                         bool boolval = false;
796                         err = cbor_value_get_boolean(&repMap, &boolval);
797                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting boolean value");
798                         res = OCRepPayloadSetPropBool(curPayload, name, boolval);
799                     }
800                     break;
801                 case CborTextStringType:
802                     {
803                         char *strval = NULL;
804                         err = cbor_value_dup_text_string(&repMap, &strval, &len, NULL);
805                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting string value");
806                         res = OCRepPayloadSetPropStringAsOwner(curPayload, name, strval);
807                     }
808                     break;
809                 case CborByteStringType:
810                     {
811                         uint8_t* bytestrval = NULL;
812                         err = cbor_value_dup_byte_string(&repMap, &bytestrval, &len, NULL);
813                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed getting byte string value");
814                         OCByteString tmp = {.bytes = bytestrval, .len = len};
815                         res = OCRepPayloadSetPropByteStringAsOwner(curPayload, name, &tmp);
816                     }
817                     break;
818                 case CborMapType:
819                     {
820                         OCRepPayload *pl = NULL;
821                         err = OCParseSingleRepPayload(&pl, &repMap, false);
822                         VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting parse single rep");
823                         res = OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl);
824                     }
825                     break;
826                 case CborArrayType:
827                     err = OCParseArray(curPayload, name, &repMap);
828                     break;
829                 default:
830                     OIC_LOG_V(ERROR, TAG, "Parsing rep property, unknown type %d", repMap.type);
831                     res = false;
832             }
833             if (type != CborArrayType)
834             {
835                 err = (CborError) !res;
836             }
837             VERIFY_CBOR_SUCCESS(TAG, err, "Failed setting value");
838
839             if (type != CborMapType && cbor_value_is_valid(&repMap))
840             {
841                 err = cbor_value_advance(&repMap);
842                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed advance repMap");
843             }
844             OICFree(name);
845             name = NULL;
846         }
847         if (cbor_value_is_container(objMap))
848         {
849             err = cbor_value_leave_container(objMap, &repMap);
850             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to leave container");
851         }
852         return err;
853     }
854
855 exit:
856     OICFree(name);
857     OCRepPayloadDestroy(*outPayload);
858     *outPayload = NULL;
859     return err;
860 }
861
862 static OCStackResult OCParseRepPayload(OCPayload **outPayload, CborValue *root)
863 {
864     OCStackResult ret = OC_STACK_INVALID_PARAM;
865     CborError err;
866     OCRepPayload *temp = NULL;
867     OCRepPayload *rootPayload = NULL;
868     OCRepPayload *curPayload = NULL;
869     CborValue rootMap = *root;
870     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
871     VERIFY_PARAM_NON_NULL(TAG, root, "Invalid Parameter root");
872
873     *outPayload = NULL;
874     if (cbor_value_is_array(root))
875     {
876         err = cbor_value_enter_container(root, &rootMap);
877         VERIFY_CBOR_SUCCESS(TAG, err, "Failed entering repMap");
878     }
879     while (cbor_value_is_valid(&rootMap))
880     {
881         temp = OCRepPayloadCreate();
882         ret = OC_STACK_NO_MEMORY;
883         VERIFY_PARAM_NON_NULL(TAG, temp, "Failed allocating memory");
884
885         CborValue curVal;
886         ret = OC_STACK_MALFORMED_RESPONSE;
887
888         // temporary fix to check for malformed cbor payload
889         if (!cbor_value_is_map(&rootMap) && !cbor_value_is_array(&rootMap)){
890             goto exit;
891         }
892
893         if (cbor_value_is_map(&rootMap))
894         {
895             err = cbor_value_map_find_value(&rootMap, OC_RSRVD_HREF, &curVal);
896             VERIFY_CBOR_SUCCESS(TAG, err, "to find href tag");
897             if (cbor_value_is_text_string(&curVal))
898             {
899                 size_t len = 0;
900                 err = cbor_value_dup_text_string(&curVal, &temp->uri, &len, NULL);
901                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find uri");
902             }
903         }
904
905         // Resource types
906         if (cbor_value_is_map(&rootMap))
907         {
908             if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal))
909             {
910                 err =  OCParseStringLL(&rootMap, OC_RSRVD_RESOURCE_TYPE, &temp->types);
911                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find rt type tag/value");
912             }
913         }
914
915         // Interface Types
916         if (cbor_value_is_map(&rootMap))
917         {
918             if (CborNoError == cbor_value_map_find_value(&rootMap, OC_RSRVD_INTERFACE, &curVal))
919             {
920                 err =  OCParseStringLL(&rootMap, OC_RSRVD_INTERFACE, &temp->interfaces);
921                 VERIFY_CBOR_SUCCESS(TAG, err, "Failed to find interfaces tag/value");
922             }
923         }
924
925         if (cbor_value_is_map(&rootMap))
926         {
927             err = OCParseSingleRepPayload(&temp, &rootMap, true);
928             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to parse single rep payload");
929         }
930
931         if(rootPayload == NULL)
932         {
933             rootPayload = temp;
934             curPayload = temp;
935         }
936         else
937         {
938             curPayload->next = temp;
939             curPayload = curPayload->next;
940         }
941
942         if (cbor_value_is_array(&rootMap))
943         {
944             err = cbor_value_advance(&rootMap);
945             VERIFY_CBOR_SUCCESS(TAG, err, "Failed to advance single rep payload");
946         }
947     }
948     *outPayload = (OCPayload *)rootPayload;
949     return OC_STACK_OK;
950
951 exit:
952     OCRepPayloadDestroy(temp);
953     OCRepPayloadDestroy(rootPayload);
954     OIC_LOG(ERROR, TAG, "CBOR error in ParseRepPayload");
955     return ret;
956 }
957
958 #ifdef WITH_PRESENCE
959 static OCStackResult OCParsePresencePayload(OCPayload **outPayload, CborValue *rootValue)
960 {
961     OCStackResult ret = OC_STACK_INVALID_PARAM;
962     OCPresencePayload *payload = NULL;
963     VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload");
964
965     *outPayload = NULL;
966
967     payload = (OCPresencePayload *)OICCalloc(1, sizeof(OCPresencePayload));
968     ret = OC_STACK_NO_MEMORY;
969     VERIFY_PARAM_NON_NULL(TAG, payload, "Failed allocating presence payload");
970     payload->base.type = PAYLOAD_TYPE_PRESENCE;
971     ret = OC_STACK_MALFORMED_RESPONSE;
972
973     if (cbor_value_is_map(rootValue))
974     {
975         CborValue curVal;
976         uint64_t temp = 0;
977         uint8_t trigger;
978
979         // Sequence Number
980         CborError err = cbor_value_map_find_value(rootValue, OC_RSRVD_NONCE, &curVal);
981         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce tag");
982         err = cbor_value_get_uint64(&curVal, &temp);
983         payload->sequenceNumber = (uint32_t)temp;
984         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding nonce value");
985
986         // Max Age
987         err = cbor_value_map_find_value(rootValue, OC_RSRVD_TTL, &curVal);
988         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl tag");
989         temp = 0;
990         err = cbor_value_get_uint64(&curVal, &temp);
991         payload->maxAge = (uint32_t)temp;
992         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding ttl value");
993
994         // Trigger
995         err = cbor_value_map_find_value(rootValue, OC_RSRVD_TRIGGER, &curVal);
996         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger tag");
997         err = cbor_value_get_simple_type(&curVal, &trigger);
998         VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding trigger value");
999         payload->trigger = (OCPresenceTrigger)trigger;
1000
1001         // Resource type name
1002         err = cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
1003         VERIFY_CBOR_SUCCESS(TAG, err, "to find res type tag");
1004         if (cbor_value_is_text_string(&curVal))
1005         {
1006             size_t len = 0;
1007             err = cbor_value_dup_text_string(&curVal, &payload->resourceType, &len, NULL);
1008             VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding resource type value");
1009         }
1010
1011         err = cbor_value_advance(rootValue);
1012         VERIFY_CBOR_SUCCESS(TAG, err, "Failed advancing root value");
1013
1014         *outPayload = (OCPayload *)payload;
1015         return OC_STACK_OK;
1016     }
1017 exit:
1018     OIC_LOG(ERROR, TAG, "CBOR error Parse Presence Payload");
1019     OCPresencePayloadDestroy(payload);
1020     return ret;
1021 }
1022 #endif // WITH_PRESENCE