Imported Upstream version 0.9.2
[platform/upstream/iotivity.git] / resource / csdk / stack / src / ocresource.c
index f2267d1..5f64f10 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/
 #define _POSIX_C_SOURCE 200112L
+#include "ocresource.h"
 #include <string.h>
-#include "ocstack.h"
-#include "ocstackconfig.h"
-#include "ocstackinternal.h"
 #include "ocresourcehandler.h"
 #include "ocobserve.h"
 #include "occollection.h"
-#include "occoap.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
 #include "logger.h"
-#include "debug.h"
 #include "cJSON.h"
+#include "ocpayload.h"
+
+#include "cacommon.h"
+#include "cainterface.h"
+
 
 /// Module Name
 #define TAG PCF("ocresource")
              TAG, PCF(#arg " is NULL")); return (retVal); } }
 
 extern OCResource *headResource;
-static cJSON *savedDeviceInfo = NULL;
-
-static const char * VIRTUAL_RSRCS[] = {
-       "/oc/core",
-       "/oc/core/d",
-       "/oc/core/types/d",
-       #ifdef WITH_PRESENCE
-       "/oc/presence"
-       #endif
-};
+static OCPlatformInfo savedPlatformInfo = {};
+static OCDeviceInfo savedDeviceInfo = {};
 
 //-----------------------------------------------------------------------------
 // Default resource entity handler function
 //-----------------------------------------------------------------------------
 OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag,
-        OCEntityHandlerRequest * request) {
-    TODO ("Implement me!!!!");
+        OCEntityHandlerRequest * request, void* callbackParam)
+{
+    //TODO ("Implement me!!!!");
     // TODO:  remove silence unused param warnings
     (void) flag;
     (void) request;
+    (void) callbackParam;
     return  OC_EH_OK; // Making sure that the Default EH and the Vendor EH have matching signatures
 }
 
-static OCStackResult ValidateUrlQuery (unsigned char *url, unsigned char *query,
-                                uint8_t *filterOn, char **filterValue)
+/* This method will retrieve the port at which the secure resource is hosted */
+static OCStackResult GetSecurePortInfo(OCDevAddr *endpoint, uint16_t *port)
 {
-    char *filterParam;
-
-    OC_LOG(INFO, TAG, PCF("Entering ValidateUrlQuery"));
-    if (!url)
-        return OC_STACK_INVALID_URI;
-
-    if (strcmp ((char *)url, GetVirtualResourceUri(OC_WELL_KNOWN_URI)) == 0 ||
-                strcmp ((char *)url, GetVirtualResourceUri(OC_DEVICE_URI)) == 0) {
-        *filterOn = STACK_RES_DISCOVERY_NOFILTER;
-        if (query && *query) {
-            char* strTokPtr;
-            filterParam = strtok_r((char *)query, "=", &strTokPtr);
-            *filterValue = strtok_r(NULL, " ", &strTokPtr);
-            if (!(*filterValue)) {
-                return OC_STACK_INVALID_QUERY;
-            } else if (strcmp (filterParam, OC_RSRVD_INTERFACE) == 0) {
-                // Resource discovery with interface filter
-                *filterOn = STACK_RES_DISCOVERY_IF_FILTER;
-            } else if (strcmp (filterParam, OC_RSRVD_RESOURCE_TYPE) == 0) {
-                // Resource discovery with resource type filter
-                *filterOn = STACK_RES_DISCOVERY_RT_FILTER;
-            } else if (strcmp (filterParam, OC_RSRVD_DEVICE_ID) == 0) {
-                //Device ID filter
-                *filterOn = STACK_DEVICE_DISCOVERY_DI_FILTER;
-            } else if (strcmp (filterParam, OC_RSRVD_DEVICE_NAME) == 0) {
-                //Device Name filter
-                *filterOn = STACK_DEVICE_DISCOVERY_DN_FILTER;
-            } else {
-                // Other filter types not supported
-                return OC_STACK_INVALID_QUERY;
-            }
+    uint16_t p = 0;
+
+    if (endpoint->adapter == OC_ADAPTER_IP)
+    {
+        if (endpoint->flags & OC_IP_USE_V6)
+        {
+            p = caglobals.ip.u6s.port;
+        }
+        else if (endpoint->flags & OC_IP_USE_V4)
+        {
+            p = caglobals.ip.u4s.port;
         }
     }
-    #ifdef WITH_PRESENCE
-    else if (strcmp((char *)url, GetVirtualResourceUri(OC_PRESENCE)) == 0) {
-        //Nothing needs to be done, except for pass a OC_PRESENCE query through as OC_STACK_OK.
-        OC_LOG(INFO, TAG, PCF("OC_PRESENCE Request"));
-        *filterOn = STACK_RES_DISCOVERY_NOFILTER;
-    }
-    #endif
-    else {
-        // Other URIs not yet supported
-        return OC_STACK_INVALID_URI;
-    }
-    OC_LOG(INFO, TAG, PCF("Exiting ValidateUrlQuery"));
+
+    *port = p;
     return OC_STACK_OK;
 }
 
-OCStackResult BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filterOn,
-                                            char *filterValue, char * out, uint16_t *remaining)
+/*
+ * Function will extract 0, 1 or 2 filters from query.
+ * More than 2 filters or unsupported filters will result in error.
+ * If both filters are of the same supported type, the 2nd one will be picked.
+ * Resource and device filters in the SAME query are NOT validated
+ * and resources will likely not clear filters.
+ */
+static OCStackResult ExtractFiltersFromQuery(char *query, char **filterOne, char **filterTwo)
 {
-    OCResourceType *resourceTypePtr;
-    OCResourceInterface *interfacePtr;
-    cJSON *resObj, *propObj, *rtArray;
-    char *jsonStr;
-    uint8_t encodeRes = 0;
-    OCStackResult ret = OC_STACK_OK;
-    uint16_t jsonLen;
 
-    OC_LOG(INFO, TAG, PCF("Entering BuildVirtualResourceResponse"));
-    resObj = cJSON_CreateObject();
+    char *key = NULL;
+    char *value = NULL;
+    char *restOfQuery = NULL;
+    int numKeyValuePairsParsed = 0;
+
+    *filterOne = NULL;
+    *filterTwo = NULL;
+
+    OC_LOG_V(INFO, TAG, "Extracting params from %s", query);
 
-    if (resourcePtr)
+    char *keyValuePair = strtok_r (query, OC_QUERY_SEPARATOR, &restOfQuery);
+
+    while(keyValuePair)
     {
-        encodeRes = 0;
-        if (filterOn == STACK_RES_DISCOVERY_RT_FILTER) {
-            resourceTypePtr = resourcePtr->rsrcType;
-            while (resourceTypePtr) {
-                if (strcmp (resourceTypePtr->resourcetypename, filterValue) == 0) {
-                    encodeRes = 1;
-                    break;
-                }
-                resourceTypePtr = resourceTypePtr->next;
-            }
-        } else if (filterOn == STACK_RES_DISCOVERY_IF_FILTER) {
-            interfacePtr = resourcePtr->rsrcInterface;
-            while (interfacePtr) {
-                if (strcmp (interfacePtr->name, filterValue) == 0) {
-                    encodeRes = 1;
-                    break;
-                }
-                interfacePtr = interfacePtr->next;
-            }
-        } else if (filterOn == STACK_RES_DISCOVERY_NOFILTER) {
-            encodeRes = 1;
-        } else {
-            //TODO: Unsupported query filter
+        if (numKeyValuePairsParsed >= 2)
+        {
+            OC_LOG(ERROR, TAG, PCF("More than 2 queries params in URI."));
             return OC_STACK_INVALID_QUERY;
         }
 
-        if (encodeRes) {
-            // Add URIs
-            cJSON_AddItemToObject (resObj, OC_RSRVD_HREF, cJSON_CreateString(resourcePtr->uri));
-
-            cJSON_AddItemToObject (resObj, "prop", propObj = cJSON_CreateObject());
-            // Add resource types
-            cJSON_AddItemToObject (propObj, OC_RSRVD_RESOURCE_TYPE, rtArray = cJSON_CreateArray());
-            resourceTypePtr = resourcePtr->rsrcType;
-            while (resourceTypePtr) {
-                cJSON_AddItemToArray (rtArray,
-                                      cJSON_CreateString(resourceTypePtr->resourcetypename));
-                resourceTypePtr = resourceTypePtr->next;
-            }
-            // Add interface types
-            cJSON_AddItemToObject (propObj, OC_RSRVD_INTERFACE, rtArray = cJSON_CreateArray());
-            interfacePtr = resourcePtr->rsrcInterface;
-            while (interfacePtr) {
-                cJSON_AddItemToArray (rtArray, cJSON_CreateString(interfacePtr->name));
-                interfacePtr = interfacePtr->next;
-            }
-            // If resource is observable, set observability flag.
-            // Resources that are not observable will not have the flag.
-            if (resourcePtr->resourceProperties & OC_OBSERVABLE) {
-                cJSON_AddItemToObject (propObj, OC_RSRVD_OBSERVABLE,
-                                       cJSON_CreateNumber(OC_RESOURCE_OBSERVABLE));
-            }
-            // Set secure flag for secure resources
-            if (resourcePtr->resourceProperties & OC_SECURE) {
-                uint16_t port;
-                cJSON_AddNumberToObject (propObj, OC_RSRVD_SECURE, OC_RESOURCE_SECURE);
-                //Set the IP port also as secure resources are hosted on a different port
-                if (OCGetResourceEndPointInfo (resourcePtr, &port) == OC_STACK_OK) {
-                    cJSON_AddNumberToObject (propObj, OC_RSRVD_HOSTING_PORT, port);
-                }
-            }
+        key = strtok_r(keyValuePair, OC_KEY_VALUE_DELIMITER, &value);
 
+        if (!key || !value)
+        {
+            return OC_STACK_INVALID_QUERY;
+        }
+        else if (strcmp (key, OC_RSRVD_INTERFACE) == 0)
+        {
+            *filterOne = value;     // if
+        }
+        else if (strcmp (key, OC_RSRVD_RESOURCE_TYPE) == 0)
+        {
+            *filterTwo = value;     // rt
+        }
+        else
+        {
+            OC_LOG_V(ERROR, TAG, "Unsupported query key: %s", key);
+            return OC_STACK_INVALID_QUERY;
         }
+        ++numKeyValuePairsParsed;
+
+        keyValuePair = strtok_r(NULL, OC_QUERY_SEPARATOR, &restOfQuery);
     }
-    jsonStr = cJSON_PrintUnformatted (resObj);
 
-    jsonLen = strlen(jsonStr);
-    if (jsonLen < *remaining)
+    OC_LOG_V(INFO, TAG, "Extracted params %s and %s.", *filterOne, *filterTwo);
+    return OC_STACK_OK;
+}
+
+static OCVirtualResources GetTypeOfVirtualURI(const char *uriInRequest)
+{
+    if (strcmp(uriInRequest, OC_RSRVD_WELL_KNOWN_URI) == 0)
     {
-        strcpy(out, jsonStr);
-        *remaining = *remaining - jsonLen;
+        return OC_WELL_KNOWN_URI;
     }
-    else
+    else if (strcmp(uriInRequest, OC_RSRVD_DEVICE_URI) == 0)
+    {
+        return OC_DEVICE_URI;
+    }
+    else if (strcmp(uriInRequest, OC_RSRVD_PLATFORM_URI) == 0)
+    {
+        return OC_PLATFORM_URI;
+    }
+    else if (strcmp(uriInRequest, OC_RSRVD_RESOURCE_TYPES_URI) == 0)
     {
-        ret = OC_STACK_ERROR;
+        return OC_RESOURCE_TYPES_URI;
     }
-    cJSON_Delete (resObj);
-    free (jsonStr);
+#ifdef WITH_PRESENCE
+    else if (strcmp(uriInRequest, OC_RSRVD_PRESENCE_URI) == 0)
+    {
+        return OC_PRESENCE;
+    }
+#endif //WITH_PRESENCE
+    return OC_UNKNOWN_URI;
+}
 
-    OC_LOG(INFO, TAG, PCF("Exiting BuildVirtualResourceResponse"));
-    return ret;
+static OCStackResult getQueryParamsForFiltering (OCVirtualResources uri, char *query,
+                                            char **filterOne, char **filterTwo)
+{
+    if(!filterOne || !filterTwo)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    *filterOne = NULL;
+    *filterTwo = NULL;
+
+    #ifdef WITH_PRESENCE
+    if (uri == OC_PRESENCE)
+    {
+        //Nothing needs to be done, except for pass a OC_PRESENCE query through as OC_STACK_OK.
+        OC_LOG(INFO, TAG, PCF("OC_PRESENCE Request for virtual resource."));
+        return OC_STACK_OK;
+    }
+    #endif
+
+    OCStackResult result = OC_STACK_OK;
+
+    if (query && *query)
+    {
+        result = ExtractFiltersFromQuery(query, filterOne, filterTwo);
+    }
+
+    return result;
 }
 
-OCStackResult BuildVirtualResourceResponseForDevice(uint8_t filterOn, char *filterValue,
-                                                    char *out, uint16_t *remaining)
+OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr,
+                    OCRepPayload** payload)
 {
-    OCStackResult ret = OC_STACK_ERROR;
+    OCRepPayload *tempPayload = OCRepPayloadCreate();
 
-    if (savedDeviceInfo != NULL)
+    if (!resourcePtr)
     {
-        char *jsonStr = NULL;
-        uint16_t jsonLen = 0;
-        cJSON *repObj = cJSON_GetObjectItem(savedDeviceInfo, "rep");
+        OCRepPayloadDestroy(tempPayload);
+        return OC_STACK_INVALID_PARAM;
+    }
 
-        OC_LOG(INFO, TAG, PCF("Entering BuildVirtualResourceResponseForDevice"));
+    if(!tempPayload)
+    {
+        return OC_STACK_NO_MEMORY;
+    }
 
-        if (filterOn == STACK_DEVICE_DISCOVERY_DI_FILTER)
-        {
-            if((cJSON_GetObjectItem(repObj,"di") != NULL) &&
-                    strcmp(cJSON_GetObjectItem(repObj,"di")->valuestring, filterValue) == 0)
-            {
-                ret = OC_STACK_OK;
-            }
-        }
-        else if (filterOn == STACK_DEVICE_DISCOVERY_DN_FILTER)
-        {
-            if((cJSON_GetObjectItem(repObj,"dn") != NULL) &&
-                    strcmp(cJSON_GetObjectItem(repObj,"dn")->valuestring, filterValue) == 0)
-            {
-                ret = OC_STACK_OK;
-            }
-        }
-        else if (filterOn == STACK_RES_DISCOVERY_NOFILTER)
-        {
-            ret = OC_STACK_OK;
-        }
-        else
-        {
-            ret = OC_STACK_INVALID_QUERY;
-        }
+    OCRepPayloadSetUri(tempPayload, resourcePtr->uri);
 
-        if (ret == OC_STACK_OK)
-        {
-            jsonStr = cJSON_PrintUnformatted (savedDeviceInfo);
+    OCResourceType *resType = resourcePtr->rsrcType;
+    while(resType)
+    {
+        OCRepPayloadAddResourceType(tempPayload, resType->resourcetypename);
+        resType = resType->next;
+    }
 
-            if(jsonStr)
-            {
-                jsonLen = strlen(jsonStr);
+    OCResourceInterface *resInterface = resourcePtr->rsrcInterface;
+    while(resInterface)
+    {
+        OCRepPayloadAddInterface(tempPayload, resInterface->name);
+        resInterface = resInterface->next;
+    }
 
-                if (jsonLen < *remaining)
-                {
-                    strncpy(out, jsonStr, (jsonLen + 1));
-                    *remaining = *remaining - jsonLen;
-                    ret = OC_STACK_OK;
-                }
-                else
-                {
-                    ret = OC_STACK_ERROR;
-                }
+    OCAttribute *resAttrib = resourcePtr->rsrcAttributes;
+    while(resAttrib)
+    {
+        OCRepPayloadSetPropString(tempPayload, resAttrib->attrName,
+                                resAttrib->attrValue);
+        resAttrib = resAttrib->next;
+    }
 
-                free(jsonStr);
-            }
-            else
-            {
-                ret = OC_STACK_ERROR;
-            }
-        }
-        else
-        {
-            ret = OC_STACK_INVALID_DEVICE_INFO;
-        }
+    if(!*payload)
+    {
+        *payload = tempPayload;
     }
     else
     {
-        //error so that stack won't respond with empty payload
-        ret = OC_STACK_INVALID_DEVICE_INFO;
+        OCRepPayloadAppend(*payload, tempPayload);
     }
 
-    OC_LOG(INFO, TAG, PCF("Exiting BuildVirtualResourceResponseForDevice"));
-    return ret;
+    return OC_STACK_OK;
 }
 
-TODO ("Does it make sense to make this method as inline")
-const char * GetVirtualResourceUri( OCVirtualResources resource)
+OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
+                        OCDiscoveryPayload *payload, OCDevAddr *devAddr)
 {
-    if (resource < OC_MAX_VIRTUAL_RESOURCES)
+    if (!resourcePtr || !payload)
     {
-        return VIRTUAL_RSRCS[resource];
+        return OC_STACK_INVALID_PARAM;
+    }
+    uint16_t port = 0;
+    if (resourcePtr->resourceProperties & OC_SECURE)
+    {
+       if (GetSecurePortInfo(devAddr, &port) != OC_STACK_OK)
+       {
+           port = 0;
+       }
     }
 
-    return NULL;
+    OCDiscoveryPayloadAddResource(payload, resourcePtr, port);
+    return OC_STACK_OK;
 }
 
-uint8_t IsVirtualResource(const char* resourceUri)
+
+uint8_t IsCollectionResource (OCResource *resource)
 {
-    for (int i = 0; i < OC_MAX_VIRTUAL_RESOURCES; i++)
+    if(!resource)
     {
-        if (strcmp(resourceUri, GetVirtualResourceUri((OCVirtualResources)i)) == 0)
-        {
-            return 1;
-        }
+        return 0;
     }
-    return 0;
-}
 
-uint8_t IsCollectionResource (OCResource *resource)
-{
     for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
     {
         if (resource->rsrcResources[i])
@@ -329,37 +294,49 @@ uint8_t IsCollectionResource (OCResource *resource)
 
 OCResource *FindResourceByUri(const char* resourceUri)
 {
+    if(!resourceUri)
+    {
+        return NULL;
+    }
+
     OCResource * pointer = headResource;
-    while (pointer) {
-        if (strcmp(resourceUri, pointer->uri) == 0) {
+    while (pointer)
+    {
+        if (strcmp(resourceUri, pointer->uri) == 0)
+        {
             return pointer;
         }
         pointer = pointer->next;
     }
-    OC_LOG(INFO, TAG, PCF("Resource not found"));
+    OC_LOG_V(INFO, TAG, "Resource %s not found", resourceUri);
     return NULL;
 }
 
 
-OCStackResult DetermineResourceHandling (OCServerRequest *request,
+OCStackResult DetermineResourceHandling (const OCServerRequest *request,
                                          ResourceHandling *handling,
                                          OCResource **resource)
 {
+    if(!request || !handling || !resource)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
 
-    OC_LOG(INFO, TAG, PCF("Entering DetermineResourceHandling"));
+    OC_LOG_V(INFO, TAG, "DetermineResourceHandling for %s", request->resourceUrl);
 
     // Check if virtual resource
-    if (IsVirtualResource((const char*)request->resourceUrl))
+    if (GetTypeOfVirtualURI(request->resourceUrl) != OC_UNKNOWN_URI)
     {
+        OC_LOG_V (INFO, TAG, "%s is virtual", request->resourceUrl);
         *handling = OC_RESOURCE_VIRTUAL;
         *resource = headResource;
         return OC_STACK_OK;
     }
-    if (NULL == request->resourceUrl || (strlen((const char*)(request->resourceUrl)) == 0))
+    if (strlen((const char*)(request->resourceUrl)) == 0)
     {
         // Resource URL not specified
         *handling = OC_RESOURCE_NOT_SPECIFIED;
-        return OC_STACK_OK;
+        return OC_STACK_NO_RESOURCE;
     }
     else
     {
@@ -380,13 +357,6 @@ OCStackResult DetermineResourceHandling (OCServerRequest *request,
             return OC_STACK_NO_RESOURCE;
         }
 
-        // secure resource will entertain only authorized requests
-        if ((resourcePtr->resourceProperties & OC_SECURE) && (request->secured == 0))
-        {
-            OC_LOG(INFO, TAG, PCF("Un-authorized request. Ignore it!"));
-            return OC_STACK_RESOURCE_ERROR;
-        }
-
         if (IsCollectionResource (resourcePtr))
         {
             // Collection resource
@@ -394,17 +364,23 @@ OCStackResult DetermineResourceHandling (OCServerRequest *request,
             {
                 *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER;
                 return OC_STACK_OK;
-            } else {
+            }
+            else
+            {
                 *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER;
                 return OC_STACK_OK;
             }
-        } else {
+        }
+        else
+        {
             // Resource not a collection
             if (resourcePtr->entityHandler != defaultResourceEHandler)
             {
                 *handling = OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER;
                 return OC_STACK_OK;
-            } else {
+            }
+            else
+            {
                 *handling = OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER;
                 return OC_STACK_OK;
             }
@@ -436,6 +412,9 @@ OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
         case OC_EH_RESOURCE_DELETED:
             result = OC_STACK_RESOURCE_DELETED;
             break;
+        case OC_EH_RESOURCE_NOT_FOUND:
+            result = OC_STACK_NO_RESOURCE;
+            break;
         default:
             result = OC_STACK_ERROR;
     }
@@ -443,136 +422,279 @@ OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
     return result;
 }
 
-static OCStackResult
-HandleVirtualResource (OCServerRequest *request, OCResource* resource)
+static bool resourceMatchesRTFilter(OCResource *resource, char *resourceTypeFilter)
 {
-    OCStackResult result = OC_STACK_ERROR;
-    char *filterValue = NULL;
-    uint8_t filterOn = 0;
-    uint16_t remaining = 0;
-    unsigned char * ptr = NULL;
-    uint8_t firstLoopDone = 0;
-    unsigned char discoveryResBuf[MAX_RESPONSE_LENGTH] = {0};
+    if (!resource)
+    {
+        return false;
+    }
 
-    OC_LOG(INFO, TAG, PCF("Entering HandleVirtualResource"));
+    // Null or empty is analogous to no filter.
+    if (resourceTypeFilter == NULL || *resourceTypeFilter == 0)
+    {
+        return true;
+    }
 
-    result = ValidateUrlQuery (request->resourceUrl,
-            request->query, &filterOn,
-            &filterValue);
+    OCResourceType *resourceTypePtr = resource->rsrcType;
 
-    if (result == OC_STACK_OK)
+    while (resourceTypePtr)
     {
-        if (strcmp ((char *)request->resourceUrl, GetVirtualResourceUri(OC_WELL_KNOWN_URI)) == 0)
+        if (strcmp (resourceTypePtr->resourcetypename, resourceTypeFilter) == 0)
         {
-            ptr = discoveryResBuf;
-            remaining = MAX_RESPONSE_LENGTH;
+            return true;
+        }
+        resourceTypePtr = resourceTypePtr->next;
+    }
 
-            while(resource)
-            {
-                if((resource->resourceProperties & OC_ACTIVE)
-                        && (resource->resourceProperties & OC_DISCOVERABLE))
-                {
-                    // if there is data on the buffer, we have already added a response,
-                    // so we need to add a comma before we do anything
-                    if(firstLoopDone
-                            && remaining >= (sizeof(OC_JSON_SEPARATOR)+1))
-                    {
-                        *ptr = OC_JSON_SEPARATOR;
-                        ptr++;
-                        remaining--;
-                    }
-                    firstLoopDone = 1;
-                    result = BuildVirtualResourceResponse(resource, filterOn, filterValue,
-                            (char*)ptr, &remaining);
+    OC_LOG_V(INFO, TAG, PCF("%s does not contain rt=%s."), resource->uri, resourceTypeFilter);
+    return false;
+}
 
-                    if (result != OC_STACK_OK)
-                    {
-                        // if this failed, we need to remove the comma added above.
-                        if(!firstLoopDone)
-                        {
-                            ptr--;
-                            *ptr = '\0';
-                            remaining++;
-                        }
-                        break;
-                    }
-                    ptr += strlen((char *)ptr);
-                    *(ptr + 1) = '\0';
-                }
-                resource = resource->next;
-            }
+static bool resourceMatchesIFFilter(OCResource *resource, char *interfaceFilter)
+{
+    if (!resource)
+    {
+        return false;
+    }
 
-            if(strlen((const char *)discoveryResBuf) > 0)
-            {
-                OCEntityHandlerResponse response = {0};
+    // Null or empty is analogous to no filter.
+    if (interfaceFilter == NULL || *interfaceFilter == 0)
+    {
+        return true;
+    }
 
-                response.ehResult = OC_EH_OK;
-                response.payload = discoveryResBuf;
-                response.payloadSize = strlen((const char *)discoveryResBuf) + 1;
-                response.persistentBufferFlag = 0;
-                response.requestHandle = (OCRequestHandle) request;
-                response.resourceHandle = (OCResourceHandle) resource;
+    OCResourceInterface *interfacePtr = resource->rsrcInterface;
 
-                result = OCDoResponse(&response);
-            }
+    while (interfacePtr)
+    {
+        if (strcmp (interfacePtr->name, interfaceFilter) == 0)
+        {
+            return true;
         }
-        else if (strcmp ((char *)request->resourceUrl, GetVirtualResourceUri(OC_DEVICE_URI)) == 0)
+        interfacePtr = interfacePtr->next;
+    }
+
+    OC_LOG_V(INFO, TAG, PCF("%s does not contain if=%s."), resource->uri, interfaceFilter);
+    return false;
+}
+
+/*
+ * If the filters are null, they will be assumed to NOT be present
+ * and the resource will not be matched against them.
+ * Function will return true if all non null AND non empty filters passed in find a match.
+ */
+static bool includeThisResourceInResponse(OCResource *resource,
+                                                 char *interfaceFilter,
+                                                 char *resourceTypeFilter)
+{
+    if (!resource)
+    {
+        OC_LOG(ERROR, TAG, PCF("Invalid resource"));
+        return false;
+    }
+
+    if ( resource->resourceProperties & OC_EXPLICIT_DISCOVERABLE)
+    {
+        /*
+         * At least one valid filter should be available to
+         * include the resource in discovery response
+         */
+        if (!((interfaceFilter && *interfaceFilter ) ||
+              (resourceTypeFilter && *resourceTypeFilter)))
         {
-            remaining = MAX_RESPONSE_LENGTH;
-            ptr = discoveryResBuf;
+            OC_LOG_V(INFO, TAG, PCF("%s no query string for EXPLICIT_DISCOVERABLE \
+                resource"), resource->uri);
+            return false;
+        }
+    }
+    else if ( !(resource->resourceProperties & OC_ACTIVE) ||
+         !(resource->resourceProperties & OC_DISCOVERABLE))
+    {
+        OC_LOG_V(INFO, TAG, PCF("%s not ACTIVE or DISCOVERABLE"), resource->uri);
+        return false;
+    }
+
+    return resourceMatchesIFFilter(resource, interfaceFilter) &&
+           resourceMatchesRTFilter(resource, resourceTypeFilter);
+
+}
+
+OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCResource *resource,
+                                OCPayload *discoveryPayload, OCEntityHandlerResult ehResult)
+{
+    OCEntityHandlerResponse response = {};
+
+    response.ehResult = ehResult;
+    response.payload = discoveryPayload;
+    response.persistentBufferFlag = 0;
+    response.requestHandle = (OCRequestHandle) request;
+    response.resourceHandle = (OCResourceHandle) resource;
+
+    return OCDoResponse(&response);
+}
+
+static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource)
+{
+    if (!request || !resource)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
 
-            result = BuildVirtualResourceResponseForDevice(filterOn, filterValue,
-                    (char*)ptr, &remaining);
+    OCStackResult discoveryResult = OC_STACK_ERROR;
 
-            if(result == OC_STACK_OK)
+    bool bMulticast    = false;     // Was the discovery request a multicast request?
+    OCPayload* payload = NULL;
+
+    OC_LOG(INFO, TAG, PCF("Entering HandleVirtualResource"));
+
+    OCVirtualResources virtualUriInRequest = GetTypeOfVirtualURI (request->resourceUrl);
+
+    // Step 1: Generate the response to discovery request
+    if (virtualUriInRequest == OC_WELL_KNOWN_URI)
+    {
+        char *filterOne = NULL;
+        char *filterTwo = NULL;
+
+        discoveryResult = getQueryParamsForFiltering (virtualUriInRequest, request->query,
+                &filterOne, &filterTwo);
+
+        if (discoveryResult == OC_STACK_OK)
+        {
+            payload = (OCPayload*)OCDiscoveryPayloadCreate();
+
+            if(payload)
             {
-                ptr += strlen((char*)ptr);
+                for(;resource && discoveryResult == OC_STACK_OK; resource = resource->next)
+                {
+                    if(includeThisResourceInResponse(resource, filterOne, filterTwo))
+                    {
+                        discoveryResult = BuildVirtualResourceResponse(resource,
+                                (OCDiscoveryPayload*)payload,
+                                &request->devAddr);
+                    }
+                }
+                // Set discoveryResult appropriately if no 'valid' resources are available.
+                if (((OCDiscoveryPayload*)payload)->resources == NULL)
+                {
+                    discoveryResult = OC_STACK_NO_RESOURCE;
+                }
             }
-
-            if(remaining < MAX_RESPONSE_LENGTH)
+            else
             {
-                OCEntityHandlerResponse response = {0};
+                discoveryResult = OC_STACK_NO_MEMORY;
+            }
+        }
+        else
+        {
+            OC_LOG_V(ERROR, TAG, "Error (%d) parsing query.", discoveryResult);
+        }
+    }
+    else if (virtualUriInRequest == OC_DEVICE_URI)
+    {
+        payload = (OCPayload*)OCDevicePayloadCreate(OC_RSRVD_DEVICE_URI,
+                OCGetServerInstanceID(), savedDeviceInfo.deviceName,
+                OC_SPEC_VERSION, OC_DATA_MODEL_VERSION);
+        if (!payload)
+        {
+            discoveryResult = OC_STACK_NO_MEMORY;
+        }
+        else
+        {
+            discoveryResult = OC_STACK_OK;
+        }
+    }
+    else if (virtualUriInRequest == OC_PLATFORM_URI)
+    {
+        payload = (OCPayload*)OCPlatformPayloadCreate(
+                OC_RSRVD_PLATFORM_URI,
+                &savedPlatformInfo);
+        if (!payload)
+        {
+            discoveryResult = OC_STACK_NO_MEMORY;
+        }
+        else
+        {
+            discoveryResult = OC_STACK_OK;
+        }
+    }
 
-                response.ehResult = OC_EH_OK;
-                response.payload = discoveryResBuf;
-                response.payloadSize = strlen((const char *)discoveryResBuf) + 1;
-                response.persistentBufferFlag = 0;
-                response.requestHandle = (OCRequestHandle) request;
-                response.resourceHandle = (OCResourceHandle) resource;
+    /**
+     * Step 2: Send the discovery response
+     *
+     * Iotivity should respond to discovery requests in below manner:
+     * 1)If query filter matching fails and discovery request is multicast,
+     *   it should NOT send any response.
+     * 2)If query filter matching fails and discovery request is unicast,
+     *   it should send an error(RESOURCE_NOT_FOUND - 404) response.
+     * 3)If Server does not have any 'DISCOVERABLE' resources and discovery
+     *   request is multicast, it should NOT send any response.
+     * 4)If Server does not have any 'DISCOVERABLE' resources and discovery
+     *   request is unicast, it should send an error(RESOURCE_NOT_FOUND - 404) response.
+     */
 
-                result = OCDoResponse(&response);
-            }
+    #ifdef WITH_PRESENCE
+    if ((virtualUriInRequest == OC_PRESENCE) &&
+        (resource->resourceProperties & OC_ACTIVE))
+    {
+        // Presence uses observer notification api to respond via SendPresenceNotification.
+        SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
+    }
+    else
+    #endif
+    {
+        if(discoveryResult == OC_STACK_OK)
+        {
+            SendNonPersistantDiscoveryResponse(request, resource, payload, OC_EH_OK);
+        }
+        else if(bMulticast == false)
+        {
+            OC_LOG_V(ERROR, TAG, "Sending a (%d) error to (%d)  \
+                discovery request", discoveryResult, virtualUriInRequest);
+            SendNonPersistantDiscoveryResponse(request, resource, NULL,
+                (discoveryResult == OC_STACK_NO_RESOURCE) ? OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR);
         }
-        #ifdef WITH_PRESENCE
         else
         {
-            if(resource->resourceProperties & OC_ACTIVE){
-                SendPresenceNotification(NULL);
-            }
+            // Ignoring the discovery request as per RFC 7252, Section #8.2
+            OC_LOG_V(INFO, TAG, "Silently ignoring the request since device does not have \
+                any useful data to send");
         }
-        #endif
     }
-    result = OC_STACK_VIRTUAL_DO_NOT_HANDLE;
-    return result;
+
+    OCPayloadDestroy(payload);
+
+    return OC_STACK_OK;
 }
 
 static OCStackResult
 HandleDefaultDeviceEntityHandler (OCServerRequest *request)
 {
+    if(!request)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
     OCStackResult result = OC_STACK_OK;
     OCEntityHandlerResult ehResult = OC_EH_ERROR;
-    OCEntityHandlerRequest ehRequest = {0};
+    OCEntityHandlerRequest ehRequest = {};
 
     OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithDefaultDeviceEntityHandler"));
-    result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
-            request->method, (OCResourceHandle) NULL, request->query,
-            request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
-            request->rcvdVendorSpecificHeaderOptions, (OCObserveAction)request->observationOption, (OCObservationId)0);
+    result = FormOCEntityHandlerRequest(&ehRequest,
+                                        (OCRequestHandle) request,
+                                        request->method,
+                                        &request->devAddr,
+                                        (OCResourceHandle) NULL, request->query,
+                                        request->payload,
+                                        request->payloadSize,
+                                        request->numRcvdVendorSpecificHeaderOptions,
+                                        request->rcvdVendorSpecificHeaderOptions,
+                                        (OCObserveAction)request->observationOption,
+                                        (OCObservationId)0);
     VERIFY_SUCCESS(result, OC_STACK_OK);
 
     // At this point we know for sure that defaultDeviceHandler exists
     ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
-                                  (char*) request->resourceUrl);
+                                  (char*) request->resourceUrl, defaultDeviceHandlerCallbackParameter);
     if(ehResult == OC_EH_SLOW)
     {
         OC_LOG(INFO, TAG, PCF("This is a slow resource"));
@@ -592,19 +714,32 @@ HandleResourceWithEntityHandler (OCServerRequest *request,
                                  OCResource *resource,
                                  uint8_t collectionResource)
 {
+    if(!request || ! resource)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
     OCStackResult result = OC_STACK_ERROR;
     OCEntityHandlerResult ehResult = OC_EH_ERROR;
     OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
     ResourceObserver *resObs = NULL;
 
-    OCEntityHandlerRequest ehRequest = {0};
+    OCEntityHandlerRequest ehRequest = {};
 
     OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithEntityHandler"));
-    result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
-            request->method, (OCResourceHandle) resource, request->query,
-            request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
-            request->rcvdVendorSpecificHeaderOptions,
-            (OCObserveAction)request->observationOption, 0);
+
+    result = FormOCEntityHandlerRequest(&ehRequest,
+                                        (OCRequestHandle)request,
+                                        request->method,
+                                        &request->devAddr,
+                                        (OCResourceHandle)resource,
+                                        request->query,
+                                        request->payload,
+                                        request->payloadSize,
+                                        request->numRcvdVendorSpecificHeaderOptions,
+                                        request->rcvdVendorSpecificHeaderOptions,
+                                        (OCObserveAction)request->observationOption,
+                                        0);
     VERIFY_SUCCESS(result, OC_STACK_OK);
 
     if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
@@ -612,28 +747,33 @@ HandleResourceWithEntityHandler (OCServerRequest *request,
         OC_LOG(INFO, TAG, PCF("No observation requested"));
         ehFlag = OC_REQUEST_FLAG;
     }
-    else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER &&
-            !collectionResource)
+    else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER && !collectionResource)
     {
-        OC_LOG(INFO, TAG, PCF("Registering observation requested"));
+        OC_LOG(INFO, TAG, PCF("Observation registration requested"));
+
         result = GenerateObserverId(&ehRequest.obsInfo.obsId);
         VERIFY_SUCCESS(result, OC_STACK_OK);
 
         result = AddObserver ((const char*)(request->resourceUrl),
                 (const char *)(request->query),
-                ehRequest.obsInfo.obsId, &request->requestToken,
-                &request->requesterAddr, resource, request->qos);
+                ehRequest.obsInfo.obsId, request->requestToken, request->tokenLength,
+                resource, request->qos,
+                &request->devAddr);
+
         if(result == OC_STACK_OK)
         {
-            OC_LOG(DEBUG, TAG, PCF("Added observer successfully"));
+            OC_LOG(INFO, TAG, PCF("Added observer successfully"));
             request->observeResult = OC_STACK_OK;
             ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
         }
         else
         {
             result = OC_STACK_OK;
+
+            // The error in observeResult for the request will be used when responding to this
+            // request by omitting the observation option/sequence number.
             request->observeResult = OC_STACK_ERROR;
-            OC_LOG(DEBUG, TAG, PCF("Observer Addition failed"));
+            OC_LOG(ERROR, TAG, PCF("Observer Addition failed"));
             ehFlag = OC_REQUEST_FLAG;
         }
 
@@ -642,7 +782,9 @@ HandleResourceWithEntityHandler (OCServerRequest *request,
             !collectionResource)
     {
         OC_LOG(INFO, TAG, PCF("Deregistering observation requested"));
-        resObs = GetObserverUsingToken (&request->requestToken);
+
+        resObs = GetObserverUsingToken (request->requestToken, request->tokenLength);
+
         if (NULL == resObs)
         {
             // Stack does not contain this observation request
@@ -653,17 +795,18 @@ HandleResourceWithEntityHandler (OCServerRequest *request,
         ehRequest.obsInfo.obsId = resObs->observeId;
         ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
 
-        result = DeleteObserverUsingToken (&request->requestToken);
+        result = DeleteObserverUsingToken (request->requestToken, request->tokenLength);
+
         if(result == OC_STACK_OK)
         {
-            OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
+            OC_LOG(INFO, TAG, PCF("Removed observer successfully"));
             request->observeResult = OC_STACK_OK;
         }
         else
         {
             result = OC_STACK_OK;
             request->observeResult = OC_STACK_ERROR;
-            OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
+            OC_LOG(ERROR, TAG, PCF("Observer Removal failed"));
         }
     }
     else
@@ -672,7 +815,7 @@ HandleResourceWithEntityHandler (OCServerRequest *request,
         goto exit;
     }
 
-    ehResult = resource->entityHandler(ehFlag, &ehRequest);
+    ehResult = resource->entityHandler(ehFlag, &ehRequest, resource->entityHandlerCallbackParam);
     if(ehResult == OC_EH_SLOW)
     {
         OC_LOG(INFO, TAG, PCF("This is a slow resource"));
@@ -691,14 +834,26 @@ static OCStackResult
 HandleCollectionResourceDefaultEntityHandler (OCServerRequest *request,
                                               OCResource *resource)
 {
-    OCStackResult result = OC_STACK_ERROR;
-    OCEntityHandlerRequest ehRequest = {0};
+    if(!request || !resource)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
 
-    result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
-            request->method, (OCResourceHandle) resource, request->query,
-            request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
-            request->rcvdVendorSpecificHeaderOptions,
-            (OCObserveAction)request->observationOption, (OCObservationId) 0);
+    OCStackResult result = OC_STACK_ERROR;
+    OCEntityHandlerRequest ehRequest = {};
+
+    result = FormOCEntityHandlerRequest(&ehRequest,
+                                        (OCRequestHandle)request,
+                                        request->method,
+                                        &request->devAddr,
+                                        (OCResourceHandle)resource,
+                                        request->query,
+                                        request->payload,
+                                        request->payloadSize,
+                                        request->numRcvdVendorSpecificHeaderOptions,
+                                        request->rcvdVendorSpecificHeaderOptions,
+                                        (OCObserveAction)request->observationOption,
+                                        (OCObservationId)0);
     if(result != OC_STACK_OK)
     {
         return result;
@@ -758,109 +913,139 @@ ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerReque
     return ret;
 }
 
-void DeleteDeviceInfo()
+void DeletePlatformInfo()
 {
-    if(savedDeviceInfo)
-    {
-        cJSON_Delete(savedDeviceInfo);
-    }
-}
+    OC_LOG(INFO, TAG, PCF("Deleting platform info."));
 
-OCStackResult SaveDeviceInfo(OCDeviceInfo deviceInfo)
-{
-    DeleteDeviceInfo();
+    OICFree(savedPlatformInfo.platformID);
+    savedPlatformInfo.platformID = NULL;
 
-    savedDeviceInfo = cJSON_CreateObject();
-    cJSON *repObj = NULL;
+    OICFree(savedPlatformInfo.manufacturerName);
+    savedPlatformInfo.manufacturerName = NULL;
 
-    cJSON_AddItemToObject (savedDeviceInfo, OC_RSRVD_HREF,
-            cJSON_CreateString(GetVirtualResourceUri(OC_DEVICE_URI)));
+    OICFree(savedPlatformInfo.manufacturerUrl);
+    savedPlatformInfo.manufacturerUrl = NULL;
 
-    cJSON_AddItemToObject (savedDeviceInfo, "rep", repObj = cJSON_CreateObject());
+    OICFree(savedPlatformInfo.modelNumber);
+    savedPlatformInfo.modelNumber = NULL;
 
-    if (deviceInfo.contentType)
-    {
-        cJSON_AddItemToObject (repObj, "ct",
-                cJSON_CreateString(deviceInfo.contentType));
-    }
+    OICFree(savedPlatformInfo.dateOfManufacture);
+    savedPlatformInfo.dateOfManufacture = NULL;
 
-    if (deviceInfo.dateOfManufacture)
-    {
-        cJSON_AddItemToObject (repObj, "mndt",
-                cJSON_CreateString(deviceInfo.dateOfManufacture));
-    }
+    OICFree(savedPlatformInfo.platformVersion);
+    savedPlatformInfo.platformVersion = NULL;
 
-    if (deviceInfo.deviceName)
-    {
-        cJSON_AddItemToObject (repObj, "dn",
-                cJSON_CreateString(deviceInfo.deviceName));
-    }
+    OICFree(savedPlatformInfo.operatingSystemVersion);
+    savedPlatformInfo.operatingSystemVersion = NULL;
 
-    if (deviceInfo.deviceUUID)
-    {
-        cJSON_AddItemToObject (repObj, "di",
-                cJSON_CreateString(deviceInfo.deviceUUID));
-    }
+    OICFree(savedPlatformInfo.hardwareVersion);
+    savedPlatformInfo.hardwareVersion = NULL;
 
-    if (deviceInfo.firmwareVersion)
-    {
-        cJSON_AddItemToObject (repObj, "mnfv",
-                cJSON_CreateString(deviceInfo.firmwareVersion));
-    }
+    OICFree(savedPlatformInfo.firmwareVersion);
+    savedPlatformInfo.firmwareVersion = NULL;
+
+    OICFree(savedPlatformInfo.supportUrl);
+    savedPlatformInfo.supportUrl = NULL;
 
-    if (deviceInfo.hostName)
+    OICFree(savedPlatformInfo.systemTime);
+    savedPlatformInfo.systemTime = NULL;
+}
+
+static OCStackResult DeepCopyPlatFormInfo(OCPlatformInfo info)
+{
+    savedPlatformInfo.platformID = OICStrdup(info.platformID);
+    savedPlatformInfo.manufacturerName = OICStrdup(info.manufacturerName);
+    savedPlatformInfo.manufacturerUrl = OICStrdup(info.manufacturerUrl);
+    savedPlatformInfo.modelNumber = OICStrdup(info.modelNumber);
+    savedPlatformInfo.dateOfManufacture = OICStrdup(info.dateOfManufacture);
+    savedPlatformInfo.platformVersion = OICStrdup(info.platformVersion);
+    savedPlatformInfo.operatingSystemVersion = OICStrdup(info.operatingSystemVersion);
+    savedPlatformInfo.hardwareVersion = OICStrdup(info.hardwareVersion);
+    savedPlatformInfo.firmwareVersion = OICStrdup(info.firmwareVersion);
+    savedPlatformInfo.supportUrl = OICStrdup(info.supportUrl);
+    savedPlatformInfo.systemTime = OICStrdup(info.systemTime);
+
+    if ((!savedPlatformInfo.platformID && info.platformID)||
+        (!savedPlatformInfo.manufacturerName && info.manufacturerName)||
+        (!savedPlatformInfo.manufacturerUrl && info.manufacturerUrl)||
+        (!savedPlatformInfo.modelNumber && info.modelNumber)||
+        (!savedPlatformInfo.dateOfManufacture && info.dateOfManufacture)||
+        (!savedPlatformInfo.platformVersion && info.platformVersion)||
+        (!savedPlatformInfo.operatingSystemVersion && info.operatingSystemVersion)||
+        (!savedPlatformInfo.hardwareVersion && info.hardwareVersion)||
+        (!savedPlatformInfo.firmwareVersion && info.firmwareVersion)||
+        (!savedPlatformInfo.supportUrl && info.supportUrl)||
+        (!savedPlatformInfo.systemTime && info.systemTime))
     {
-        cJSON_AddItemToObject (repObj, "hn", cJSON_CreateString(deviceInfo.hostName));
+        DeletePlatformInfo();
+        return OC_STACK_INVALID_PARAM;
     }
 
-    if (deviceInfo.manufacturerName)
-    {
-        if(strlen(deviceInfo.manufacturerName) > MAX_MANUFACTURER_NAME_LENGTH)
-        {
-            DeleteDeviceInfo();
-            return OC_STACK_INVALID_PARAM;
-        }
+    return OC_STACK_OK;
 
-        cJSON_AddItemToObject (repObj, "mnmn",
-                cJSON_CreateString(deviceInfo.manufacturerName));
-    }
+}
 
-    if (deviceInfo.manufacturerUrl)
-    {
-        if(strlen(deviceInfo.manufacturerUrl) > MAX_MANUFACTURER_URL_LENGTH)
-        {
-            DeleteDeviceInfo();
-            return OC_STACK_INVALID_PARAM;
-        }
+OCStackResult SavePlatformInfo(OCPlatformInfo info)
+{
+    DeletePlatformInfo();
 
-        cJSON_AddItemToObject (repObj, "mnml",
-                cJSON_CreateString(deviceInfo.manufacturerUrl));
-    }
+    OCStackResult res = DeepCopyPlatFormInfo(info);
 
-    if (deviceInfo.modelNumber)
+    if (res != OC_STACK_OK)
     {
-        cJSON_AddItemToObject (repObj, "mnmo",
-                cJSON_CreateString(deviceInfo.modelNumber));
+        OC_LOG_V(ERROR, TAG, PCF("Failed to save platform info. errno(%d)"), res);
     }
-
-    if (deviceInfo.platformVersion)
+    else
     {
-        cJSON_AddItemToObject (repObj, "mnpv",
-                cJSON_CreateString(deviceInfo.platformVersion));
+        OC_LOG(ERROR, TAG, PCF("Platform info saved."));
     }
 
-    if (deviceInfo.supportUrl)
+    return res;
+}
+
+void DeleteDeviceInfo()
+{
+    OC_LOG(INFO, TAG, PCF("Deleting device info."));
+
+    OICFree(savedDeviceInfo.deviceName);
+    savedDeviceInfo.deviceName = NULL;
+}
+
+static OCStackResult DeepCopyDeviceInfo(OCDeviceInfo info)
+{
+    savedDeviceInfo.deviceName = OICStrdup(info.deviceName);
+
+    if(!savedDeviceInfo.deviceName && info.deviceName)
     {
-        cJSON_AddItemToObject (repObj, "mnsl",
-                cJSON_CreateString(deviceInfo.supportUrl));
+        DeleteDeviceInfo();
+        return OC_STACK_NO_MEMORY;
     }
 
-    if (deviceInfo.version)
+    return OC_STACK_OK;
+}
+
+OCStackResult SaveDeviceInfo(OCDeviceInfo info)
+{
+    OCStackResult res = OC_STACK_OK;
+
+    DeleteDeviceInfo();
+
+    res = DeepCopyDeviceInfo(info);
+
+    VERIFY_SUCCESS(res, OC_STACK_OK);
+
+    if(OCGetServerInstanceID() == NULL)
     {
-        cJSON_AddItemToObject (repObj, "icv",
-                cJSON_CreateString(deviceInfo.version));
+        OC_LOG(INFO, TAG, PCF("Device ID generation failed"));
+        res =  OC_STACK_ERROR;
+        goto exit;
     }
 
+    OC_LOG(INFO, TAG, PCF("Device initialized successfully."));
     return OC_STACK_OK;
-}
 
+    exit:
+        DeleteDeviceInfo();
+        return res;
+
+}