#include <string.h>
#include "ocstack.h"
#include "ocstackinternal.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
#include "logger.h"
#include "debug.h"
#include "cJSON.h"
/// Module Name
+#include <stdio.h>
+
+#define WITH_GROUPACTION 1
+
+#ifdef WITH_GROUPACTION
+#include "oicgroup.h"
+#endif
+
#define TAG PCF("occollection")
#define NUM_PARAM_IN_QUERY 2
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 (strcmp (innerToken, OC_RSRVD_INTERFACE) == 0)
{
return OC_STACK_INVALID_QUERY;
}
- if (!ifPtr)
- {
- // IF not specified in query, use default IF
- *ifParam = STACK_IF_DEFAULT;
- }
- else
+ 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;
}
}
-
- if (!rtPtr)
+ else
{
- // RT not specified in query. Use the first resource type for the resource as default.
- *rtParam = (char *) OCGetResourceTypeName (resource, 0);
+ // IF not specified in query, use default IF
+ *ifParam = STACK_IF_DEFAULT;
}
- else
+
+ if (rtPtr)
{
if (CheckRTParamSupport((OCResource *)resource, rtPtr) == OC_STACK_OK)
+ {
*rtParam = rtPtr;
+ }
else
+ {
return OC_STACK_INVALID_QUERY;
+ }
+ }
+ else
+ {
+ // RT not specified in query. Use the first resource type for the resource as default.
+ *rtParam = (char *) OCGetResourceTypeName (resource, 0);
}
OC_LOG_V(INFO, TAG, "Query params: IF = %d, RT = %s", *ifParam, *rtParam);
return OC_STACK_OK;
}
-static OCStackResult BuildRootResourceJSON(OCResource *resource, OCEntityHandlerRequest *ehRequest)
+
+
+static OCStackResult BuildRootResourceJSON(OCResource *resource,
+ unsigned char * bufferPtr, uint16_t *remaining)
{
OCStackResult ret = OC_STACK_ERROR;
cJSON *resObj;
OC_LOG(INFO, TAG, PCF("Entering BuildRootResourceJSON"));
resObj = cJSON_CreateObject();
+
if (resource)
{
cJSON_AddItemToObject (resObj, OC_RSRVD_HREF, cJSON_CreateString(resource->uri));
}
jsonStr = cJSON_PrintUnformatted (resObj);
jsonLen = strlen(jsonStr);
- if (jsonLen < ehRequest->resJSONPayloadLen)
+ if (jsonLen < *remaining)
{
- strcpy((char*)ehRequest->resJSONPayload, jsonStr);
- ehRequest->resJSONPayloadLen -= jsonLen;
- ehRequest->resJSONPayload += jsonLen;
- ret = OC_STACK_OK;
- }
-
- if (ehRequest->resJSONPayloadLen >= (sizeof(OC_JSON_SEPARATOR) + 1))
- {
- *ehRequest->resJSONPayload = OC_JSON_SEPARATOR;
- ehRequest->resJSONPayload++;
- ehRequest->resJSONPayloadLen--;
+ strcpy((char*) bufferPtr, jsonStr);
+ *remaining -= jsonLen;
+ bufferPtr += jsonLen;
ret = OC_STACK_OK;
}
static OCStackResult
-BuildCollectionJSONResponse(OCResource *resource, OCEntityHandlerRequest *ehRequest,
+HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest,
uint8_t filterOn, char *filterValue)
{
OCStackResult ret = OC_STACK_ERROR;
- ret = BuildRootResourceJSON(resource, ehRequest);
+ unsigned char jsonbuffer[MAX_RESPONSE_LENGTH] = {0};
+ size_t jsonbufferLength = 0;
+ uint16_t remaining = 0;
+ unsigned char * ptr = NULL;
+ OCResource * collResource = (OCResource *) ehRequest->resource;
+
+ ptr = jsonbuffer;
+ remaining = MAX_RESPONSE_LENGTH;
+
+ ret = BuildRootResourceJSON(collResource, ptr, &remaining);
+ ptr += strlen((char*)ptr);
+
+ if (ret == OC_STACK_OK && remaining >= (sizeof(OC_JSON_SEPARATOR) + 1))
+ {
+ *ptr = OC_JSON_SEPARATOR;
+ ptr++;
+ remaining--;
+ }
+ else
+ {
+ ret = OC_STACK_ERROR;
+ }
+ *(ptr + 1) = '\0';
- unsigned char* buffer = ehRequest->resJSONPayload;
- uint16_t remaining = ehRequest->resJSONPayloadLen;
if (ret == OC_STACK_OK)
{
for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
{
- OCResource* temp = resource->rsrcResources[i];
+ OCResource* temp = collResource->rsrcResources[i];
if (temp)
{
- ret = BuildVirtualResourceResponse(temp, filterOn, filterValue, (char*)buffer, &remaining);
+ ret = BuildVirtualResourceResponse(temp, filterOn, filterValue, (char*)ptr, &remaining);
if (ret != OC_STACK_OK)
{
break;
}
-
- buffer += strlen((char*)buffer);
- if (resource->rsrcResources[i+1] && remaining > sizeof(OC_JSON_SEPARATOR))
+ ptr += strlen((char*)ptr);
+ if (collResource->rsrcResources[i+1] && remaining > sizeof(OC_JSON_SEPARATOR))
{
- *buffer = OC_JSON_SEPARATOR;
- buffer++;
+ *ptr = OC_JSON_SEPARATOR;
+ ptr++;
remaining--;
}
+ *(ptr + 1) = '\0';
}
else
{
break;
}
}
- ehRequest->resJSONPayload = buffer;
- ehRequest->resJSONPayloadLen = remaining;
}
+ jsonbufferLength = strlen((const char *)jsonbuffer);
+ if(ret == OC_STACK_OK && jsonbufferLength)
+ {
+ OCEntityHandlerResponse response = {0};
+ response.ehResult = OC_EH_OK;
+ response.payload = jsonbuffer;
+ response.payloadSize = jsonbufferLength + 1;
+ response.persistentBufferFlag = 0;
+ response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
+ response.resourceHandle = (OCResourceHandle) collResource;
+ ret = OCDoResponse(&response);
+ }
return ret;
}
-
static OCStackResult
-BuildCollectionBatchJSONResponse(OCEntityHandlerFlag flag,
- OCResource *resource, OCEntityHandlerRequest *ehRequest)
+HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
{
OCStackResult stackRet = OC_STACK_ERROR;
- OCEntityHandlerResult ehRet = OC_EH_ERROR;
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
+ unsigned char jsonbuffer[MAX_RESPONSE_LENGTH] = {0};
+ size_t jsonbufferLength = 0;
+ uint16_t remaining = 0;
+ unsigned char * ptr = NULL;
+ OCResource * collResource = (OCResource *) ehRequest->resource;
+
+ ptr = jsonbuffer;
+ remaining = MAX_RESPONSE_LENGTH;
+
+ stackRet = BuildRootResourceJSON(collResource, ptr, &remaining);
+ ptr += strlen((char*)ptr);
+ *(ptr + 1) = '\0';
+
+ jsonbufferLength = strlen((const char *)jsonbuffer);
+ if(jsonbufferLength)
+ {
+ OCEntityHandlerResponse response = {0};
+ response.ehResult = OC_EH_OK;
+ response.payload = jsonbuffer;
+ response.payloadSize = jsonbufferLength + 1;
+ response.persistentBufferFlag = 0;
+ response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
+ response.resourceHandle = (OCResourceHandle) collResource;
+ stackRet = OCDoResponse(&response);
+ }
- stackRet = BuildRootResourceJSON(resource, ehRequest);
if (stackRet == OC_STACK_OK)
{
- OCResourceHandle origResourceHandle = ehRequest->resource;
-
for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
{
- OCResource* temp = resource->rsrcResources[i];
+ OCResource* temp = collResource->rsrcResources[i];
if (temp)
{
+ // 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;
- ehRet = temp->entityHandler(OC_REQUEST_FLAG, ehRequest);
- stackRet = EntityHandlerCodeToOCStackCode(ehRet);
+ ehResult = temp->entityHandler(OC_REQUEST_FLAG, ehRequest);
- if(ehRet == OC_EH_OK)
+ // The default collection handler is returning as OK
+ if(stackRet != OC_STACK_SLOW_RESOURCE)
{
- unsigned char* buffer = ehRequest->resJSONPayload;
- ehRequest->resJSONPayloadLen =
- ehRequest->resJSONPayloadLen - strlen((char*)buffer);
-
- buffer += strlen((char*)buffer);
- ehRequest->resJSONPayload = buffer;
- if ( resource->rsrcResources[i+1] &&
- ehRequest->resJSONPayloadLen > sizeof(OC_JSON_SEPARATOR) )
- {
- * buffer = OC_JSON_SEPARATOR;
- buffer++;
- ehRequest->resJSONPayload = buffer;
- ehRequest->resJSONPayloadLen = ehRequest->resJSONPayloadLen - 1;
- }
+ stackRet = OC_STACK_OK;
}
- else
+ // if a single resource is slow, then entire response will be treated
+ // as slow response
+ if(ehResult == OC_EH_SLOW)
{
- break;
+ OC_LOG(INFO, TAG, PCF("This is a slow resource"));
+ ((OCServerRequest *)ehRequest->requestHandle)->slowFlag = 1;
+ stackRet = EntityHandlerCodeToOCStackCode(ehResult);
}
}
else
{
- break;
+ break;
}
}
-
- ehRequest->resource = origResourceHandle;
+ ehRequest->resource = (OCResourceHandle) collResource;
}
return stackRet;
}
+uint8_t GetNumOfResourcesInCollection (OCResource *resource)
+{
+ uint8_t num = 0;
+ for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
+ {
+ if (resource->rsrcResources[i])
+ {
+ num++;
+ }
+ }
+ return num;
+}
+
OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
OCEntityHandlerRequest *ehRequest)
{
- OCStackResult result;
- OCStackIfTypes ifQueryParam;
- char *rtQueryParam;
+ OCStackResult result = OC_STACK_ERROR;
+ OCStackIfTypes ifQueryParam = STACK_IF_INVALID;
+ char *rtQueryParam = NULL;
- OC_LOG(INFO, TAG, PCF("DefaultCollectionEntityHandler"));
+ OC_LOG_V(INFO, TAG, "DefaultCollectionEntityHandler with query %s", ehRequest->query);
if (flag != OC_REQUEST_FLAG)
return OC_STACK_ERROR;
if (result != OC_STACK_OK)
return result;
- if ((ehRequest->method != OC_REST_GET) &&
- (ehRequest->method != OC_REST_PUT))
+
+ if(!((ehRequest->method == OC_REST_GET) ||
+ (ehRequest->method == OC_REST_PUT) ||
+ (ehRequest->method == OC_REST_POST)))
return OC_STACK_ERROR;
if (ehRequest->method == OC_REST_GET)
// Get attributes of collection resource and properties of contined resource
// 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, PCF("STACK_IF_DEFAULT"));
- return BuildCollectionJSONResponse( (OCResource *)ehRequest->resource,
- ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
+ return HandleLinkedListInterface(ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
case STACK_IF_LL:
OC_LOG(INFO, TAG, PCF("STACK_IF_LL"));
- return BuildCollectionJSONResponse( (OCResource *)ehRequest->resource,
- ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
+ return HandleLinkedListInterface(ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
case STACK_IF_BATCH:
OC_LOG(INFO, TAG, PCF("STACK_IF_BATCH"));
- return BuildCollectionBatchJSONResponse(flag, (OCResource *)ehRequest->resource, ehRequest);
-
+ ((OCServerRequest *)ehRequest->requestHandle)->ehResponseHandler = HandleAggregateResponse;
+ ((OCServerRequest *)ehRequest->requestHandle)->numResponses =
+ GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
+ return HandleBatchInterface(ehRequest);
+#ifdef WITH_GROUPACTION
+ case STACK_IF_GROUP:
+ return BuildCollectionGroupActionJSONResponse(OC_REST_GET/*flag*/, (OCResource *)ehRequest->resource,
+ ehRequest);
+#endif // WITH_GROUPACTION
default:
return OC_STACK_ERROR;
}
return OC_STACK_ERROR;
case STACK_IF_BATCH:
- return BuildCollectionBatchJSONResponse(flag, (OCResource *)ehRequest->resource, ehRequest);
+ ((OCServerRequest *)ehRequest->requestHandle)->ehResponseHandler = HandleAggregateResponse;
+ ((OCServerRequest *)ehRequest->requestHandle)->numResponses =
+ GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
+ return HandleBatchInterface(ehRequest);
+
+#ifdef WITH_GROUPACTION
+ case STACK_IF_GROUP:
+ {
+ OC_LOG_V(INFO, TAG, "IF_COLLECTION PUT with request ::\n%s\n ", ehRequest->reqJSONPayload);
+ printf("PUT ::\n%s\n", ehRequest->reqJSONPayload);
+ return BuildCollectionGroupActionJSONResponse(OC_REST_PUT/*flag*/, (OCResource *)ehRequest->resource, ehRequest);
+ }
+#endif // WITH_GROUPACTION
+ default:
+ return OC_STACK_ERROR;
+ }
+ }
+#ifdef WITH_GROUPACTION
+ else if(ehRequest->method == OC_REST_POST) {
+
+ switch(ifQueryParam)
+ {
+ case STACK_IF_GROUP:
+ {
+ OC_LOG_V(INFO, TAG, "IF_COLLECTION POST with request :: \n%s\n ", ehRequest->reqJSONPayload);
+ printf("POST ::\n%s\n", ehRequest->reqJSONPayload);
+ return BuildCollectionGroupActionJSONResponse(OC_REST_POST/*flag*/, (OCResource *)ehRequest->resource, ehRequest);
+ }
default:
return OC_STACK_ERROR;
}
}
+#endif // WITH_GROUPACTION
return result;
}