Add collection payload to include each resource information separately
[platform/upstream/iotivity.git] / resource / csdk / stack / src / ocpayloadparse.c
index 203986f..1851d45 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
+// Defining _POSIX_C_SOURCE macro with 200112L (or greater) as value
+// causes header files to expose definitions
+// corresponding to the POSIX.1-2001 base
+// specification (excluding the XSI extension).
+// For POSIX.1-2001 base specification,
+// Refer http://pubs.opengroup.org/onlinepubs/009695399/
+// Required for strok_r
+#define _POSIX_C_SOURCE 200112L
+#include <string.h>
 #include "ocpayloadcbor.h"
 #include <stdlib.h>
 #include "logger.h"
+#include "oic_string.h"
 #include "oic_malloc.h"
 #include "ocstackinternal.h"
 #include "ocpayload.h"
 #include "cbor.h"
+#include "oic_string.h"
+#include "payload_logging.h"
+#include "rdpayload.h"
 
-#define TAG PCF("OCPayloadParse")
+#define TAG "OCPayloadParse"
 
 static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue* arrayVal);
 static OCStackResult OCParseDevicePayload(OCPayload** outPayload, CborValue* arrayVal);
@@ -36,59 +49,43 @@ static OCStackResult OCParseRepPayload(OCPayload** outPayload, CborValue* arrayV
 static OCStackResult OCParsePresencePayload(OCPayload** outPayload, CborValue* arrayVal);
 static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, CborValue* arrayVal);
 
-OCStackResult OCParsePayload(OCPayload** outPayload, const uint8_t* payload, size_t payloadSize)
+OCStackResult OCParsePayload(OCPayload** outPayload, OCPayloadType payloadType,
+        const uint8_t* payload, size_t payloadSize)
 {
     CborParser parser;
     CborValue rootValue;
     bool err = false;
 
-    OC_LOG_V(INFO, TAG, "CBOR Parsing size: %d", payloadSize, payload);
+    OC_LOG_V(INFO, TAG, "CBOR Parsing size: %d", payloadSize);
     if((err = cbor_parser_init(payload, payloadSize, 0, &parser, &rootValue)) != false)
     {
         OC_LOG_V(ERROR, TAG, "CBOR Parser init failed: %d", err);
         return OC_STACK_ERROR;
     }
 
-    if(!cbor_value_is_array(&rootValue))
-    {
-        OC_LOG_V(ERROR, TAG, "CBOR payload root object is not an array :%x", rootValue.type);
-        return OC_STACK_MALFORMED_RESPONSE;
-    }
-
-    CborValue arrayValue;
-    // enter the array
-    err = err || cbor_value_enter_container(&rootValue, &arrayValue);
-
-    int payloadType;
-    err = err || cbor_value_get_int(&arrayValue, &payloadType);
-    err = err || cbor_value_advance_fixed(&arrayValue);
-
-    if(err)
-    {
-        OC_LOG_V(ERROR, TAG, "CBOR payload parse failed :%d", err);
-        return OC_STACK_MALFORMED_RESPONSE;
-    }
-
     OCStackResult result = OC_STACK_ERROR;
     switch(payloadType)
     {
         case PAYLOAD_TYPE_DISCOVERY:
-            result = OCParseDiscoveryPayload(outPayload, &arrayValue);
+            result = OCParseDiscoveryPayload(outPayload, &rootValue);
             break;
         case PAYLOAD_TYPE_DEVICE:
-            result = OCParseDevicePayload(outPayload, &arrayValue);
+            result = OCParseDevicePayload(outPayload, &rootValue);
             break;
         case PAYLOAD_TYPE_PLATFORM:
-            result = OCParsePlatformPayload(outPayload, &arrayValue);
+            result = OCParsePlatformPayload(outPayload, &rootValue);
             break;
         case PAYLOAD_TYPE_REPRESENTATION:
-            result = OCParseRepPayload(outPayload, &arrayValue);
+            result = OCParseRepPayload(outPayload, &rootValue);
             break;
         case PAYLOAD_TYPE_PRESENCE:
-            result = OCParsePresencePayload(outPayload, &arrayValue);
+            result = OCParsePresencePayload(outPayload, &rootValue);
             break;
         case PAYLOAD_TYPE_SECURITY:
-            result = OCParseSecurityPayload(outPayload, &arrayValue);
+            result = OCParseSecurityPayload(outPayload, &rootValue);
+            break;
+        case PAYLOAD_TYPE_RD:
+            result = OCRDCborToPayload(&rootValue, outPayload);
             break;
         default:
             OC_LOG_V(ERROR, TAG, "ParsePayload Type default: %d", payloadType);
@@ -96,15 +93,7 @@ OCStackResult OCParsePayload(OCPayload** outPayload, const uint8_t* payload, siz
             break;
     }
 
-    if(result == OC_STACK_OK)
-    {
-        err = err || cbor_value_leave_container(&rootValue, &arrayValue);
-        if(err != CborNoError)
-        {
-            return OC_STACK_MALFORMED_RESPONSE;
-        }
-    }
-    else
+    if(result != OC_STACK_OK)
     {
         OC_LOG_V(INFO, TAG, "Finished parse payload, result is %d", result);
     }
@@ -114,33 +103,25 @@ OCStackResult OCParsePayload(OCPayload** outPayload, const uint8_t* payload, siz
 
 void OCFreeOCStringLL(OCStringLL* ll);
 
-static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, CborValue* arrayVal)
+static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, CborValue* rootValue)
 {
-    bool err = false;
-    char * securityData = NULL;
-
-    if(cbor_value_is_map(arrayVal))
-    {
-        CborValue curVal;
-        err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_REPRESENTATION, &curVal);
-
-        if(cbor_value_is_valid(&curVal))
-        {
-            size_t len;
-            err = err || cbor_value_dup_text_string(&curVal, &securityData, &len, NULL);
-        }
-    }
-    else
+    if (!outPayload)
     {
-        OC_LOG_V(ERROR, TAG, PCF("Cbor main value not a map"));
-        return OC_STACK_MALFORMED_RESPONSE;
+        return OC_STACK_INVALID_PARAM;
     }
 
-    err = err || cbor_value_advance(arrayVal);
+    bool err = false;
+    char * securityData = NULL;
+    CborValue map;
+    size_t len;
+
+    err = err || cbor_value_enter_container(rootValue, &map);
+    err = err || cbor_value_dup_text_string(&map, &securityData, &len, NULL);
+    err = err || cbor_value_leave_container(rootValue, &map);
 
     if(err)
     {
-        OC_LOG_V(ERROR, TAG, "Cbor in error condition");
+        OC_LOG(ERROR, TAG, "Cbor in error condition");
         OICFree(securityData);
         return OC_STACK_MALFORMED_RESPONSE;
     }
@@ -152,221 +133,313 @@ static OCStackResult OCParseSecurityPayload(OCPayload** outPayload, CborValue* a
 
 }
 
-static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue* arrayVal)
+static char* InPlaceStringTrim(char* str)
+{
+    while (str[0] == ' ')
+    {
+        ++str;
+    }
+
+    size_t lastchar = strlen(str);
+
+    while (str[lastchar] == ' ')
+    {
+        str[lastchar] = '\0';
+        --lastchar;
+    }
+
+    return str;
+}
+
+static OCStackResult OCParseDiscoveryPayload(OCPayload** outPayload, CborValue* rootValue)
 {
+    if (!outPayload)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
     bool err = false;
+    OCResourcePayload* resource = NULL;
+    uint16_t resourceCount = 0;
+    CborValue resourceMap = {};
 
     OCDiscoveryPayload* out = OCDiscoveryPayloadCreate();
-
     if(!out)
     {
         return OC_STACK_NO_MEMORY;
     }
 
-    size_t resourceCount = 0;
-    while(!err &&
-            cbor_value_is_map(arrayVal))
+    // Root value is already inside the main root array
+    CborValue rootMap = {};
+
+    // Enter the main root map
+    err = err || cbor_value_enter_container(rootValue, &rootMap);
+    // Look for DI
+    CborValue curVal = {};
+    err = cbor_value_map_find_value(&rootMap, OC_RSRVD_DEVICE_ID, &curVal);
+    if (CborNoError != err)
+    {
+        OC_LOG(ERROR, TAG, "Cbor find value failed.");
+        goto malformed_cbor;
+    }
+    size_t len;
+    err = cbor_value_dup_byte_string(&curVal, &(out->sid), &len, NULL);
+
+    // Look for Links which will have an array as the value
+    err = cbor_value_map_find_value(&rootMap, OC_RSRVD_LINKS, &curVal);
+    if (CborNoError != err)
+    {
+        OC_LOG(ERROR, TAG, "Cbor find value failed.");
+        goto malformed_cbor;
+    }
+
+    // Enter the links array and start iterating through the array processing
+    // each resource which shows up as a map.
+    err = err || cbor_value_enter_container(&curVal, &resourceMap);
+
+    while (cbor_value_is_map(&resourceMap))
     {
-        OCResourcePayload* resource = (OCResourcePayload*)OICCalloc(1, sizeof(OCResourcePayload));
+        resource = (OCResourcePayload*)OICCalloc(1, sizeof(OCResourcePayload));
         if(!resource)
         {
-            OC_LOG_V(ERROR, TAG, "Memory allocation failed");
+            OC_LOG(ERROR, TAG, "Memory allocation failed");
+            OCDiscoveryPayloadDestroy(out);
             return OC_STACK_NO_MEMORY;
         }
-        CborValue curVal;
 
         // Uri
-        err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_HREF, &curVal);
-        size_t len;
-        err = err || cbor_value_dup_text_string(&curVal, &(resource->uri), &len, NULL);
-
-        // SID
-        err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_SERVER_INSTANCE_ID, &curVal);
-        err = err || cbor_value_dup_byte_string(&curVal, &(resource->sid), &len, NULL);
-
-        // Prop Tag
+        CborValue uriVal = {};
+        err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_HREF, &uriVal);
+        if (CborNoError != err)
         {
-             err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_PROPERTY, &curVal);
-            // ResourceTypes
-            CborValue rtArray;
-             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_RESOURCE_TYPE, &rtArray);
-
-            CborValue rtVal;
-             err = err || cbor_value_enter_container(&rtArray, &rtVal);
-
-            OCStringLL* llPtr = NULL;
-            while(!err && cbor_value_is_text_string(&rtVal))
+            OC_LOG(ERROR, TAG, "Cbor finding href type failed.");
+            goto malformed_cbor;
+        }
+        err = cbor_value_dup_text_string(&uriVal, &(resource->uri), &len, NULL);
+        if (CborNoError != err)
+        {
+            OC_LOG(ERROR, TAG, "Cbor finding href value failed.");
+            goto malformed_cbor;
+        }
+        // ResourceTypes
+        CborValue rtVal = {};
+        err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_RESOURCE_TYPE, &rtVal);
+        if (CborNoError != err)
+        {
+            OC_LOG(ERROR, TAG, "Cbor finding rt type failed.");
+            goto malformed_cbor;
+        }
+        if (cbor_value_is_text_string(&rtVal))
+        {
+            char* input = NULL;
+            char* savePtr;
+            err = cbor_value_dup_text_string(&rtVal, &input, &len, NULL);
+            if (CborNoError != err)
             {
-                if(resource->types == NULL)
-                {
-                    resource->types = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
-                    llPtr = resource->types;
-                    if(!llPtr)
-                    {
-                        OC_LOG_V(ERROR, TAG, "Memory allocation failed");
-                        OICFree(resource->uri);
-                        OICFree(resource->sid);
-                        OICFree(resource);
-                        return OC_STACK_NO_MEMORY;
-                    }
-                }
-                else
+                OC_LOG(ERROR, TAG, "Cbor finding rt value failed.");
+                goto malformed_cbor;
+            }
+            if (input)
+            {
+                char* curPtr = strtok_r(input, " ", &savePtr);
+
+                while (curPtr)
                 {
-                    llPtr->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
-                    llPtr = llPtr->next;
-                    if(!llPtr)
+                    char* trimmed = InPlaceStringTrim(curPtr);
+                    if (trimmed[0] !='\0')
                     {
-                        OC_LOG_V(ERROR, TAG, "Memory allocation failed");
-                        OICFree(resource->uri);
-                        OICFree(resource->sid);
-                        OCFreeOCStringLL(resource->types);
-                        OICFree(resource);
-                        return OC_STACK_NO_MEMORY;
+                        if (!OCResourcePayloadAddResourceType(resource, trimmed))
+                        {
+                            OICFree(resource->uri);
+                            OCFreeOCStringLL(resource->types);
+                            OICFree(resource);
+                            OCDiscoveryPayloadDestroy(out);
+                            return OC_STACK_NO_MEMORY;
+                        }
                     }
-
+                    curPtr = strtok_r(NULL, " ", &savePtr);
                 }
-
-                 err = err || cbor_value_dup_text_string(&rtVal, &(llPtr->value), &len, NULL);
-                 err = err || cbor_value_advance(&rtVal);
+                OICFree(input);
             }
+        }
 
-             err = err || cbor_value_leave_container(&rtArray, &rtVal);
-            //
-            // Interface Types
-            CborValue ifArray;
-             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_INTERFACE, &ifArray);
-            CborValue ifVal;
-             err = err || cbor_value_enter_container(&ifArray, &ifVal);
-
-            llPtr = NULL;
-            while(!err && cbor_value_is_text_string(&ifVal))
+        // Interface Types
+        CborValue ifVal = {};
+        err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_INTERFACE, &ifVal);
+        if (CborNoError != err)
+        {
+            OC_LOG(ERROR, TAG, "Cbor finding if type failed.");
+            goto malformed_cbor;
+        }
+        if (!err && cbor_value_is_text_string(&ifVal))
+        {
+            char* input = NULL;
+            char* savePtr;
+            err = cbor_value_dup_text_string(&ifVal, &input, &len, NULL);
+            if (CborNoError != err)
             {
-                if(resource->interfaces == NULL)
-                {
-                    resource->interfaces = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
-                    llPtr = resource->interfaces;
-                    if(!llPtr)
-                    {
-                        OC_LOG_V(ERROR, TAG, "Memory allocation failed");
-                        OICFree(resource->uri);
-                        OICFree(resource->sid);
-                        OCFreeOCStringLL(resource->types);
-                        OICFree(resource);
-                        return OC_STACK_NO_MEMORY;
-                    }
-                }
-                else
+                OC_LOG(ERROR, TAG, "Cbor finding if value failed.");
+                goto malformed_cbor;
+            }
+            if (input)
+            {
+                char* curPtr = strtok_r(input, " ", &savePtr);
+
+                while (curPtr)
                 {
-                    llPtr->next = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
-                    llPtr = llPtr->next;
-                    if(!llPtr)
+                    char* trimmed = InPlaceStringTrim(curPtr);
+                    if (trimmed[0] !='\0')
                     {
-                        OC_LOG_V(ERROR, TAG, "Memory allocation failed");
-                        OICFree(resource->uri);
-                        OICFree(resource->sid);
-                        OCFreeOCStringLL(resource->types);
-                        OCFreeOCStringLL(resource->interfaces);
-                        OICFree(resource);
-                        return OC_STACK_NO_MEMORY;
+                        if (!OCResourcePayloadAddInterface(resource, trimmed))
+                        {
+                            OICFree(resource->uri);
+                            OCFreeOCStringLL(resource->types);
+                            OICFree(resource);
+                            OCDiscoveryPayloadDestroy(out);
+                            return OC_STACK_NO_MEMORY;
+                        }
                     }
+                    curPtr = strtok_r(NULL, " ", &savePtr);
                 }
-
-                 err = err || cbor_value_dup_text_string(&ifVal, &(llPtr->value), &len, NULL);
-                 err = err || cbor_value_advance(&ifVal);
+                OICFree(input);
             }
-             err = err || cbor_value_leave_container(&ifArray, &ifVal);
+        }
 
-            // Policy
+        // Policy
+        CborValue policyMap = {};
+        err = cbor_value_map_find_value(&resourceMap, OC_RSRVD_POLICY, &policyMap);
+        if (CborNoError != err)
+        {
+            OC_LOG(ERROR, TAG, "Cbor finding policy type failed.");
+            goto malformed_cbor;
+        }
+        // Bitmap
+        CborValue val = {};
+        err = cbor_value_map_find_value(&policyMap, OC_RSRVD_BITMAP, &val);
+        if (CborNoError != err)
+        {
+            OC_LOG(ERROR, TAG, "Cbor finding bitmap type failed.");
+            goto malformed_cbor;
+        }
+        uint64_t temp = 0;
+        err = cbor_value_get_uint64(&val, &temp);
+        if (CborNoError != err)
+        {
+            OC_LOG(ERROR, TAG, "Cbor finding bitmap value failed.");
+            goto malformed_cbor;
+        }
+        resource->bitmap = (uint8_t)temp;
+        // Secure Flag
+        err = cbor_value_map_find_value(&policyMap, OC_RSRVD_SECURE, &val);
+        if (CborNoError != err)
+        {
+            OC_LOG(ERROR, TAG, "Cbor finding secure type failed.");
+            goto malformed_cbor;
+        }
+        if(cbor_value_is_valid(&val))
+        {
+            err = cbor_value_get_boolean(&val, &(resource->secure));
+            if (CborNoError != err)
             {
-                CborValue policyMap;
-                err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_POLICY, &policyMap);
-
-                // Bitmap
-                CborValue val;
-                err = err || cbor_value_map_find_value(&policyMap, OC_RSRVD_BITMAP, &val);
-                uint64_t temp = 0;
-                err = err || cbor_value_get_uint64(&val, &temp);
-                resource->bitmap = (uint8_t)temp;
-                // Secure Flag
-                err = err || cbor_value_map_find_value(&policyMap, OC_RSRVD_SECURE, &val);
-                if(cbor_value_is_valid(&val))
+                OC_LOG(ERROR, TAG, "Cbor finding secure value failed.");
+                goto malformed_cbor;
+            }
+            // Port
+            CborValue port;
+            err = cbor_value_map_find_value(&policyMap, OC_RSRVD_HOSTING_PORT,
+                            &port);
+            if (CborNoError != err)
+            {
+                OC_LOG(ERROR, TAG, "Cbor finding port type failed.");
+                goto malformed_cbor;
+            }
+            if(cbor_value_is_valid(&port))
+            {
+                err = cbor_value_get_uint64(&port, &temp);
+                if (CborNoError != err)
                 {
-                    err = err || cbor_value_get_boolean(&val, &(resource->secure));
-                    // Port
-                    CborValue port;
-                    err = err || cbor_value_map_find_value(&policyMap, OC_RSRVD_HOSTING_PORT,
-                                    &port);
-                    if(cbor_value_is_valid(&port))
-                    {
-                        err = err || cbor_value_get_uint64(&port, &temp);
-                        resource->port = (uint16_t)temp;
-                    }
+                    OC_LOG(ERROR, TAG, "Cbor finding port value failed.");
+                    goto malformed_cbor;
                 }
+                resource->port = (uint16_t)temp;
             }
         }
 
-         err = err || cbor_value_advance(arrayVal);
-        if(err)
+        err = cbor_value_advance(&resourceMap);
+        if (CborNoError != err)
         {
-            OICFree(resource->uri);
-            OICFree(resource->sid);
-            OCFreeOCStringLL(resource->types);
-            OCFreeOCStringLL(resource->interfaces);
-            OICFree(resource);
-            OCDiscoveryPayloadDestroy(out);
-            OC_LOG_V(ERROR, TAG, "CBOR in error condition", err);
-            return OC_STACK_MALFORMED_RESPONSE;
+            OC_LOG(ERROR, TAG, "Cbor advance value failed.");
+            goto malformed_cbor;
         }
         ++resourceCount;
         OCDiscoveryPayloadAddNewResource(out, resource);
     }
 
-    *outPayload = (OCPayload*)out;
+    err = err || cbor_value_leave_container(rootValue, &resourceMap);
 
+    *outPayload = (OCPayload*)out;
     return OC_STACK_OK;
+
+malformed_cbor:
+    OICFree(resource->uri);
+    OCFreeOCStringLL(resource->types);
+    OCFreeOCStringLL(resource->interfaces);
+    OICFree(resource);
+    OCDiscoveryPayloadDestroy(out);
+    return OC_STACK_MALFORMED_RESPONSE;
+
+cbor_error:
+    OCDiscoveryCollectionPayloadDestroy(out);
+    return OC_STACK_MALFORMED_RESPONSE;
 }
 
-static OCStackResult OCParseDevicePayload(OCPayload** outPayload, CborValue* arrayVal)
+static OCStackResult OCParseDevicePayload(OCPayload** outPayload, CborValue* rootValue)
 {
+    if (!outPayload)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
     bool err = false;
 
-    if(cbor_value_is_map(arrayVal))
+    if(cbor_value_is_map(rootValue))
     {
-        char* uri = NULL;
         uint8_t* sid = NULL;
         char* dname = NULL;
         char* specVer = NULL;
         char* dmVer = NULL;
-        CborValue curVal;
-         err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_HREF, &curVal);
-        size_t len;
-         err = err || cbor_value_dup_text_string(&curVal, &uri, &len, NULL);
 
-        // Representation
+        CborValue repVal;
+        // Device ID
+        err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_DEVICE_ID, &repVal);
+        size_t len;
+        if(cbor_value_is_valid(&repVal))
         {
-             err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_REPRESENTATION, &curVal);
-
-            CborValue repVal;
-            // Device ID
-             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_DEVICE_ID, &repVal);
-             err = err || cbor_value_dup_byte_string(&repVal, &sid, &len, NULL);
-            // Device Name
-             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_DEVICE_NAME, &repVal);
-             err = err || cbor_value_dup_text_string(&repVal, &dname, &len, NULL);
-            // Device Spec Version
-             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_SPEC_VERSION, &repVal);
-             err = err || cbor_value_dup_text_string(&repVal, &specVer, &len, NULL);
-            // Data Model Version
-             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_DATA_MODEL_VERSION, &repVal);
-             err = err || cbor_value_dup_text_string(&repVal, &dmVer, &len, NULL);
-
+            err = err || cbor_value_dup_byte_string(&repVal, &sid, &len, NULL);
+        }
+        // Device Name
+        err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_DEVICE_NAME, &repVal);
+        if(cbor_value_is_valid(&repVal))
+        {
+            err = err || cbor_value_dup_text_string(&repVal, &dname, &len, NULL);
+        }
+        // Device Spec Version
+        err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_SPEC_VERSION, &repVal);
+        if(cbor_value_is_valid(&repVal))
+        {
+            err = err || cbor_value_dup_text_string(&repVal, &specVer, &len, NULL);
+        }
+        // Data Model Version
+        err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_DATA_MODEL_VERSION, &repVal);
+        if (cbor_value_is_valid(&repVal))
+        {
+            err = err || cbor_value_dup_text_string(&repVal, &dmVer, &len, NULL);
         }
 
-         err = err || cbor_value_advance(arrayVal);
+        err = err || cbor_value_advance(rootValue);
 
         if(err)
         {
-            OICFree(uri);
             OICFree(sid);
             OICFree(dname);
             OICFree(specVer);
@@ -375,9 +448,8 @@ static OCStackResult OCParseDevicePayload(OCPayload** outPayload, CborValue* arr
             return OC_STACK_MALFORMED_RESPONSE;
         }
 
-        *outPayload = (OCPayload*)OCDevicePayloadCreate(uri, sid, dname, specVer, dmVer);
+        *outPayload = (OCPayload*)OCDevicePayloadCreate(sid, dname, specVer, dmVer);
 
-        OICFree(uri);
         OICFree(sid);
         OICFree(dname);
         OICFree(specVer);
@@ -391,108 +463,109 @@ static OCStackResult OCParseDevicePayload(OCPayload** outPayload, CborValue* arr
     }
     else
     {
-        OC_LOG(ERROR, TAG, PCF("Root device node was not a map"));
+        OC_LOG(ERROR, TAG, "Root device node was not a map");
         return OC_STACK_MALFORMED_RESPONSE;
     }
 
 }
 
-static OCStackResult OCParsePlatformPayload(OCPayload** outPayload, CborValue* arrayVal)
+static OCStackResult OCParsePlatformPayload(OCPayload** outPayload, CborValue* rootValue)
 {
+    if (!outPayload)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
     bool err = false;
 
-    if(cbor_value_is_map(arrayVal))
+    if(cbor_value_is_map(rootValue))
     {
-        char* uri = NULL;
-        OCPlatformInfo info = {};
-        CborValue curVal;
-         err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_HREF, &curVal);
-        size_t len;
-         err = err || cbor_value_dup_text_string(&curVal, &uri, &len, NULL);
-
-        // Representation
-        {
-             err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_REPRESENTATION, &curVal);
+        OCPlatformInfo info = {0};
 
-            CborValue repVal;
-            // Platform ID
-             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_PLATFORM_ID, &repVal);
+        CborValue repVal;
+        size_t len;
+        // Platform ID
+        err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_ID, &repVal);
+        if(cbor_value_is_valid(&repVal))
+         {
              err = err || cbor_value_dup_text_string(&repVal, &(info.platformID), &len, NULL);
+         }
 
-            // MFG Name
-             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_MFG_NAME, &repVal);
+         // MFG Name
+         err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_NAME, &repVal);
+         if(cbor_value_is_valid(&repVal))
+         {
              err = err || cbor_value_dup_text_string(&repVal, &(info.manufacturerName), &len, NULL);
+         }
 
-            // MFG URL
-             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_MFG_URL, &repVal);
-            if(cbor_value_is_valid(&repVal))
-            {
-                 err = err || cbor_value_dup_text_string(&repVal, &(info.manufacturerUrl), &len, NULL);
-            }
+        // MFG URL
+        err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_URL, &repVal);
+        if(cbor_value_is_valid(&repVal))
+        {
+             err = err || cbor_value_dup_text_string(&repVal, &(info.manufacturerUrl), &len, NULL);
+        }
 
-            // Model Num
-             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_MODEL_NUM, &repVal);
-            if(cbor_value_is_valid(&repVal))
-            {
-                 err = err || cbor_value_dup_text_string(&repVal, &(info.modelNumber), &len, NULL);
-            }
+        // Model Num
+        err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_MODEL_NUM, &repVal);
+        if(cbor_value_is_valid(&repVal))
+        {
+             err = err || cbor_value_dup_text_string(&repVal, &(info.modelNumber), &len, NULL);
+        }
 
-            // Date of Mfg
-             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_MFG_DATE, &repVal);
-            if(cbor_value_is_valid(&repVal))
-            {
-                 err = err || cbor_value_dup_text_string(&repVal, &(info.dateOfManufacture), &len,
-                        NULL);
-            }
+        // Date of Mfg
+        err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_MFG_DATE, &repVal);
+        if(cbor_value_is_valid(&repVal))
+        {
+             err = err || cbor_value_dup_text_string(&repVal, &(info.dateOfManufacture), &len,
+                    NULL);
+        }
 
-            // Platform Version
-             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_PLATFORM_VERSION, &repVal);
-            if(cbor_value_is_valid(&repVal))
-            {
-                 err = err || cbor_value_dup_text_string(&repVal, &(info.platformVersion), &len,
-                        NULL);
-            }
+        // Platform Version
+        err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_PLATFORM_VERSION, &repVal);
+        if(cbor_value_is_valid(&repVal))
+        {
+             err = err || cbor_value_dup_text_string(&repVal, &(info.platformVersion), &len, NULL);
+        }
 
-            // OS Version
-             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_OS_VERSION, &repVal);
-            if(cbor_value_is_valid(&repVal))
-            {
-                 err = err || cbor_value_dup_text_string(&repVal, &(info.operatingSystemVersion),
-                        &len, NULL);
-            }
+        // OS Version
+        err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_OS_VERSION, &repVal);
+        if(cbor_value_is_valid(&repVal))
+        {
+             err = err || cbor_value_dup_text_string(&repVal, &(info.operatingSystemVersion),
+                    &len, NULL);
+        }
 
-            // Hardware Version
-             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_HARDWARE_VERSION, &repVal);
-            if(cbor_value_is_valid(&repVal))
-            {
-                 err = err || cbor_value_dup_text_string(&repVal, &(info.hardwareVersion), &len,
-                        NULL);
-            }
+        // Hardware Version
+        err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_HARDWARE_VERSION, &repVal);
+        if(cbor_value_is_valid(&repVal))
+        {
+             err = err || cbor_value_dup_text_string(&repVal, &(info.hardwareVersion), &len,
+                    NULL);
+        }
 
-            // Firmware Version
-             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_FIRMWARE_VERSION, &repVal);
-            if(cbor_value_is_valid(&repVal))
-            {
-                 err = err || cbor_value_dup_text_string(&repVal, &(info.firmwareVersion), &len,
-                        NULL);
-            }
+        // Firmware Version
+        err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_FIRMWARE_VERSION, &repVal);
+        if(cbor_value_is_valid(&repVal))
+        {
+             err = err || cbor_value_dup_text_string(&repVal, &(info.firmwareVersion), &len,
+                    NULL);
+        }
 
-            // Support URL
-             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_SUPPORT_URL, &repVal);
-            if(cbor_value_is_valid(&repVal))
-            {
-                 err = err || cbor_value_dup_text_string(&repVal, &(info.supportUrl), &len, NULL);
-            }
+        // Support URL
+        err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_SUPPORT_URL, &repVal);
+        if(cbor_value_is_valid(&repVal))
+        {
+             err = err || cbor_value_dup_text_string(&repVal, &(info.supportUrl), &len, NULL);
+        }
 
-            // System Time
-             err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_SYSTEM_TIME, &repVal);
-            if(cbor_value_is_valid(&repVal))
-            {
-                 err = err || cbor_value_dup_text_string(&repVal, &(info.systemTime), &len, NULL);
-            }
+        // System Time
+        err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_SYSTEM_TIME, &repVal);
+        if(cbor_value_is_valid(&repVal))
+        {
+             err = err || cbor_value_dup_text_string(&repVal, &(info.systemTime), &len, NULL);
         }
 
-         err = err || cbor_value_advance(arrayVal);
+        err = err || cbor_value_advance(rootValue);
 
         if(err)
         {
@@ -507,11 +580,11 @@ static OCStackResult OCParsePlatformPayload(OCPayload** outPayload, CborValue* a
             OICFree(info.platformVersion);
             OICFree(info.supportUrl);
             OICFree(info.systemTime);
-            OC_LOG(ERROR, TAG, PCF("CBOR error In ParsePlatformPayload"));
+            OC_LOG(ERROR, TAG, "CBOR error In ParsePlatformPayload");
             return OC_STACK_MALFORMED_RESPONSE;
         }
 
-        *outPayload = (OCPayload*)OCPlatformPayloadCreateAsOwner(uri, &info);
+        *outPayload = (OCPayload*)OCPlatformPayloadCreateAsOwner(&info);
 
         if(!*outPayload)
         {
@@ -522,229 +595,460 @@ static OCStackResult OCParsePlatformPayload(OCPayload** outPayload, CborValue* a
     }
     else
     {
-        OC_LOG(ERROR, TAG, PCF("Root device node was not a map"));
+        OC_LOG(ERROR, TAG, "Root device node was not a map");
         return OC_STACK_MALFORMED_RESPONSE;
     }
 }
 
-static bool OCParseArray(OCRepPayload* out, const char* name, CborValue* container)
+static OCRepPayloadPropType DecodeCborType(CborType type)
+{
+    switch (type)
+    {
+            case CborNullType:
+                return OCREP_PROP_NULL;
+            case CborIntegerType:
+                return OCREP_PROP_INT;
+            case CborDoubleType:
+                return OCREP_PROP_DOUBLE;
+            case CborBooleanType:
+                return OCREP_PROP_BOOL;
+            case CborTextStringType:
+                return OCREP_PROP_STRING;
+            case CborByteStringType:
+                return OCREP_PROP_BYTE_STRING;
+            case CborMapType:
+                return OCREP_PROP_OBJECT;
+            case CborArrayType:
+                return OCREP_PROP_ARRAY;
+            default:
+                return OCREP_PROP_NULL;
+    }
+}
+static bool OCParseArrayFindDimensionsAndType(const CborValue* parent, size_t dimensions[MAX_REP_ARRAY_DEPTH],
+        OCRepPayloadPropType* type)
 {
+    bool err = false;
     CborValue insideArray;
+    *type = OCREP_PROP_NULL;
+    dimensions[0] = dimensions[1] = dimensions[2] = 0;
+
+    err = err || cbor_value_enter_container(parent, &insideArray);
+
+    while (cbor_value_is_valid(&insideArray))
+    {
+        OCRepPayloadPropType tempType = DecodeCborType(cbor_value_get_type(&insideArray));
+
+        if (tempType == OCREP_PROP_ARRAY)
+        {
+            size_t subdim[MAX_REP_ARRAY_DEPTH];
+            tempType = OCREP_PROP_NULL;
+            err = err || OCParseArrayFindDimensionsAndType(&insideArray, subdim, &tempType);
+
+            if (subdim[2] != 0)
+            {
+                OC_LOG(ERROR, TAG, "Parse array helper, sub-array too deep");
+            }
+
+            dimensions[1] = dimensions[1] >= subdim[0] ? dimensions[1] : subdim[0];
+            dimensions[2] = dimensions[2] >= subdim[1] ? dimensions[2] : subdim[1];
+
+            if (*type != OCREP_PROP_NULL && tempType != OCREP_PROP_NULL
+                    && *type != tempType)
+            {
+                OC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed (subtype)");
+                return true;
+            }
+            else if (*type == OCREP_PROP_NULL)
+            {
+                // We don't know the type of this array yet, so the assignment is OK
+                *type = tempType;
+            }
+        }
+        else if (*type == OCREP_PROP_NULL)
+        {
+            // We don't know the type of this array yet, so the assignment is OK
+            *type = tempType;
+        }
+        // tempType is allowed to be NULL, since it might now know the answer yet
+        else if (tempType != OCREP_PROP_NULL && *type != tempType)
+        {
+            // this is an invalid situation!
+            OC_LOG(ERROR, TAG, "Array parse failed, mixed arrays not allowed");
+            return true;
+        }
+
+        ++dimensions[0];
+        cbor_value_advance(&insideArray);
+    }
+
+    return err;
+}
+
+static size_t getAllocSize(OCRepPayloadPropType type)
+{
+    switch (type)
+    {
+        case OCREP_PROP_INT:
+            return sizeof (int64_t);
+        case OCREP_PROP_DOUBLE:
+            return sizeof (double);
+        case OCREP_PROP_BOOL:
+            return sizeof (bool);
+        case OCREP_PROP_STRING:
+            return sizeof (char*);
+        case OCREP_PROP_BYTE_STRING:
+            return sizeof (OCByteString);
+        case OCREP_PROP_OBJECT:
+            return sizeof (OCRepPayload*);
+        default:
+            return 0;
+    }
+}
+
+static size_t arrayStep(size_t dimensions[MAX_REP_ARRAY_DEPTH], size_t elementNum)
+{
+    return
+        (dimensions[1] == 0 ? 1 : dimensions[1]) *
+        (dimensions[2] == 0 ? 1 : dimensions[2]) *
+        elementNum;
+}
+
+static bool OCParseArrayFillArray(const CborValue* parent, size_t dimensions[MAX_REP_ARRAY_DEPTH],
+        OCRepPayloadPropType type, void* targetArray)
+{
     bool err = false;
-    uint64_t tempInt = 0;
+    CborValue insideArray;
+
+    err = err || cbor_value_enter_container(parent, &insideArray);
+
+    size_t i = 0;
+    char* tempStr = NULL;
+    OCByteString ocByteStr = { .bytes = NULL, .len = 0};
+    size_t tempLen = 0;
+    OCRepPayload* tempPl = NULL;
+
+    size_t newdim[MAX_REP_ARRAY_DEPTH];
+    newdim[0] = dimensions[1];
+    newdim[1] = dimensions[2];
+    newdim[2] = 0;
+
+    while (!err && i < dimensions[0] && cbor_value_is_valid(&insideArray))
+    {
+        bool noAdvance = false;
+        if (cbor_value_get_type(&insideArray) != CborNullType)
+        {
+            switch (type)
+            {
+                case OCREP_PROP_INT:
+                    if (dimensions[1] == 0)
+                    {
+                        err = err || cbor_value_get_int64(&insideArray,
+                                &(((int64_t*)targetArray)[i]));
+                    }
+                    else
+                    {
+                        err = err || OCParseArrayFillArray(&insideArray, newdim,
+                            type,
+                            &(((int64_t*)targetArray)[arrayStep(dimensions, i)])
+                            );
+                    }
+                    break;
+                case OCREP_PROP_DOUBLE:
+                    if (dimensions[1] == 0)
+                    {
+                        err = err || cbor_value_get_double(&insideArray,
+                                &(((double*)targetArray)[i]));
+                    }
+                    else
+                    {
+                        err = err || OCParseArrayFillArray(&insideArray, newdim,
+                            type,
+                            &(((double*)targetArray)[arrayStep(dimensions, i)])
+                            );
+                    }
+                    break;
+                case OCREP_PROP_BOOL:
+                    if (dimensions[1] == 0)
+                    {
+                        err = err || cbor_value_get_boolean(&insideArray,
+                                &(((bool*)targetArray)[i]));
+                    }
+                    else
+                    {
+                        err = err || OCParseArrayFillArray(&insideArray, newdim,
+                            type,
+                            &(((bool*)targetArray)[arrayStep(dimensions, i)])
+                            );
+                    }
+                    break;
+                case OCREP_PROP_STRING:
+                    if (dimensions[1] == 0)
+                    {
+                        err = err || cbor_value_dup_text_string(&insideArray,
+                                &tempStr, &tempLen, NULL);
+                        ((char**)targetArray)[i] = tempStr;
+                        tempStr = NULL;
+                    }
+                    else
+                    {
+                        err = err || OCParseArrayFillArray(&insideArray, newdim,
+                            type,
+                            &(((char**)targetArray)[arrayStep(dimensions, i)])
+                            );
+                    }
+                    break;
+                case OCREP_PROP_BYTE_STRING:
+                    if (dimensions[1] == 0)
+                    {
+                        err = err || cbor_value_dup_byte_string(&insideArray,
+                                &(ocByteStr.bytes), &(ocByteStr.len), NULL);
+                        ((OCByteString*)targetArray)[i] = ocByteStr;
+                    }
+                    else
+                    {
+                        err = err || OCParseArrayFillArray(&insideArray, newdim,
+                                type,
+                                &(((OCByteString*)targetArray)[arrayStep(dimensions, i)])
+                                );
+                    }
+                    break;
+                case OCREP_PROP_OBJECT:
+                    if (dimensions[1] == 0)
+                    {
+                        err = err || OCParseSingleRepPayload(&tempPl, &insideArray);
+                        ((OCRepPayload**)targetArray)[i] = tempPl;
+                        tempPl = NULL;
+                        noAdvance = true;
+                    }
+                    else
+                    {
+                        err = err || OCParseArrayFillArray(&insideArray, newdim,
+                            type,
+                            &(((OCRepPayload**)targetArray)[arrayStep(dimensions, i)])
+                            );
+                    }
+                    break;
+                default:
+                    OC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
+                    err = true;
+                    break;
+            }
+        }
+        ++i;
+        if (!noAdvance && cbor_value_is_valid(&insideArray))
+        {
+            err = err || cbor_value_advance(&insideArray);
+        }
+    }
+
+    return err;
+}
+
+static bool OCParseArray(OCRepPayload* out, const char* name, CborValue* container)
+{
     OCRepPayloadPropType type;
     size_t dimensions[MAX_REP_ARRAY_DEPTH];
-    err = err || cbor_value_enter_container(container, &insideArray);
+    bool err = OCParseArrayFindDimensionsAndType(container, dimensions, &type);
 
-    err = err || cbor_value_get_uint64(&insideArray, &tempInt);
-    err = err || cbor_value_advance_fixed(&insideArray);
-    type = (OCRepPayloadPropType)tempInt;
+    if (err)
+    {
+        OC_LOG(ERROR, TAG, "Array details weren't clear");
+        return err;
+    }
 
-    for(int i = 0; i < MAX_REP_ARRAY_DEPTH; ++ i)
+    if (type == OCREP_PROP_NULL)
     {
-         err = err || cbor_value_get_uint64(&insideArray, &tempInt);
-         err = err || cbor_value_advance_fixed(&insideArray);
-        dimensions[i] = tempInt;
+        err = err || OCRepPayloadSetNull(out, name);
+        err = err || cbor_value_advance(container);
+        return err;
     }
 
     size_t dimTotal = calcDimTotal(dimensions);
+    size_t allocSize = getAllocSize(type);
+    void* arr = OICCalloc(dimTotal, allocSize);
 
-    void* arr = NULL;
-    char* tempStr;
-    size_t len;
-    OCRepPayload* pl;
-    switch(type)
+    if (!arr)
+    {
+        OC_LOG(ERROR, TAG, "Array Parse allocation failed");
+        return true;
+    }
+
+    err = err || OCParseArrayFillArray(container, dimensions, type, arr);
+
+    switch (type)
     {
         case OCREP_PROP_INT:
-            arr = (int64_t*)OICMalloc(dimTotal * sizeof(int64_t));
-            for(size_t i = 0; i < dimTotal && !err; ++i)
-            {
-                 err = err || cbor_value_get_int64(&insideArray, &(((int64_t*)arr)[i]));
-                 err = err || cbor_value_advance_fixed(&insideArray);
-            }
-            if(!err &&
-                OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t*)arr, dimensions))
-            {}
-            else
+            if (err || !OCRepPayloadSetIntArrayAsOwner(out, name, (int64_t*)arr, dimensions))
             {
-                err = CborUnknownError;
+                OICFree(arr);
+                err = true;
             }
             break;
         case OCREP_PROP_DOUBLE:
-            arr = (double*)OICMalloc(dimTotal * sizeof(double));
-            for(size_t i = 0; i < dimTotal && !err; ++i)
+            if (err || !OCRepPayloadSetDoubleArrayAsOwner(out, name, (double*)arr, dimensions))
             {
-                 err = err || cbor_value_get_double(&insideArray, &(((double*)arr)[i]));
-                 err = err || cbor_value_advance_fixed(&insideArray);
-            }
-            if(!err &&
-                OCRepPayloadSetDoubleArrayAsOwner(out, name, (double*)arr, dimensions))
-            {}
-            else
-            {
-                err = CborUnknownError;
+                OICFree(arr);
+                err = true;
             }
             break;
         case OCREP_PROP_BOOL:
-            arr = (bool*)OICMalloc(dimTotal * sizeof(bool));
-            for(size_t i = 0; i < dimTotal && !err; ++i)
+            if (err || !OCRepPayloadSetBoolArrayAsOwner(out, name, (bool*)arr, dimensions))
             {
-                 err = err || cbor_value_get_boolean(&insideArray, &(((bool*)arr)[i]));
-                 err = err || cbor_value_advance_fixed(&insideArray);
-            }
-            if(!err &&
-                OCRepPayloadSetBoolArrayAsOwner(out, name, (bool*)arr, dimensions))
-            {}
-            else
-            {
-                err = CborUnknownError;
+                OICFree(arr);
+                err = true;
             }
             break;
         case OCREP_PROP_STRING:
-            arr = (char**)OICMalloc(dimTotal * sizeof(char*));
-            for(size_t i = 0; i < dimTotal && !err; ++i)
+            if (err || !OCRepPayloadSetStringArrayAsOwner(out, name, (char**)arr, dimensions))
             {
-                err = err || cbor_value_dup_text_string(&insideArray, &tempStr, &len, NULL);
-                ((char**) arr)[i] = tempStr;
-                err = err || cbor_value_advance(&insideArray);
+                for(size_t i = 0; i < dimTotal; ++i)
+                {
+                    OICFree(((char**)arr)[i]);
+                }
+                OICFree(arr);
+                err = true;
             }
-            if(!err &&
-                OCRepPayloadSetStringArrayAsOwner(out, name, (char**)arr, dimensions))
-            {}
-            else
+            break;
+        case OCREP_PROP_BYTE_STRING:
+            if (err || !OCRepPayloadSetByteStringArrayAsOwner(out, name, (OCByteString*)arr, dimensions))
             {
-                err = CborUnknownError;
+                for (size_t i = 0; i < dimTotal; ++i)
+                {
+                    OICFree(((OCByteString*)arr)[i].bytes);
+                }
+                OICFree(arr);
+                err = true;
             }
             break;
         case OCREP_PROP_OBJECT:
-            arr = (OCRepPayload**)OICMalloc(dimTotal * sizeof(OCRepPayload*));
-            for(size_t i = 0; i < dimTotal && !err; ++i)
-            {
-                pl = NULL;
-                 err = err || OCParseSingleRepPayload(&pl, &insideArray);
-                ((OCRepPayload**)arr)[i] = pl;
-                 err = err || cbor_value_advance(&insideArray);
-            }
-            if(!err &&
-                OCRepPayloadSetPropObjectArrayAsOwner(out, name, (OCRepPayload**)arr, dimensions))
-            {}
-            else
+            if (err || !OCRepPayloadSetPropObjectArrayAsOwner(out, name, (OCRepPayload**)arr, dimensions))
             {
-                err = CborUnknownError;
+                for(size_t i = 0; i < dimTotal; ++i)
+                {
+                    OCRepPayloadDestroy(((OCRepPayload**)arr)[i]);
+                }
+                OICFree(arr);
+                err = true;
             }
             break;
         default:
             OC_LOG(ERROR, TAG, "Invalid Array type in Parse Array");
-            err = CborUnknownError;
+            err = true;
             break;
     }
 
     return err;
 }
 
-static bool OCParseSingleRepPayload(OCRepPayload** outPayload, CborValue* repParent)
+static bool OCParseSingleRepPayload(OCRepPayload** outPayload, CborValue *objMap)
 {
-    *outPayload = OCRepPayloadCreate();
-    OCRepPayload* curPayload = *outPayload;
-    bool err = false;
-    if(!*outPayload)
+    if (!outPayload)
     {
-        return CborErrorOutOfMemory;
+        return false;
     }
 
-    size_t len;
-    CborValue curVal;
-    err = err || cbor_value_map_find_value(repParent, OC_RSRVD_HREF, &curVal);
-    if(cbor_value_is_valid(&curVal))
-    {
-        err = err || cbor_value_dup_text_string(&curVal, &curPayload->uri, &len,
-            NULL);
-    }
+    bool err = false;
 
-    err = err || cbor_value_map_find_value(repParent, OC_RSRVD_PROPERTY, &curVal);
-    if(cbor_value_is_valid(&curVal))
+    if (cbor_value_is_map(objMap))
     {
-        CborValue insidePropArray;
-        err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_RESOURCE_TYPE,
-                &insidePropArray);
-
-        if(cbor_value_is_array(&insidePropArray))
+        if (!*outPayload)
         {
-            CborValue rtArray;
-            err = err || cbor_value_enter_container(&insidePropArray, &rtArray);
-
-            while(!err && cbor_value_is_valid(&rtArray))
+            *outPayload = OCRepPayloadCreate();
+            if(!*outPayload)
             {
-                char* curRt;
-                err = err || cbor_value_dup_text_string(&rtArray, &curRt, &len, NULL);
-                err = err || cbor_value_advance(&rtArray);
-                OCRepPayloadAddResourceTypeAsOwner(curPayload, curRt);
+                return CborErrorOutOfMemory;
             }
-
-            err = err || cbor_value_leave_container(&insidePropArray, &rtArray);
         }
 
-        err = err || cbor_value_map_find_value(&curVal, OC_RSRVD_INTERFACE, &insidePropArray);
-
-        if(cbor_value_is_array(&insidePropArray))
+        OCRepPayload* curPayload = *outPayload;
+        size_t len = 0;
+        CborValue repMap = *objMap;
+        err = err || cbor_value_enter_container(objMap, &repMap);
+        while (!err && cbor_value_is_valid(&repMap))
         {
-            CborValue ifArray;
-            err = err || cbor_value_enter_container(&insidePropArray, &ifArray);
-
-            while(!err && cbor_value_is_valid(&ifArray))
+            char *name = NULL;
+            if (cbor_value_is_text_string(&repMap))
             {
-                char* curIf;
-                err = err || cbor_value_dup_text_string(&ifArray, &curIf, &len, NULL);
-                err = err || cbor_value_advance(&ifArray);
-                OCRepPayloadAddInterfaceAsOwner(curPayload, curIf);
-            }
-
-            err = err || cbor_value_leave_container(&insidePropArray, &ifArray);
-        }
-    }
-    err = err || cbor_value_map_find_value(repParent, OC_RSRVD_REPRESENTATION, &curVal);
-    if(cbor_value_is_map(&curVal))
-    {
-        CborValue repMap;
-        err = err || cbor_value_enter_container(&curVal, &repMap);
-
-        while(!err && cbor_value_is_valid(&repMap))
-        {
-            char* name;
-             err = err || cbor_value_dup_text_string(&repMap, &name, &len, NULL);
-
-             err = err || cbor_value_advance(&repMap);
+                err = err || cbor_value_dup_text_string(&repMap, &name, &len, NULL);
+                err = err || cbor_value_advance(&repMap);
+                if (name &&
+                    ((0 == strcmp(OC_RSRVD_HREF, name)) ||
+                     (0 == strcmp(OC_RSRVD_RESOURCE_TYPE, name)) ||
+                    (0 == strcmp(OC_RSRVD_INTERFACE, name))))
+                {
+                    err = err || cbor_value_advance(&repMap);
+                    OICFree(name);
+                    continue;
+                }
 
-            int64_t intval = 0;
-            bool boolval = false;
-            char* strval = NULL;
-            double doubleval = 0;
-            OCRepPayload* pl;
+            }
+            CborType type = cbor_value_get_type(&repMap);
 
-            switch(cbor_value_get_type(&repMap))
+            switch(type)
             {
                 case CborNullType:
-                    OCRepPayloadSetNull(curPayload, name);
+                    err = !OCRepPayloadSetNull(curPayload, name);
                     break;
                 case CborIntegerType:
-                    err = err || cbor_value_get_int64(&repMap, &intval);
-                    OCRepPayloadSetPropInt(curPayload, name, intval);
+                    {
+                        int64_t intval = 0;
+                        err = err || cbor_value_get_int64(&repMap, &intval);
+                        if (!err)
+                        {
+                            err = !OCRepPayloadSetPropInt(curPayload, name, intval);
+                        }
+                    }
                     break;
                 case CborDoubleType:
-                    err = err || cbor_value_get_double(&repMap, &doubleval);
-                    OCRepPayloadSetPropDouble(curPayload, name, doubleval);
+                    {
+                        double doubleval = 0;
+                        err = err || cbor_value_get_double(&repMap, &doubleval);
+                        if (!err)
+                        {
+                            err = !OCRepPayloadSetPropDouble(curPayload, name, doubleval);
+                        }
+                    }
                     break;
                 case CborBooleanType:
-                    err = err || cbor_value_get_boolean(&repMap, &boolval);
-                    OCRepPayloadSetPropBool(curPayload, name, boolval);
+                    {
+                        bool boolval = false;
+                        err = err || cbor_value_get_boolean(&repMap, &boolval);
+                        if (!err)
+                        {
+                            err = !OCRepPayloadSetPropBool(curPayload, name, boolval);
+                        }
+                    }
                     break;
                 case CborTextStringType:
-                    err = err || cbor_value_dup_text_string(&repMap, &strval, &len, NULL);
-                    OCRepPayloadSetPropStringAsOwner(curPayload, name, strval);
+                    {
+                        char* strval = NULL;
+                        err = err || cbor_value_dup_text_string(&repMap, &strval, &len, NULL);
+                        if (!err)
+                        {
+                            err = !OCRepPayloadSetPropStringAsOwner(curPayload, name, strval);
+                        }
+                    }
+                    break;
+                case CborByteStringType:
+                    {
+                        uint8_t* bytestrval = NULL;
+                        err = err || cbor_value_dup_byte_string(&repMap, &bytestrval, &len, NULL);
+                        if (!err)
+                        {
+                            OCByteString tmp = {.bytes = bytestrval, .len = len};
+                            err = !OCRepPayloadSetPropByteStringAsOwner(curPayload, name, &tmp);
+                        }
+                    }
                     break;
                 case CborMapType:
-                    err = err || OCParseSingleRepPayload(&pl, &repMap);
-                    OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl);
+                    {
+                        OCRepPayload *pl = NULL;
+                        err = err || OCParseSingleRepPayload(&pl, &repMap);
+                        if (!err)
+                        {
+                            err = !OCRepPayloadSetPropObjectAsOwner(curPayload, name, pl);
+                        }
+                    }
                     break;
                 case CborArrayType:
                     err = err || OCParseArray(curPayload, name, &repMap);
@@ -754,32 +1058,112 @@ static bool OCParseSingleRepPayload(OCRepPayload** outPayload, CborValue* repPar
                     err = true;
             }
 
-             err = err || cbor_value_advance(&repMap);
+            if (type != CborMapType && cbor_value_is_valid(&repMap))
+            {
+                err = err || cbor_value_advance(&repMap);
+            }
             OICFree(name);
         }
-        err = err || cbor_value_leave_container(&curVal, &repMap);
-    }
-
-    if(err)
-    {
-        OCRepPayloadDestroy(*outPayload);
-        *outPayload = NULL;
+        if (cbor_value_is_container(objMap))
+        {
+            err = err || cbor_value_leave_container(objMap, &repMap);
+        }
+        if (err)
+        {
+            OCRepPayloadDestroy(*outPayload);
+            *outPayload = NULL;
+        }
     }
 
     return err;
 }
-static OCStackResult OCParseRepPayload(OCPayload** outPayload, CborValue* arrayVal)
-{
-    bool err = false;
 
-    OCRepPayload* rootPayload = NULL;
-    OCRepPayload* curPayload = NULL;
-    OCRepPayload* temp = NULL;
-    while(!err && cbor_value_is_map(arrayVal))
+static OCStackResult OCParseRepPayload(OCPayload** outPayload, CborValue* root)
+{
+    if (!outPayload)
     {
-         err = err || OCParseSingleRepPayload(&temp, arrayVal);
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OCRepPayload *rootPayload = NULL;
+    OCRepPayload *curPayload = NULL;
 
-        if(rootPayload == NULL)
+    CborValue curVal;
+    bool err = false;
+    size_t len = 0;
+    CborValue rootMap = *root;
+    if (cbor_value_is_array(root))
+    {
+        cbor_value_enter_container(root, &rootMap);
+    }
+    while (!err && cbor_value_is_valid(&rootMap))
+    {
+        OCRepPayload *temp = OCRepPayloadCreate();
+        if (!temp)
+        {
+            return OC_STACK_NO_MEMORY;
+        }
+        if (!err && cbor_value_is_map(&rootMap))
+        {
+            err = err || cbor_value_map_find_value(&rootMap, OC_RSRVD_HREF, &curVal);
+            if (cbor_value_is_valid(&curVal))
+            {
+                err = err || cbor_value_dup_text_string(&curVal, &temp->uri, &len, NULL);
+            }
+        }
+        if (!err && cbor_value_is_map(&rootMap))
+        {
+            err = err || cbor_value_map_find_value(&rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal);
+            if(cbor_value_is_text_string(&curVal))
+            {
+                char* allRt = NULL;
+                err = err || cbor_value_dup_text_string(&curVal, &allRt, &len, NULL);
+                if (allRt)
+                {
+                    char* savePtr;
+                    char* curPtr = strtok_r(allRt, " ", &savePtr);
+                    while (curPtr)
+                    {
+                        char* trimmed = InPlaceStringTrim(curPtr);
+                        if (trimmed[0] != '\0')
+                        {
+                            OCRepPayloadAddResourceType(temp, curPtr);
+                        }
+                        curPtr = strtok_r(NULL, " ", &savePtr);
+                    }
+                }
+                OICFree(allRt);
+            }
+        }
+        if (!err && cbor_value_is_map(&rootMap))
+        {
+            err = err || cbor_value_map_find_value(&rootMap, OC_RSRVD_INTERFACE, &curVal);
+            if(cbor_value_is_text_string(&curVal))
+            {
+                char* allIf = NULL;
+                err = err || cbor_value_dup_text_string(&curVal, &allIf, &len, NULL);
+                if (allIf)
+                {
+                    char* savePtr;
+                    char* curPtr = strtok_r(allIf, " ", &savePtr);
+                    while (curPtr)
+                    {
+                        char* trimmed = InPlaceStringTrim(curPtr);
+                        if (trimmed[0] != '\0')
+                        {
+                            OCRepPayloadAddInterface(temp, curPtr);
+                        }
+                        curPtr = strtok_r(NULL, " ", &savePtr);
+                    }
+                }
+                OICFree(allIf);
+            }
+        }
+        if (!err && cbor_value_is_map(&rootMap))
+        {
+             err = err || OCParseSingleRepPayload(&temp, &rootMap);
+        }
+        if (rootPayload == NULL)
         {
             rootPayload = temp;
             curPayload = temp;
@@ -789,26 +1173,31 @@ static OCStackResult OCParseRepPayload(OCPayload** outPayload, CborValue* arrayV
             curPayload->next = temp;
             curPayload = curPayload->next;
         }
-
-
-         err = err || cbor_value_advance(arrayVal);
-        if(err)
+        if (err)
         {
             OCRepPayloadDestroy(rootPayload);
-            OC_LOG_V(ERROR, TAG, PCF("CBOR error in ParseRepPayload"));
+            OC_LOG(ERROR, TAG, "CBOR error in ParseRepPayload");
             return OC_STACK_MALFORMED_RESPONSE;
         }
+        if (cbor_value_is_array(&rootMap))
+        {
+            err = err || cbor_value_advance(&rootMap);
+        }
     }
-
-    *outPayload = (OCPayload*)rootPayload;
+    *outPayload = (OCPayload *)rootPayload;
 
     return OC_STACK_OK;
 }
 
-static OCStackResult OCParsePresencePayload(OCPayload** outPayload, CborValue* arrayVal)
+static OCStackResult OCParsePresencePayload(OCPayload** outPayload, CborValue* rootValue)
 {
+    if (!outPayload)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
     bool err = false;
-    if(cbor_value_is_map(arrayVal))
+    if(cbor_value_is_map(rootValue))
     {
         uint64_t seqNum = 0;
         uint64_t maxAge = 0;
@@ -818,28 +1207,28 @@ static OCStackResult OCParsePresencePayload(OCPayload** outPayload, CborValue* a
 
         CborValue curVal;
         // Sequence Number
-         err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_NONCE, &curVal);
-         err = err || cbor_value_get_uint64(&curVal, &seqNum);
+        err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_NONCE, &curVal);
+        err = err || cbor_value_get_uint64(&curVal, &seqNum);
 
         // Max Age
-         err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_TTL, &curVal);
-         err = err || cbor_value_get_uint64(&curVal, &maxAge);
+        err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_TTL, &curVal);
+        err = err || cbor_value_get_uint64(&curVal, &maxAge);
 
         // Trigger
-         err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_TRIGGER, &curVal);
-         err = err || cbor_value_dup_text_string(&curVal, &tempStr, &len, NULL);
+        err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_TRIGGER, &curVal);
+        err = err || cbor_value_dup_text_string(&curVal, &tempStr, &len, NULL);
         trigger = convertTriggerStringToEnum(tempStr);
         OICFree(tempStr);
         tempStr = NULL;
 
         // Resource type name
-         err = err || cbor_value_map_find_value(arrayVal, OC_RSRVD_RESOURCE_TYPE, &curVal);
+        err = err || cbor_value_map_find_value(rootValue, OC_RSRVD_RESOURCE_TYPE, &curVal);
         if(cbor_value_is_valid(&curVal))
         {
              err = err || cbor_value_dup_text_string(&curVal, &tempStr, &len, NULL);
         }
 
-        err = err || cbor_value_advance(arrayVal);
+        err = err || cbor_value_advance(rootValue);
 
         if(!err)
         {
@@ -850,7 +1239,7 @@ static OCStackResult OCParsePresencePayload(OCPayload** outPayload, CborValue* a
         if(err)
         {
             OCPayloadDestroy(*outPayload);
-            OC_LOG_V(ERROR, TAG, PCF("CBOR error Parse Presence Payload"));
+            OC_LOG(ERROR, TAG, "CBOR error Parse Presence Payload");
             return OC_STACK_MALFORMED_RESPONSE;
         }
 
@@ -863,7 +1252,7 @@ static OCStackResult OCParsePresencePayload(OCPayload** outPayload, CborValue* a
     }
     else
     {
-        OC_LOG(ERROR, TAG, PCF("Root presence node was not a map"));
+        OC_LOG(ERROR, TAG, "Root presence node was not a map");
         return OC_STACK_MALFORMED_RESPONSE;
     }
 }