// 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 "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)
+static bool AddRTSBaslinePayload(OCRepPayload **linkArray, int size, OCRepPayload **colPayload)
{
- if (!resource || !rtPtr)
- {
- return OC_STACK_INVALID_PARAM;
- }
-
- OCResourceType* rTPointer = resource->rsrcType;
- while (rTPointer)
+ size_t arraySize = 0;
+ for (int j = 0; j < size; j++)
{
- if (strcmp(rTPointer->resourcetypename, rtPtr) == 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]);
}
-
- rTPointer = rTPointer->next;
}
- return OC_STACK_ERROR;
-}
-static OCStackResult CheckIFParamSupport(const OCResource* resource, const char* ifPtr)
-{
- if (!resource || !ifPtr)
- {
- return OC_STACK_INVALID_PARAM;
- }
+ for (OCStringLL *rsrcType = (*colPayload)->types; rsrcType; rsrcType = rsrcType->next, arraySize++);
- OCResourceInterface* iFPointer = resource->rsrcInterface;
- while (iFPointer)
+ 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)
{
- if (strcmp(iFPointer->name, ifPtr) == 0)
- {
- return OC_STACK_OK;
- }
-
- 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");
-
- if (!query)
- {
- 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)
+ 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++)
{
- 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);
- }
+ rts[k++] = OICStrdup(rt[l]);
+ OICFree(rt[l]);
}
- if (numParam != NUM_PARAM_IN_QUERY)
- {
- // Query parameter should be of the form if=<string>. String should not have & or =
- return OC_STACK_INVALID_QUERY;
- }
- 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);
{
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 *)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:
- 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 *)ehRequest->requestHandle)->ehResponseHandler =
- HandleAggregateResponse;
- ((OCServerRequest *)ehRequest->requestHandle)->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((OCServerRequest *)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;
}
* 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;
*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;
return false;
}
-OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr,
- OCRepPayload** payload, OCDevAddr *devAddr)
+static OCStackResult BuildDevicePlatformPayload(const OCResource *resourcePtr, OCRepPayload** payload, bool addDeviceId)
{
- OCRepPayload *tempPayload = OCRepPayloadCreate();
-
if (!resourcePtr)
{
- OCRepPayloadDestroy(tempPayload);
return OC_STACK_INVALID_PARAM;
}
- if(!tempPayload)
+ OCRepPayload *tempPayload = OCRepPayloadCreate();
+ if (!tempPayload)
{
return OC_STACK_NO_MEMORY;
}
- OCRepPayloadSetUri(tempPayload, resourcePtr->uri);
+ if (addDeviceId)
+ {
+ const char *deviceId = OCGetServerInstanceIDString();
+ if (!deviceId)
+ {
+ OIC_LOG(ERROR, TAG, "Failed retrieving device id.");
+ return OC_STACK_ERROR;
+ }
+ OCRepPayloadSetPropString(tempPayload, OC_RSRVD_DEVICE_ID, deviceId);
+ }
OCResourceType *resType = resourcePtr->rsrcType;
while(resType)
{
if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName))
{
- appendOCStringLL(tempPayload, (OCStringLL *)resAttrib->attrValue);
+ char *dmv = OCCreateString((OCStringLL *)resAttrib->attrValue);
+ if (dmv)
+ {
+ OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, dmv);
+ OICFree(dmv);
+ }
}
else
{
resAttrib = resAttrib->next;
}
+ if(!*payload)
+ {
+ *payload = tempPayload;
+ }
+ else
+ {
+ OCRepPayloadAppend(*payload, tempPayload);
+ }
+
+ return OC_STACK_OK;
+}
+
+OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr,
+ OCRepPayload** payload, OCDevAddr *devAddr)
+{
+ OCRepPayload *tempPayload = OCRepPayloadCreate();
+
+ if (!resourcePtr)
+ {
+ OCRepPayloadDestroy(tempPayload);
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ if(!tempPayload)
+ {
+ return OC_STACK_NO_MEMORY;
+ }
+
+ OCRepPayloadSetPropString(tempPayload, OC_RSRVD_HREF, resourcePtr->uri);
+
+ uint8_t numElement = 0;
+ if (OC_STACK_OK == OCGetNumberOfResourceTypes((OCResource *)resourcePtr, &numElement))
+ {
+ 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);
+ }
+
+ numElement = 0;
+ if (OC_STACK_OK == OCGetNumberOfResourceInterfaces((OCResource *)resourcePtr, &numElement))
+ {
+ 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);
+ }
+
+ for (OCAttribute *resAttrib = resourcePtr->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
+ {
+ if (resAttrib->attrName && resAttrib->attrValue)
+ {
+ if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName))
+ {
+ appendOCStringLL(tempPayload, (OCStringLL *)resAttrib->attrValue);
+ }
+ else
+ {
+ OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, (char *)resAttrib->attrValue);
+ }
+ }
+ }
+
OCResourceProperty p = OCGetResourceProperties((OCResourceHandle *)resourcePtr);
OCRepPayload *policy = OCRepPayloadCreate();
if (!policy)
}
OCRepPayloadSetPropObjectAsOwner(tempPayload, OC_RSRVD_POLICY, policy);
- if(!*payload)
+ if (!*payload)
{
*payload = tempPayload;
}
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)
return OC_STACK_NO_RESOURCE;
}
- if (IsCollectionResource (resourcePtr))
+ if (resourcePtr && resourcePtr->rsrcChildResourcesHead != NULL)
{
// Collection resource
if (resourcePtr->entityHandler != defaultResourceEHandler)
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);
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);
*/
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);
return resourceMatchesIFFilter(resource, interfaceFilter) &&
resourceMatchesRTFilter(resource, resourceTypeFilter);
-
}
OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCResource *resource,
return OCDoResponse(&response);
}
+
+static OCStackResult EHRequest(OCEntityHandlerRequest *ehRequest, OCPayloadType type,
+ OCServerRequest *request, OCResource *resource)
+{
+ return FormOCEntityHandlerRequest(ehRequest,
+ (OCRequestHandle)request,
+ 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
}
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,
- 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
}
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;
}
- result = FormOCEntityHandlerRequest(&ehRequest,
- (OCRequestHandle)request,
- 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)
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,
- 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);
}
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: