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