replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / csdk / stack / src / occollection.c
old mode 100644 (file)
new mode 100755 (executable)
index 5684f6a..66b5dce
 // 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 "occollection"
-
-#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
-
-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;
-}
+#define TAG "OIC_RI_COLLECTION"
 
-static OCStackResult CheckIFParamSupport(const OCResource* resource, const char* ifPtr)
+static bool AddRTSBaslinePayload(OCRepPayload **linkArray, int size, OCRepPayload **colPayload)
 {
-    if(!resource || !ifPtr)
+    size_t arraySize = 0;
+    for (int j = 0; j < size; j++)
     {
-        return OC_STACK_INVALID_PARAM;
-    }
-
-    OCResourceInterface* iFPointer = resource->rsrcInterface;
-    while (iFPointer)
-    {
-        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;
+        OICFree(rt);
     }
-    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.
-    OC_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;
+        OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+        return OC_STACK_NO_MEMORY;
     }
-
-    if(!ifParam || !rtParam)
+    int k = 0;
+    for (int j = 0; j < size; j++)
     {
-        return OC_STACK_INVALID_PARAM;
-    }
-
-    if (!(*query))
-    {
-        // Query string is empty
-        OC_LOG(INFO, TAG, "Empty query string, use default IF and RT");
-        *ifParam = STACK_IF_DEFAULT;
-        *rtParam = (char *) OCGetResourceTypeName (resource, 0);
-        return OC_STACK_OK;
-    }
-
-    // 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)
-    {
-        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);
+        OICFree(rt);
     }
-
-    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++;
     }
-    OC_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)
+    if (!ehRequest)
     {
         return OC_STACK_INVALID_PARAM;
     }
 
-    OCStackResult ret = OC_STACK_OK;
     OCResource *collResource = (OCResource *)ehRequest->resource;
+    if (!collResource)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
 
-    OCRepPayload* payload = NULL;
+    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");
 
-    if(ret == OC_STACK_OK)
+    for (OCChildResource *tempChildResource = collResource->rsrcChildResourcesHead;
+        tempChildResource && ret == OC_STACK_OK; tempChildResource = tempChildResource->next)
     {
-        ret = BuildResponseRepresentation(collResource, &payload);
+        OCResource* temp = tempChildResource->rsrcResource;
+        if (temp)
+        {
+            ret = BuildResponseRepresentation(temp, &linkArr[i++], &ehRequest->devAddr);
+        }
     }
 
     if (ret == OC_STACK_OK)
     {
-        for  (int i = 0; i < MAX_CONTAINED_RESOURCES && ret == OC_STACK_OK; i++)
+        colPayload = OCRepPayloadCreate();
+        if (colPayload)
         {
-            OCResource* temp = collResource->rsrcResources[i];
-            if (temp)
+            if (0 == strcmp(OC_RSRVD_INTERFACE_DEFAULT, ifQueryParam))
             {
                 //TODO : Add resource type filtering once collections
                 // start supporting queries.
-                ret = BuildResponseRepresentation(temp, &payload);
+                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);
             }
+            OCRepPayloadSetPropObjectArrayAsOwner(colPayload, OC_RSRVD_LINKS, linkArr, dim);
         }
     }
 
-    if(ret == OC_STACK_OK)
+exit:
+    if (ret == OC_STACK_OK)
+    {
+        ehResult = OC_EH_OK;
+    }
+    else
     {
-        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 = (ret == OC_STACK_NO_RESOURCE) ? OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR;
     }
-    OCRepPayloadDestroy(payload);
+    ret = SendResponse(colPayload, ehRequest, collResource, ehResult);
+    OIC_LOG_PAYLOAD(DEBUG, (OCPayload *)colPayload);
+    OCRepPayloadDestroy(colPayload);
     return ret;
 }
 
-static OCStackResult
-HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
+static OCStackResult HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
 {
     if (!ehRequest)
     {
@@ -283,60 +187,49 @@ HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
     }
 
     OCStackResult stackRet = OC_STACK_OK;
-    OCEntityHandlerResult ehResult = OC_EH_ERROR;
-    OCResource * collResource = (OCResource *) ehRequest->resource;
+    char *storeQuery = NULL;
+    OCResource *collResource = (OCResource *)ehRequest->resource;
 
-    OCRepPayload* payload = OCRepPayloadCreate();
-    if(!payload)
+    if (stackRet == OC_STACK_OK)
     {
-        stackRet = OC_STACK_NO_MEMORY;
-    }
 
-    if(stackRet == OC_STACK_OK)
-    {
-        if (collResource)
+        if (collResource->rsrcChildResourcesHead)
         {
-            OCRepPayloadSetUri(payload, collResource->uri);
+            storeQuery = ehRequest->query;
+            ehRequest->query = NULL;
+            OIC_LOG_V(DEBUG, TAG, "Query : %s", ehRequest->query);
         }
-    }
-
-    if(stackRet == 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;
-        stackRet = OCDoResponse(&response);
-    }
 
-    if (stackRet == OC_STACK_OK)
-    {
-        for  (uint8_t i = 0; i < MAX_CONTAINED_RESOURCES; i++)
+        uint8_t numRes = 0;
+        for (OCChildResource *tempChildResource = collResource->rsrcChildResourcesHead;
+            tempChildResource; tempChildResource = tempChildResource->next, numRes++)
         {
-            OCResource* temp = collResource->rsrcResources[i];
-            if (temp)
+            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) temp;
-
-                ehResult = temp->entityHandler(OC_REQUEST_FLAG, ehRequest,
-                                        temp->entityHandlerCallbackParam);
+                ehRequest->resource = (OCResourceHandle) tempRsrcResource;
+                OCEntityHandlerResult ehResult = tempRsrcResource->entityHandler(OC_REQUEST_FLAG,
+                                           ehRequest, tempRsrcResource->entityHandlerCallbackParam);
 
                 // The default collection handler is returning as OK
-                if(stackRet != OC_STACK_SLOW_RESOURCE)
+                if (stackRet != OC_STACK_SLOW_RESOURCE)
                 {
                     stackRet = OC_STACK_OK;
                 }
                 // if a single resource is slow, then entire response will be treated
                 // as slow response
-                if(ehResult == OC_EH_SLOW)
+                if (ehResult == OC_EH_SLOW)
                 {
-                    OC_LOG(INFO, TAG, "This is a slow resource");
-                    ((OCServerRequest *)ehRequest->requestHandle)->slowFlag = 1;
+                    OIC_LOG(INFO, TAG, "This is a slow resource");
+                    OCServerRequest *request =
+                            GetServerRequestUsingHandle(ehRequest->requestHandle);
+                    if (request)
+                    {
+                        request->slowFlag = 1;
+                    }
                     stackRet = EntityHandlerCodeToOCStackCode(ehResult);
                 }
             }
@@ -347,152 +240,71 @@ HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
         }
         ehRequest->resource = (OCResourceHandle) collResource;
     }
+    ehRequest->query = storeQuery;
     return stackRet;
 }
 
-uint8_t GetNumOfResourcesInCollection (OCResource *resource)
+OCStackResult DefaultCollectionEntityHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest *ehRequest)
 {
-    if(resource)
+    if (!ehRequest || !ehRequest->query)
     {
-        uint8_t num = 0;
-        for (uint8_t i = 0; i < MAX_CONTAINED_RESOURCES; i++)
-        {
-            if (resource->rsrcResources[i])
-            {
-                num++;
-            }
-        }
-        return num;
+        return OC_STACK_INVALID_PARAM;
     }
-    else
+    // Delete is not supported for any interface query method.
+    if (ehRequest->method == OC_REST_DELETE || flag != OC_REQUEST_FLAG)
     {
-        return -1;
+        return OC_STACK_ERROR;
     }
-}
-
+    OIC_LOG_V(INFO, TAG, "DefaultCollectionEntityHandler with query %s", ehRequest->query);
 
-OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
-                                              OCEntityHandlerRequest *ehRequest)
-{
-    if(!ehRequest || !ehRequest->query)
+    char *ifQueryParam = NULL;
+    char *rtQueryParam = NULL;
+    OCStackResult result = ExtractFiltersFromQuery(ehRequest->query, &ifQueryParam, &rtQueryParam);
+    if (result != OC_STACK_OK)
     {
-        return OC_STACK_INVALID_PARAM;
+        result = OC_STACK_NO_RESOURCE;
+        goto exit;
     }
-
-    OCStackResult result = OC_STACK_ERROR;
-    OCStackIfTypes ifQueryParam = STACK_IF_INVALID;
-    char *rtQueryParam = NULL;
-
-    OC_LOG_V(INFO, TAG, "DefaultCollectionEntityHandler with query %s", ehRequest->query);
-
-    if (flag != OC_REQUEST_FLAG)
+    if (!ifQueryParam)
     {
-        return OC_STACK_ERROR;
+        ifQueryParam = OICStrdup(OC_RSRVD_INTERFACE_LL);
     }
 
-    result = ValidateQuery (ehRequest->query,
-                            ehRequest->resource, &ifQueryParam, &rtQueryParam);
+    VERIFY_PARAM_NON_NULL(TAG, ifQueryParam, "Invalid Parameter root");
 
-    if (result != OC_STACK_OK)
+    if (0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_LL) || 0 == strcmp (ifQueryParam, OC_RSRVD_INTERFACE_DEFAULT))
     {
-        return result;
+        if (ehRequest->method == OC_REST_PUT || ehRequest->method == OC_REST_POST)
+        {
+            result =  OC_STACK_ERROR;
+        }
+        else
+        {
+            result = HandleLinkedListInterface(ehRequest, ifQueryParam);
+        }
     }
-
-    switch (ehRequest->method)
+    else if (0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_BATCH))
     {
-        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.
-                    OC_LOG(INFO, TAG, "STACK_IF_DEFAULT");
-                    return HandleLinkedListInterface(ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
-
-                case STACK_IF_LL:
-                    OC_LOG(INFO, TAG, "STACK_IF_LL");
-                    return HandleLinkedListInterface(ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
-
-                case STACK_IF_BATCH:
-                    OC_LOG(INFO, TAG, "STACK_IF_BATCH");
-                    ((OCServerRequest *)ehRequest->requestHandle)->ehResponseHandler =
-                                                                            HandleAggregateResponse;
-
-                    ((OCServerRequest *)ehRequest->requestHandle)->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 *)ehRequest->requestHandle)->ehResponseHandler =
-                                                                            HandleAggregateResponse;
-                    ((OCServerRequest *)ehRequest->requestHandle)->numResponses =
-                            GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
-                    return HandleBatchInterface(ehRequest);
-
-                case STACK_IF_GROUP:
-                    OC_LOG(INFO, TAG, "IF_COLLECTION PUT with request ::\n");
-                    OC_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 *)ehRequest->requestHandle)->ehResponseHandler =
-                                                                            HandleAggregateResponse;
-                    ((OCServerRequest *)ehRequest->requestHandle)->numResponses =
-                            GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
-                    return HandleBatchInterface(ehRequest);
-
-                case STACK_IF_GROUP:
-                    OC_LOG(INFO, TAG, "IF_COLLECTION POST with request ::\n");
-                    OC_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;
+        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;
 }