Add links and rep in the response for the collection
authorHabib Virji <habib.virji@samsung.com>
Wed, 30 Nov 2016 21:24:52 +0000 (21:24 +0000)
committerUze Choi <uzchoi@samsung.com>
Fri, 2 Dec 2016 01:04:53 +0000 (01:04 +0000)
- Use common ExtractParamFromQuery in ocresource and occollection to extract query parameters.
- Added links tag to the oic.if.ll and oic.if.baseline.
- Added rts tag in the payload for the baseline. - Added rep tag for oic.if.b response.
- occollection was using extra structure to differentiate ll, baseline, batch and group. Simplified the code to use
a simpler code and removed unwanted structure.
- oic.wk.col added in the types.
- OCStackIfTypes is removed as it was used only internally. This is not needed due to usage of ExtractParamFromQuery.
- BuildResponseRepresentation is updated as it is used in collection. For inner payload, these
values were not being used by ocpayloadconvert.
- oic.if.ll has been updated to give response in form of {links:[{href:"", rt:[""], if:[""]}]}
- oic.if.baseline has been updated to give response in form of {rt:[], if:[], rts:[], links:[{href:"", rt:[""], if:[""]}]}
- oic.if.b has been to response in form of [{"href": "", "rep": {""}}]
- in case of wrong query it will respond with error message.

Change-Id: I98489ac9923ab3c63012ddfe6b55c2b3064c3f28
Signed-off-by: Habib Virji <habib.virji@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/14621
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Uze Choi <uzchoi@samsung.com>
Tested-by: Uze Choi <uzchoi@samsung.com>
resource/csdk/stack/include/internal/occollection.h
resource/csdk/stack/include/internal/ocresource.h
resource/csdk/stack/include/internal/ocstackinternal.h
resource/csdk/stack/include/ocpayload.h
resource/csdk/stack/include/octypes.h
resource/csdk/stack/samples/linux/SimpleClientServer/occlientcoll.cpp
resource/csdk/stack/src/occollection.c
resource/csdk/stack/src/ocpayload.c
resource/csdk/stack/src/ocresource.c
resource/csdk/stack/src/ocserverrequest.c

index e421d06..24c7a18 100644 (file)
@@ -24,7 +24,7 @@
 #include "ocstack.h"
 #include "ocresourcehandler.h"
 
-uint8_t GetNumOfResourcesInCollection (OCResource *resource);
+uint8_t GetNumOfResourcesInCollection(const OCResource *resource);
 
 OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
                                               OCEntityHandlerRequest *entityHandlerRequest);
index 55b7860..1e6b12e 100755 (executable)
@@ -61,19 +61,6 @@ typedef struct PRESENCERESOURCE{
 struct rsrc_t;
 
 /**
- * Typedefs for stack interface
- * IF here stands for Interface
- */
-
-typedef enum {
-    STACK_IF_DEFAULT = 0,
-    STACK_IF_LL,
-    STACK_IF_BATCH,
-    STACK_IF_GROUP,
-    STACK_IF_INVALID
-} OCStackIfTypes;
-
-/**
  * following structure will be created in occollection.
  */
 
index 73910a0..02d725f 100644 (file)
@@ -287,6 +287,25 @@ void CopyEndpointToDevAddr(const CAEndpoint_t *in, OCDevAddr *out);
 
 void CopyDevAddrToEndpoint(const OCDevAddr *in, CAEndpoint_t *out);
 
+/**
+ * Get the CoAP ticks after the specified number of milli-seconds.
+ *
+ * @param milliSeconds Milli-seconds.
+ * @return CoAP ticks
+ */
+uint32_t GetTicks(uint32_t milliSeconds);
+
+/**
+ * Extract interface and resource type from the query.
+ *
+ * @param query is the request received from the client
+ * @param filterOne will include result if the interface is included in the query.
+ * @param filterTwo will include result if the resource type is included in the query.
+ *
+ * @return ::OC_STACK_OK on success, some other value upon failure
+ */
+OCStackResult ExtractFiltersFromQuery(const char *query, char **filterOne, char **filterTwo);
+
 #if defined(RD_CLIENT) || defined(RD_SERVER)
 /**
  * This function binds an resource unique ins value to the resource. This can be only called
index 0c534e9..204af4f 100644 (file)
@@ -74,6 +74,8 @@ size_t calcDimTotal(const size_t dimensions[MAX_REP_ARRAY_DEPTH]);
 
 OCRepPayload* OCRepPayloadClone(const OCRepPayload* payload);
 
+OCRepPayload* OCRepPayloadBatchClone(const OCRepPayload* repPayload);
+
 void OCRepPayloadAppend(OCRepPayload* parent, OCRepPayload* child);
 
 bool OCRepPayloadSetUri(OCRepPayload* payload, const char* uri);
index e36a9b9..2117fc3 100755 (executable)
@@ -154,6 +154,9 @@ extern "C" {
 /** To represent resource type with platform.*/
 #define OC_RSRVD_RESOURCE_TYPE_PLATFORM "oic.wk.p"
 
+/** To represent resource type with collection.*/
+#define OC_RSRVD_RESOURCE_TYPE_COLLECTION "oic.wk.col"
+
 /** To represent resource type with RES.*/
 #define OC_RSRVD_RESOURCE_TYPE_RES      "oic.wk.res"
 
index 9a5103d..16ca072 100644 (file)
@@ -59,6 +59,8 @@ typedef enum
     TEST_UNKNOWN_RESOURCE_GET_DEFAULT,
     TEST_UNKNOWN_RESOURCE_GET_BATCH,
     TEST_UNKNOWN_RESOURCE_GET_LINK_LIST,
+    TEST_GET_EMPTY,
+    TEST_GET_NULL,
     MAX_TESTS
 } CLIENT_TEST;
 
@@ -92,6 +94,8 @@ testToTextMap queryInterface[] = {
         {"?if=oic.if.baseline", TEST_PUT_DEFAULT},
         {"?if=oic.if.b", TEST_PUT_BATCH},
         {"?if=oic.if.ll", TEST_PUT_LINK_LIST},
+        {"", TEST_GET_EMPTY},
+        {NULL, TEST_GET_NULL},
 };
 
 
@@ -162,6 +166,11 @@ void PrintUsage()
                  "unavailable resource using batch interface.");
     OIC_LOG(INFO, TAG, "Test Case 9 : Discover Resources && Initiate GET Request on an "\
                  "unavailable resource using link list interface.");
+    OIC_LOG(INFO, TAG, "Test Case 10 : Discover Resources && Initiate GET Request on an "\
+                 "empty resource.");
+    OIC_LOG(INFO, TAG, "Test Case 11 : Discover Resources && Initiate GET Request on an "\
+                 "NULL resource.");
+
 }
 
 OCStackApplicationResult putReqCB(void* ctx, OCDoHandle /*handle*/,
@@ -448,4 +457,3 @@ std::string getQueryStrForGetPut()
 {
     return "/a/room";
 }
-
index 9769a93..aafb5ab 100755 (executable)
 // For POSIX.1-2001 base specification,
 // Refer http://pubs.opengroup.org/onlinepubs/009695399/
 #define _POSIX_C_SOURCE 200112L
+
 #include "occollection.h"
-#include <string.h>
+#include "ocpayload.h"
 #include "ocstack.h"
-#include "ocstackinternal.h"
-#include "ocresourcehandler.h"
-#include "logger.h"
-#include "cJSON.h"
-#include "oic_malloc.h"
+#include "oicgroup.h"
 #include "oic_string.h"
-#include "ocpayload.h"
 #include "payload_logging.h"
 
-/// Module Name
-#include <stdio.h>
-
-#define WITH_GROUPACTION 1
-
-#include "oicgroup.h"
-
 #define TAG "OIC_RI_COLLECTION"
 
-#define NUM_PARAM_IN_QUERY   2 // The expected number of parameters in a query
-#define NUM_FIELDS_IN_QUERY  2 // The expected number of fields in a query
-
-#include "platform_features.h"
-
-static OCStackResult CheckRTParamSupport(const OCResource* resource, const char* rtPtr)
-{
-    if (!resource || !rtPtr)
-    {
-        return OC_STACK_INVALID_PARAM;
-    }
-
-    OCResourceType* rTPointer = resource->rsrcType;
-    while (rTPointer)
-    {
-        if (strcmp(rTPointer->resourcetypename, rtPtr) == 0)
-        {
-            return OC_STACK_OK;
-        }
-
-        rTPointer = rTPointer->next;
-    }
-    return OC_STACK_ERROR;
-}
-
-static OCStackResult CheckIFParamSupport(const OCResource* resource, const char* ifPtr)
+static bool AddRTSBaslinePayload(OCRepPayload **linkArray, int size, OCRepPayload **colPayload)
 {
-    if (!resource || !ifPtr)
-    {
-        return OC_STACK_INVALID_PARAM;
-    }
-
-    OCResourceInterface* iFPointer = resource->rsrcInterface;
-    while (iFPointer)
+    size_t arraySize = 0;
+    for (int j = 0; j < size; j++)
     {
-        if (strcmp(iFPointer->name, ifPtr) == 0)
+        size_t rtDim[MAX_REP_ARRAY_DEPTH] = {0};
+        char **rt = NULL;
+        OCRepPayloadGetStringArray(linkArray[j], OC_RSRVD_RESOURCE_TYPE, &rt, rtDim);
+        arraySize += rtDim[0];
+        for (size_t l = 0; l < rtDim[0]; l++)
         {
-            return OC_STACK_OK;
+            OICFree(rt[l]);
         }
-
-        iFPointer = iFPointer->next;
     }
-    return OC_STACK_ERROR;
-}
-
-static OCStackResult
-ValidateQuery (const char *query, OCResourceHandle resource,
-               OCStackIfTypes *ifParam, char **rtParam)
-{
-    uint8_t numFields = 0;
-    uint8_t numParam;
 
-    //TODO: Query and URL validation is being done for virtual resource case
-    // using ValidateUrlQuery function. We should be able to merge it with this
-    // function.
-    OIC_LOG(INFO, TAG, "Entering ValidateQuery");
+    for (OCStringLL *rsrcType = (*colPayload)->types; rsrcType; rsrcType = rsrcType->next, arraySize++);
 
-    if (!query)
+    OIC_LOG_V(DEBUG, TAG, "Number of RTS elements : %zd", arraySize);
+    size_t dim[MAX_REP_ARRAY_DEPTH] = {arraySize, 0, 0};
+    char **rts = (char **)OICMalloc(sizeof(char *) * arraySize);
+    if (!rts)
     {
-        return OC_STACK_ERROR;
-    }
-
-    if (!ifParam || !rtParam)
-    {
-        return OC_STACK_INVALID_PARAM;
-    }
-
-    if (!(*query))
-    {
-        // Query string is empty
-        OIC_LOG(INFO, TAG, "Empty query string, use default IF and RT");
-        *ifParam = STACK_IF_DEFAULT;
-        *rtParam = (char *) OCGetResourceTypeName (resource, 0);
-        return OC_STACK_OK;
+        OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+        return OC_STACK_NO_MEMORY;
     }
-
-    // Break the query string to validate it and determine IF and RT parameters
-    // Validate there are atmost 2 parameters in string and that one is 'if' and other 'rt'
-    // separated by token '&' or ';'. Stack will accept both the versions.
-
-    char *endStr, *ifPtr = NULL, *rtPtr = NULL;
-    char *token = strtok_r ((char *)query, OC_QUERY_SEPARATOR , &endStr);
-
-    // External loop breaks query string into fields using the & separator
-    while (token != NULL)
+    int k = 0;
+    for (int j = 0; j < size; j++)
     {
-        numFields++;
-        char *endToken;
-        char *innerToken = strtok_r (token, "=", &endToken);
-        numParam = 0;
-
-        // Internal loop parses the field to extract values (parameters) assigned to each field
-        while (innerToken != NULL)
-        {
-            numParam++;
-            if (strncmp (innerToken, OC_RSRVD_INTERFACE, sizeof(OC_RSRVD_INTERFACE)) == 0)
-            {
-                // Determine the value of IF parameter
-                innerToken = strtok_r (NULL, "=", &endToken);
-                ifPtr = innerToken;
-            }
-            else if (strcmp (innerToken, OC_RSRVD_RESOURCE_TYPE) == 0)
-            {
-                // Determine the value of RT parameter
-                innerToken = strtok_r (NULL, "=", &endToken);
-                rtPtr = innerToken;
-            }
-            else
-            {
-                innerToken = strtok_r (NULL, "=", &endToken);
-            }
-        }
-        if (numParam != NUM_PARAM_IN_QUERY)
+        size_t rtDim[MAX_REP_ARRAY_DEPTH] = {0};
+        char **rt = NULL;
+        OCRepPayloadGetStringArray(linkArray[j], OC_RSRVD_RESOURCE_TYPE, &rt, rtDim);
+        for (size_t l = 0; l < rtDim[0]; l++)
         {
-            // Query parameter should be of the form if=<string>. String should not have & or =
-            return OC_STACK_INVALID_QUERY;
+            rts[k++] = OICStrdup(rt[l]);
+            OICFree(rt[l]);
         }
-        token = strtok_r (NULL, OC_QUERY_SEPARATOR, &endStr);
     }
-
-    if (numFields > NUM_FIELDS_IN_QUERY)
+    for (OCStringLL *rsrcType = (*colPayload)->types; rsrcType; rsrcType = rsrcType->next, size++)
     {
-        // current release supports one IF value, one RT value and no other params
-        return OC_STACK_INVALID_QUERY;
+        rts[k++] = OICStrdup(rsrcType->value);
     }
 
-    if (ifPtr)
-    {
-        if (CheckIFParamSupport((OCResource *)resource, ifPtr) != OC_STACK_OK)
-        {
-            return OC_STACK_INVALID_QUERY;
-        }
-        if (strcmp (ifPtr, OC_RSRVD_INTERFACE_DEFAULT) == 0)
-        {
-            *ifParam = STACK_IF_DEFAULT;
-        }
-        else if (strcmp (ifPtr, OC_RSRVD_INTERFACE_LL) == 0)
-        {
-            *ifParam = STACK_IF_LL;
-        }
-        else if (strcmp (ifPtr, OC_RSRVD_INTERFACE_BATCH) == 0)
-        {
-            *ifParam = STACK_IF_BATCH;
-        }
-        else if (strcmp (ifPtr, OC_RSRVD_INTERFACE_GROUP) == 0)
-        {
-            *ifParam = STACK_IF_GROUP;
-        }
-        else
-        {
-            return OC_STACK_ERROR;
-        }
-    }
-    else
-    {
-        // IF not specified in query, use default IF
-        *ifParam = STACK_IF_DEFAULT;
-    }
+    return OCRepPayloadSetStringArrayAsOwner(*colPayload, OC_RSRVD_RTS, rts, dim);
+}
 
-    if (rtPtr)
-    {
-        if (CheckRTParamSupport((OCResource *)resource, rtPtr) == OC_STACK_OK)
-        {
-            *rtParam = rtPtr;
-        }
-        else
-        {
-            return OC_STACK_INVALID_QUERY;
-        }
-    }
-    else
+static OCStackResult SendResponse(const OCRepPayload *payload, const OCEntityHandlerRequest *ehRequest,
+    const OCResource* collResource, OCEntityHandlerResult ehResult)
+{
+    OCEntityHandlerResponse response = {0};
+    response.ehResult = ehResult;
+    response.payload = (OCPayload*)payload;
+    response.persistentBufferFlag = 0;
+    response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
+    response.resourceHandle = (OCResourceHandle) collResource;
+    return OCDoResponse(&response);
+}
+
+uint8_t GetNumOfResourcesInCollection(const OCResource *collResource)
+{
+    uint8_t size = 0;
+    for (OCChildResource *tempChildResource = collResource->rsrcChildResourcesHead;
+        tempChildResource; tempChildResource = tempChildResource->next)
     {
-        // RT not specified in query. Use the first resource type for the resource as default.
-        *rtParam = (char *) OCGetResourceTypeName (resource, 0);
+        size++;
     }
-    OIC_LOG_V(INFO, TAG, "Query params: IF = %d, RT = %s", *ifParam, *rtParam);
-
-    return OC_STACK_OK;
+    return size;
 }
 
-static OCStackResult
-HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest,
-                          uint8_t filterOn,
-                          char *filterValue)
+static OCStackResult HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest, char *ifQueryParam)
 {
-    (void)filterOn;
-    (void)filterValue;
     if (!ehRequest)
     {
         return OC_STACK_INVALID_PARAM;
     }
 
     OCResource *collResource = (OCResource *)ehRequest->resource;
-    OCChildResource *tempChildResource = NULL;
-    OCRepPayload* payload = NULL;
-
-    if(!collResource)
+    if (!collResource)
     {
         return OC_STACK_INVALID_PARAM;
     }
 
-    OCStackResult ret = BuildResponseRepresentation(collResource, &payload, &ehRequest->devAddr);
+    uint8_t size = GetNumOfResourcesInCollection(collResource);
+    OCRepPayload *colPayload = NULL;
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    int i = 0;
+    OCStackResult ret = OC_STACK_OK;
+    size_t dim[MAX_REP_ARRAY_DEPTH] = {size, 0, 0};
+    OCRepPayload **linkArr = (OCRepPayload **)OICCalloc(size, sizeof(OCRepPayload *));
+    VERIFY_PARAM_NON_NULL(TAG, linkArr, "Failed creating LinkArray");
+
+    for (OCChildResource *tempChildResource = collResource->rsrcChildResourcesHead;
+        tempChildResource && ret == OC_STACK_OK; tempChildResource = tempChildResource->next)
+    {
+        OCResource* temp = tempChildResource->rsrcResource;
+        if (temp)
+        {
+            ret = BuildResponseRepresentation(temp, &linkArr[i++], &ehRequest->devAddr);
+        }
+    }
+
     if (ret == OC_STACK_OK)
     {
-        tempChildResource = collResource->rsrcChildResourcesHead;
-        while (tempChildResource && ret == OC_STACK_OK)
+        colPayload = OCRepPayloadCreate();
+        if (colPayload)
         {
-            OCResource* temp = tempChildResource->rsrcResource;
-            if (temp)
+            if (0 == strcmp(OC_RSRVD_INTERFACE_DEFAULT, ifQueryParam))
             {
                 //TODO : Add resource type filtering once collections
                 // start supporting queries.
-                ret = BuildResponseRepresentation(temp, &payload, &ehRequest->devAddr);
+                OCRepPayloadAddResourceType(colPayload, OC_RSRVD_RESOURCE_TYPE_COLLECTION);
+                for (OCResourceType *types = collResource->rsrcType; types; types = types->next)
+                {
+                    if (0 != strcmp(OC_RSRVD_RESOURCE_TYPE_COLLECTION, types->resourcetypename))
+                    {
+                        OCRepPayloadAddResourceType(colPayload, types->resourcetypename);
+                    }
+                }
+                for (OCResourceInterface *itf = collResource->rsrcInterface; itf; itf = itf->next)
+                {
+                    OCRepPayloadAddInterface(colPayload, itf->name);
+                }
+                AddRTSBaslinePayload(linkArr, i, &colPayload);
             }
-
-            tempChildResource = tempChildResource->next;
+            OCRepPayloadSetPropObjectArrayAsOwner(colPayload, OC_RSRVD_LINKS, linkArr, dim);
         }
     }
 
+exit:
     if (ret == OC_STACK_OK)
     {
-        OCEntityHandlerResponse response = {0};
-        response.ehResult = OC_EH_OK;
-        response.payload = (OCPayload*)payload;
-        response.persistentBufferFlag = 0;
-        response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
-        response.resourceHandle = (OCResourceHandle) collResource;
-        ret = OCDoResponse(&response);
+        ehResult = OC_EH_OK;
     }
+    else
+    {
+        ehResult = (ret == OC_STACK_NO_RESOURCE) ? OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR;
+    }
+    ret = SendResponse(colPayload, ehRequest, collResource, ehResult);
+    OIC_LOG_PAYLOAD(DEBUG, (OCPayload *)colPayload);
 
-    OCRepPayloadDestroy(payload);
     return ret;
 }
 
-static OCStackResult
-HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
+static OCStackResult HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
 {
     if (!ehRequest)
     {
         return OC_STACK_INVALID_PARAM;
     }
 
-    OCResource * collResource = (OCResource *) ehRequest->resource;
-
-    OCRepPayload* payload = OCRepPayloadCreate();
-    if (!payload)
-    {
-        return OC_STACK_NO_MEMORY;
-    }
+    OCStackResult stackRet = OC_STACK_OK;
+    char *storeQuery = NULL;
+    OCRepPayload *payload = OCRepPayloadCreate();
+    OCResource *collResource = (OCResource *)ehRequest->resource;
+    VERIFY_PARAM_NON_NULL(TAG, payload, "Failed creating RepPayload");
 
-    if (collResource)
+    if (stackRet == OC_STACK_OK)
     {
-        OCRepPayloadSetUri(payload, collResource->uri);
-    }
 
-    OCEntityHandlerResponse response = {0};
-    response.ehResult = OC_EH_OK;
-    response.payload = (OCPayload*)payload;
-    response.persistentBufferFlag = 0;
-    response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
-    response.resourceHandle = (OCResourceHandle) collResource;
-    OCStackResult stackRet = OCDoResponse(&response);
+        if (collResource->rsrcChildResourcesHead)
+        {
+            storeQuery = OICStrdup(ehRequest->query);
+            ehRequest->query = NULL;
+            OIC_LOG_V(DEBUG, TAG, "Query : %s", ehRequest->query);
+        }
 
-    if (stackRet == OC_STACK_OK)
-    {
-        OCChildResource *tempChildResource = (collResource) ? collResource->rsrcChildResourcesHead
-                                                              : NULL;
-        while(tempChildResource)
+        uint8_t numRes = 0;
+        for (OCChildResource *tempChildResource = collResource->rsrcChildResourcesHead;
+            tempChildResource; tempChildResource = tempChildResource->next, numRes++)
         {
             OCResource* tempRsrcResource = tempChildResource->rsrcResource;
-
             if (tempRsrcResource)
             {
                 // Note that all entity handlers called through a collection
                 // will get the same pointer to ehRequest, the only difference
                 // is ehRequest->resource
                 ehRequest->resource = (OCResourceHandle) tempRsrcResource;
-
                 OCEntityHandlerResult ehResult = tempRsrcResource->entityHandler(OC_REQUEST_FLAG,
                                            ehRequest, tempRsrcResource->entityHandlerCallbackParam);
 
@@ -350,175 +237,75 @@ HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
             {
                 break;
             }
-
-            tempChildResource = tempChildResource->next;
-
         }
-
         ehRequest->resource = (OCResourceHandle) collResource;
     }
+    ehRequest->query = OICStrdup(storeQuery);
+    OICFree(storeQuery);
     return stackRet;
+exit:
+    OICFree(storeQuery);
+    return OC_STACK_NO_MEMORY;
 }
 
-uint8_t GetNumOfResourcesInCollection (OCResource *resource)
-{
-    if (resource)
-    {
-        uint8_t num = 0;
-        OCChildResource *tempChildResource = NULL;
-
-        tempChildResource = resource->rsrcChildResourcesHead;
-
-        while(tempChildResource)
-        {
-            num++;
-            tempChildResource = tempChildResource->next;
-        }
-
-        return num;
-    }
-    else
-    {
-        return -1;
-    }
-}
-
-
-OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
-                                              OCEntityHandlerRequest *ehRequest)
+OCStackResult DefaultCollectionEntityHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest *ehRequest)
 {
     if (!ehRequest || !ehRequest->query)
     {
         return OC_STACK_INVALID_PARAM;
     }
-
-    OIC_LOG_V(INFO, TAG, "DefaultCollectionEntityHandler with query %s", ehRequest->query);
-
-    if (flag != OC_REQUEST_FLAG)
+    // Delete is not supported for any interface query method.
+    if (ehRequest->method == OC_REST_DELETE || flag != OC_REQUEST_FLAG)
     {
         return OC_STACK_ERROR;
     }
+    OIC_LOG_V(INFO, TAG, "DefaultCollectionEntityHandler with query %s", ehRequest->query);
 
-    OCStackIfTypes ifQueryParam = STACK_IF_INVALID;
+    char *ifQueryParam = NULL;
     char *rtQueryParam = NULL;
-    OCStackResult result = ValidateQuery (ehRequest->query,
-                                          ehRequest->resource, &ifQueryParam, &rtQueryParam);
-
+    OCStackResult result = ExtractFiltersFromQuery(ehRequest->query, &ifQueryParam, &rtQueryParam);
     if (result != OC_STACK_OK)
     {
-        return result;
+        result = OC_STACK_NO_RESOURCE;
+        goto exit;
     }
-
-    switch (ehRequest->method)
+    if (!ifQueryParam)
     {
-        case OC_REST_GET:
-            switch (ifQueryParam)
-            {
-                case STACK_IF_DEFAULT:
-                    // Get attributes of collection resource and properties of contained resources
-                    // M1 release does not support attributes for collection resource, so the GET
-                    // operation is same as the GET on LL interface.
-                    OIC_LOG(INFO, TAG, "STACK_IF_DEFAULT");
-                    return HandleLinkedListInterface(ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
-
-                case STACK_IF_LL:
-                    OIC_LOG(INFO, TAG, "STACK_IF_LL");
-                    return HandleLinkedListInterface(ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
-
-                case STACK_IF_BATCH:
-                {
-                    OIC_LOG(INFO, TAG, "STACK_IF_BATCH");
-                    OCServerRequest *request =
-                            GetServerRequestUsingHandle(ehRequest->requestHandle);
-                    if (request)
-                    {
-                        request->ehResponseHandler = HandleAggregateResponse;
-                        request->numResponses =
-                            GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
-                    }
-
-                    return HandleBatchInterface(ehRequest);
-                }
-                case STACK_IF_GROUP:
-                    return BuildCollectionGroupActionCBORResponse(OC_REST_GET/*flag*/,
-                            (OCResource *) ehRequest->resource, ehRequest);
-
-                default:
-                    return OC_STACK_ERROR;
-            }
-
-        case OC_REST_PUT:
-            switch (ifQueryParam)
-            {
-                case STACK_IF_DEFAULT:
-                    // M1 release does not support PUT on default interface
-                    return OC_STACK_ERROR;
-
-                case STACK_IF_LL:
-                    // LL interface only supports GET
-                    return OC_STACK_ERROR;
-
-                case STACK_IF_BATCH:
-                {
-                    OCServerRequest *request =
-                            GetServerRequestUsingHandle(ehRequest->requestHandle);
-                    if (request)
-                    {
-                        request->ehResponseHandler = HandleAggregateResponse;
-                        request->numResponses =
-                            GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
-                    }
-                    return HandleBatchInterface(ehRequest);
-                }
-                case STACK_IF_GROUP:
-                    OIC_LOG(INFO, TAG, "IF_COLLECTION PUT with request ::\n");
-                    OIC_LOG_PAYLOAD(INFO, ehRequest->payload);
-                    return BuildCollectionGroupActionCBORResponse(OC_REST_PUT/*flag*/,
-                            (OCResource *) ehRequest->resource, ehRequest);
-
-                default:
-                    return OC_STACK_ERROR;
-            }
-
-        case OC_REST_POST:
-            switch (ifQueryParam)
-            {
-                case STACK_IF_DEFAULT:
-                    // M1 release does not support POST on default interface
-                    return OC_STACK_ERROR;
-
-                case STACK_IF_LL:
-                    // LL interface only supports GET
-                    return OC_STACK_ERROR;
-
-                case STACK_IF_BATCH:
-                {
-                    OCServerRequest *request =
-                            GetServerRequestUsingHandle(ehRequest->requestHandle);
-                    if (request)
-                    {
-                        request->ehResponseHandler = HandleAggregateResponse;
-                        request->numResponses =
-                            GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
-                    }
-                    return HandleBatchInterface(ehRequest);
-                }
-
-                case STACK_IF_GROUP:
-                    OIC_LOG(INFO, TAG, "IF_COLLECTION POST with request ::\n");
-                    OIC_LOG_PAYLOAD(INFO, ehRequest->payload);
-                    return BuildCollectionGroupActionCBORResponse(OC_REST_POST/*flag*/,
-                            (OCResource *) ehRequest->resource, ehRequest);
-
-                default:
-                    return OC_STACK_ERROR;
-            }
-
-        case OC_REST_DELETE:
-            // TODO implement DELETE accordingly to the desired behavior
-            return OC_STACK_ERROR;
-
-        default:
-            return OC_STACK_ERROR;
+        ifQueryParam = OICStrdup(OC_RSRVD_INTERFACE_LL);
+    }
+    if (0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_LL) || 0 == strcmp (ifQueryParam, OC_RSRVD_INTERFACE_DEFAULT))
+    {
+        if (ehRequest->method == OC_REST_PUT || ehRequest->method == OC_REST_POST)
+        {
+            result =  OC_STACK_ERROR;
+        }
+        else
+        {
+            result = HandleLinkedListInterface(ehRequest, ifQueryParam);
+        }
+    }
+    else if (0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_BATCH))
+    {
+        OCServerRequest *request = GetServerRequestUsingHandle(ehRequest->requestHandle);
+        if (request)
+        {
+            request->numResponses = GetNumOfResourcesInCollection((OCResource *)ehRequest->resource);
+            request->ehResponseHandler = HandleAggregateResponse;
+            result = HandleBatchInterface(ehRequest);
+        }
+    }
+    else if (0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_GROUP))
+    {
+        OIC_LOG_V(INFO, TAG, "IF_COLLECTION %d with request ::\n", ehRequest->method);
+        OIC_LOG_PAYLOAD(INFO, ehRequest->payload);
+        result = BuildCollectionGroupActionCBORResponse(ehRequest->method, (OCResource *) ehRequest->resource, ehRequest);
+    }
+exit:
+    if (result != OC_STACK_OK)
+    {
+        result = SendResponse(NULL, ehRequest, (OCResource *)ehRequest->resource, OC_EH_BAD_REQ);
     }
+    OICFree(ifQueryParam);
+    OICFree(rtQueryParam);
+    return result;
 }
index 6958938..a04f840 100644 (file)
@@ -1580,6 +1580,29 @@ OCRepPayload* OCRepPayloadClone (const OCRepPayload* payload)
     return clone;
 }
 
+OCRepPayload* OCRepPayloadBatchClone(const OCRepPayload* repPayload)
+{
+    OCRepPayload *newPayload = OCRepPayloadCreate();
+    if (!newPayload)
+    {
+        return NULL;
+    }
+
+    newPayload->uri = OICStrdup(repPayload->uri);
+    OCRepPayload *clone = OCRepPayloadCreate();
+    if (!clone)
+    {
+        OCPayloadDestroy((OCPayload *)newPayload);
+        return NULL;
+    }
+
+    clone->types  = CloneOCStringLL(repPayload->types);
+    clone->interfaces  = CloneOCStringLL(repPayload->interfaces);
+    clone->values = OCRepPayloadValueClone(repPayload->values);
+    OCRepPayloadSetPropObjectAsOwner(newPayload, OC_RSRVD_REPRESENTATION, clone);
+
+    return newPayload;
+}
 
 void OCRepPayloadDestroy(OCRepPayload* payload)
 {
index fb1597f..a8747ba 100755 (executable)
@@ -44,7 +44,6 @@
 #include "oic_malloc.h"
 #include "oic_string.h"
 #include "logger.h"
-#include "cJSON.h"
 #include "ocpayload.h"
 #include "secureresourcemanager.h"
 #include "cacommon.h"
@@ -137,8 +136,13 @@ static OCStackResult GetTCPPortInfo(OCDevAddr *endpoint, uint16_t *port, bool se
  * 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)
+OCStackResult ExtractFiltersFromQuery(const char *query, char **filterOne, char **filterTwo)
 {
+    if (!query)
+    {
+        OIC_LOG_V(ERROR, TAG, "Query is empty!");
+        return OC_STACK_INVALID_QUERY;
+    }
     char *key = NULL;
     char *value = NULL;
     char *queryDup = NULL;
@@ -292,14 +296,14 @@ static OCStackResult getQueryParamsForFiltering (OCVirtualResources uri, char *q
     *filterOne = NULL;
     *filterTwo = NULL;
 
-    #ifdef WITH_PRESENCE
+#ifdef WITH_PRESENCE
     if (uri == OC_PRESENCE)
     {
         //Nothing needs to be done, except for pass a OC_PRESENCE query through as OC_STACK_OK.
         OIC_LOG(INFO, TAG, "OC_PRESENCE Request for virtual resource.");
         return OC_STACK_OK;
     }
-    #endif
+#endif
 
     OCStackResult result = OC_STACK_OK;
 
@@ -341,14 +345,12 @@ exit:
 
 static OCStackResult BuildDevicePlatformPayload(const OCResource *resourcePtr, OCRepPayload** payload, bool addDeviceId)
 {
-    OCRepPayload *tempPayload = OCRepPayloadCreate();
-
     if (!resourcePtr)
     {
-        OCRepPayloadDestroy(tempPayload);
         return OC_STACK_INVALID_PARAM;
     }
 
+    OCRepPayload *tempPayload = OCRepPayloadCreate();
     if (!tempPayload)
     {
         return OC_STACK_NO_MEMORY;
@@ -429,23 +431,37 @@ OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr,
         return OC_STACK_NO_MEMORY;
     }
 
-    OCRepPayloadSetUri(tempPayload, resourcePtr->uri);
-    OCResourceType *resType = resourcePtr->rsrcType;
-    while(resType)
+    OCRepPayloadSetPropString(tempPayload, OC_RSRVD_HREF, resourcePtr->uri);
+
+    uint8_t numElement = 0;
+    if (OC_STACK_OK == OCGetNumberOfResourceTypes((OCResource *)resourcePtr, &numElement))
     {
-        OCRepPayloadAddResourceType(tempPayload, resType->resourcetypename);
-        resType = resType->next;
+        size_t rtDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
+        char **rt = (char **)OICMalloc(sizeof(char *) * numElement);
+        for (uint8_t i = 0; i < numElement; ++i)
+        {
+            const char *value = OCGetResourceTypeName((OCResource *)resourcePtr, i);
+            OIC_LOG_V(DEBUG, TAG, "value: %s", value);
+            rt[i] = OICStrdup(value);
+        }
+        OCRepPayloadSetStringArrayAsOwner(tempPayload, OC_RSRVD_RESOURCE_TYPE, rt, rtDim);
     }
 
-    OCResourceInterface *resInterface = resourcePtr->rsrcInterface;
-    while(resInterface)
+    numElement = 0;
+    if (OC_STACK_OK == OCGetNumberOfResourceInterfaces((OCResource *)resourcePtr, &numElement))
     {
-        OCRepPayloadAddInterface(tempPayload, resInterface->name);
-        resInterface = resInterface->next;
+        size_t ifDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
+        char **itf = (char **)OICMalloc(sizeof(char *) * numElement);
+        for (uint8_t i = 0; i < numElement; ++i)
+        {
+            const char *value = OCGetResourceInterfaceName((OCResource *)resourcePtr, i);
+            OIC_LOG_V(DEBUG, TAG, "value: %s", value);
+            itf[i] = OICStrdup(value);
+        }
+        OCRepPayloadSetStringArrayAsOwner(tempPayload, OC_RSRVD_INTERFACE, itf, ifDim);
     }
 
-    OCAttribute *resAttrib = resourcePtr->rsrcAttributes;
-    while(resAttrib)
+    for (OCAttribute *resAttrib = resourcePtr->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
     {
         if (resAttrib->attrName && resAttrib->attrValue)
         {
@@ -463,7 +479,6 @@ OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr,
                 OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, (char *)resAttrib->attrValue);
             }
         }
-        resAttrib = resAttrib->next;
     }
 
     if (devAddr)
@@ -489,7 +504,7 @@ OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr,
         OCRepPayloadSetPropObjectAsOwner(tempPayload, OC_RSRVD_POLICY, policy);
     }
 
-    if(!*payload)
+    if (!*payload)
     {
         *payload = tempPayload;
     }
@@ -529,21 +544,6 @@ OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
     return OC_STACK_OK;
 }
 
-uint8_t IsCollectionResource (OCResource *resource)
-{
-    if(!resource)
-    {
-        return 0;
-    }
-
-    if(resource->rsrcChildResourcesHead != NULL)
-    {
-        return 1;
-    }
-
-    return 0;
-}
-
 OCResource *FindResourceByUri(const char* resourceUri)
 {
     if(!resourceUri)
@@ -564,7 +564,6 @@ OCResource *FindResourceByUri(const char* resourceUri)
     return NULL;
 }
 
-
 OCStackResult DetermineResourceHandling (const OCServerRequest *request,
                                          ResourceHandling *handling,
                                          OCResource **resource)
@@ -608,7 +607,7 @@ OCStackResult DetermineResourceHandling (const OCServerRequest *request,
             return OC_STACK_NO_RESOURCE;
         }
 
-        if (IsCollectionResource (resourcePtr))
+        if (resourcePtr && resourcePtr->rsrcChildResourcesHead != NULL)
         {
             // Collection resource
             if (resourcePtr->entityHandler != defaultResourceEHandler)
@@ -694,15 +693,12 @@ static bool resourceMatchesRTFilter(OCResource *resource, char *resourceTypeFilt
         return true;
     }
 
-    OCResourceType *resourceTypePtr = resource->rsrcType;
-
-    while (resourceTypePtr)
+    for (OCResourceType *rtPtr = resource->rsrcType; rtPtr; rtPtr = rtPtr->next)
     {
-        if (strcmp (resourceTypePtr->resourcetypename, resourceTypeFilter) == 0)
+        if (0 == strcmp(rtPtr->resourcetypename, resourceTypeFilter))
         {
             return true;
         }
-        resourceTypePtr = resourceTypePtr->next;
     }
 
     OIC_LOG_V(INFO, TAG, "%s does not contain rt=%s.", resource->uri, resourceTypeFilter);
@@ -722,17 +718,14 @@ static bool resourceMatchesIFFilter(OCResource *resource, char *interfaceFilter)
         return true;
     }
 
-    OCResourceInterface *interfacePtr = resource->rsrcInterface;
-
-    while (interfacePtr)
+    for (OCResourceInterface *ifPtr = resource->rsrcInterface; ifPtr; ifPtr = ifPtr->next)
     {
-        if (strcmp (interfacePtr->name, interfaceFilter) == 0 ||
-            strcmp (OC_RSRVD_INTERFACE_LL, interfaceFilter) == 0 ||
-            strcmp (OC_RSRVD_INTERFACE_DEFAULT, interfaceFilter) == 0)
+        if (0 == strcmp(ifPtr->name, interfaceFilter) ||
+            0 == strcmp(OC_RSRVD_INTERFACE_LL, interfaceFilter) ||
+            0 == strcmp(OC_RSRVD_INTERFACE_DEFAULT, interfaceFilter))
         {
             return true;
         }
-        interfacePtr = interfacePtr->next;
     }
 
     OIC_LOG_V(INFO, TAG, "%s does not contain if=%s.", resource->uri, interfaceFilter);
@@ -762,12 +755,12 @@ static bool includeThisResourceInResponse(OCResource *resource,
          */
         if (!(resourceTypeFilter && *resourceTypeFilter))
         {
-            OIC_LOG_V(INFO, TAG, "%s no query string for EXPLICIT_DISCOVERABLE \
+            OIC_LOG_V(INFO, TAG, "%s no query string for EXPLICIT_DISCOVERABLE\
                 resource", resource->uri);
             return false;
         }
     }
-    else if ( !(resource->resourceProperties & OC_ACTIVE) ||
+    else if (!(resource->resourceProperties & OC_ACTIVE) ||
          !(resource->resourceProperties & OC_DISCOVERABLE))
     {
         OIC_LOG_V(INFO, TAG, "%s not ACTIVE or DISCOVERABLE", resource->uri);
@@ -776,7 +769,6 @@ static bool includeThisResourceInResponse(OCResource *resource,
 
     return resourceMatchesIFFilter(resource, interfaceFilter) &&
            resourceMatchesRTFilter(resource, resourceTypeFilter);
-
 }
 
 OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCResource *resource,
@@ -792,6 +784,26 @@ OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCRes
 
     return OCDoResponse(&response);
 }
+
+static OCStackResult EHRequest(OCEntityHandlerRequest *ehRequest, OCPayloadType type,
+    OCServerRequest *request, OCResource *resource)
+{
+    return FormOCEntityHandlerRequest(ehRequest,
+                                     (OCRequestHandle)request->requestId,
+                                     request->method,
+                                     &request->devAddr,
+                                     (OCResourceHandle)resource,
+                                     request->query,
+                                     type,
+                                     request->payload,
+                                     request->payloadSize,
+                                     request->numRcvdVendorSpecificHeaderOptions,
+                                     request->rcvdVendorSpecificHeaderOptions,
+                                     (OCObserveAction)request->observationOption,
+                                     (OCObservationId)0,
+                                     request->coapID);
+}
+
 #ifdef RD_SERVER
 /**
  * Find resource at the resource directory server. This resource is not local resource but a
@@ -929,7 +941,7 @@ static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource
 #endif
             )
     {
-        discoveryResult = getQueryParamsForFiltering (virtualUriInRequest, request->query,
+        discoveryResult = getQueryParamsForFiltering(virtualUriInRequest, request->query,
                 &interfaceQuery, &resourceTypeQuery);
         VERIFY_SUCCESS(discoveryResult);
         if (!interfaceQuery && !resourceTypeQuery)
@@ -1090,31 +1102,17 @@ exit:
 }
 
 static OCStackResult
-HandleDefaultDeviceEntityHandler (OCServerRequest *request)
+HandleDefaultDeviceEntityHandler(OCServerRequest *request)
 {
-    if(!request)
+    if (!request)
     {
         return OC_STACK_INVALID_PARAM;
     }
 
-    OCStackResult result = OC_STACK_OK;
     OCEntityHandlerResult ehResult = OC_EH_ERROR;
     OCEntityHandlerRequest ehRequest = {0};
-
     OIC_LOG(INFO, TAG, "Entering HandleResourceWithDefaultDeviceEntityHandler");
-    result = FormOCEntityHandlerRequest(&ehRequest,
-                                        (OCRequestHandle) request->requestId,
-                                        request->method,
-                                        &request->devAddr,
-                                        (OCResourceHandle) NULL, request->query,
-                                        PAYLOAD_TYPE_REPRESENTATION,
-                                        request->payload,
-                                        request->payloadSize,
-                                        request->numRcvdVendorSpecificHeaderOptions,
-                                        request->rcvdVendorSpecificHeaderOptions,
-                                        (OCObserveAction)request->observationOption,
-                                        (OCObservationId)0,
-                                        request->coapID);
+    OCStackResult result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, NULL);
     VERIFY_SUCCESS(result);
 
     // At this point we know for sure that defaultDeviceHandler exists
@@ -1136,12 +1134,9 @@ exit:
 }
 
 static OCStackResult
-HandleResourceWithEntityHandler (OCServerRequest *request,
-                                 OCResource *resource,
-                                 uint8_t collectionResource)
+HandleResourceWithEntityHandler(OCServerRequest *request,
+                                OCResource *resource)
 {
-    OC_UNUSED(collectionResource);
-
     if(!request || ! resource)
     {
         return OC_STACK_INVALID_PARAM;
@@ -1162,20 +1157,7 @@ HandleResourceWithEntityHandler (OCServerRequest *request,
         type = PAYLOAD_TYPE_SECURITY;
     }
 
-    result = FormOCEntityHandlerRequest(&ehRequest,
-                                        (OCRequestHandle)request->requestId,
-                                        request->method,
-                                        &request->devAddr,
-                                        (OCResourceHandle)resource,
-                                        request->query,
-                                        type,
-                                        request->payload,
-                                        request->payloadSize,
-                                        request->numRcvdVendorSpecificHeaderOptions,
-                                        request->rcvdVendorSpecificHeaderOptions,
-                                        (OCObserveAction)request->observationOption,
-                                        0,
-                                        request->coapID);
+    result = EHRequest(&ehRequest, type, request, resource);
     VERIFY_SUCCESS(result);
 
     if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
@@ -1294,32 +1276,16 @@ exit:
     return result;
 }
 
-static OCStackResult
-HandleCollectionResourceDefaultEntityHandler (OCServerRequest *request,
-                                              OCResource *resource)
+static OCStackResult HandleCollectionResourceDefaultEntityHandler(OCServerRequest *request,
+                                                                  OCResource *resource)
 {
-    if(!request || !resource)
+    if (!request || !resource)
     {
         return OC_STACK_INVALID_PARAM;
     }
 
-    OCStackResult result = OC_STACK_ERROR;
     OCEntityHandlerRequest ehRequest = {0};
-
-    result = FormOCEntityHandlerRequest(&ehRequest,
-                                        (OCRequestHandle)request->requestId,
-                                        request->method,
-                                        &request->devAddr,
-                                        (OCResourceHandle)resource,
-                                        request->query,
-                                        PAYLOAD_TYPE_REPRESENTATION,
-                                        request->payload,
-                                        request->payloadSize,
-                                        request->numRcvdVendorSpecificHeaderOptions,
-                                        request->rcvdVendorSpecificHeaderOptions,
-                                        (OCObserveAction)request->observationOption,
-                                        (OCObservationId)0,
-                                        request->coapID);
+    OCStackResult result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, resource);
     if(result == OC_STACK_OK)
     {
         result = DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest);
@@ -1353,12 +1319,12 @@ ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerReque
         }
         case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
         {
-            ret = HandleResourceWithEntityHandler (request, resource, 0);
+            ret = HandleResourceWithEntityHandler (request, resource);
             break;
         }
         case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
         {
-            ret = HandleResourceWithEntityHandler (request, resource, 1);
+            ret = HandleResourceWithEntityHandler (request, resource);
             break;
         }
         case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
index a3e96c4..39290d3 100644 (file)
@@ -773,7 +773,7 @@ OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse)
             goto exit;
         }
 
-        OCRepPayload *newPayload = OCRepPayloadClone((OCRepPayload *)ehResponse->payload);
+        OCRepPayload *newPayload = OCRepPayloadBatchClone((OCRepPayload *)ehResponse->payload);
 
         if(!serverResponse->payload)
         {
@@ -791,6 +791,7 @@ OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse)
         {
             OIC_LOG(INFO, TAG, "This is the last response fragment");
             ehResponse->payload = serverResponse->payload;
+            ehResponse->ehResult = OC_EH_OK;
             stackRet = HandleSingleResponse(ehResponse);
             //Delete the request and response
             FindAndDeleteServerRequest(serverRequest);
@@ -803,5 +804,6 @@ OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse)
         }
     }
 exit:
+
     return stackRet;
 }