1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 // Defining _POSIX_C_SOURCE macro with 200112L (or greater) as value
22 // causes header files to expose definitions
23 // corresponding to the POSIX.1-2001 base
24 // specification (excluding the XSI extension).
25 // For POSIX.1-2001 base specification,
26 // Refer http://pubs.opengroup.org/onlinepubs/009695399/
27 #define _POSIX_C_SOURCE 200112L
29 #include "occollection.h"
30 #include "ocpayload.h"
33 #include "oic_string.h"
34 #include "payload_logging.h"
36 #define TAG "OIC_RI_COLLECTION"
38 static bool AddRTSBaslinePayload(OCRepPayload **linkArray, int size, OCRepPayload **colPayload)
41 for (int j = 0; j < size; j++)
43 size_t rtDim[MAX_REP_ARRAY_DEPTH] = {0};
45 OCRepPayloadGetStringArray(linkArray[j], OC_RSRVD_RESOURCE_TYPE, &rt, rtDim);
46 arraySize += rtDim[0];
47 for (size_t l = 0; l < rtDim[0]; l++)
53 for (OCStringLL *rsrcType = (*colPayload)->types; rsrcType; rsrcType = rsrcType->next, arraySize++);
55 OIC_LOG_V(DEBUG, TAG, "Number of RTS elements : %zd", arraySize);
56 size_t dim[MAX_REP_ARRAY_DEPTH] = {arraySize, 0, 0};
57 char **rts = (char **)OICMalloc(sizeof(char *) * arraySize);
60 OIC_LOG(ERROR, TAG, "Memory allocation failed!");
61 return OC_STACK_NO_MEMORY;
64 for (int j = 0; j < size; j++)
66 size_t rtDim[MAX_REP_ARRAY_DEPTH] = {0};
68 OCRepPayloadGetStringArray(linkArray[j], OC_RSRVD_RESOURCE_TYPE, &rt, rtDim);
69 for (size_t l = 0; l < rtDim[0]; l++)
71 rts[k++] = OICStrdup(rt[l]);
75 for (OCStringLL *rsrcType = (*colPayload)->types; rsrcType; rsrcType = rsrcType->next, size++)
77 rts[k++] = OICStrdup(rsrcType->value);
80 return OCRepPayloadSetStringArrayAsOwner(*colPayload, OC_RSRVD_RTS, rts, dim);
83 static OCStackResult SendResponse(const OCRepPayload *payload, const OCEntityHandlerRequest *ehRequest,
84 const OCResource* collResource, OCEntityHandlerResult ehResult)
86 OCEntityHandlerResponse response = {0};
87 response.ehResult = ehResult;
88 response.payload = (OCPayload*)payload;
89 response.persistentBufferFlag = 0;
90 response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
91 response.resourceHandle = (OCResourceHandle) collResource;
92 return OCDoResponse(&response);
95 uint8_t GetNumOfResourcesInCollection(const OCResource *collResource)
98 for (OCChildResource *tempChildResource = collResource->rsrcChildResourcesHead;
99 tempChildResource; tempChildResource = tempChildResource->next)
106 static OCStackResult HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest, char *ifQueryParam)
110 return OC_STACK_INVALID_PARAM;
113 OCResource *collResource = (OCResource *)ehRequest->resource;
116 return OC_STACK_INVALID_PARAM;
119 uint8_t size = GetNumOfResourcesInCollection(collResource);
120 OCRepPayload *colPayload = NULL;
121 OCEntityHandlerResult ehResult = OC_EH_ERROR;
123 OCStackResult ret = OC_STACK_OK;
124 size_t dim[MAX_REP_ARRAY_DEPTH] = {size, 0, 0};
125 OCRepPayload **linkArr = (OCRepPayload **)OICCalloc(size, sizeof(OCRepPayload *));
126 VERIFY_PARAM_NON_NULL(TAG, linkArr, "Failed creating LinkArray");
128 for (OCChildResource *tempChildResource = collResource->rsrcChildResourcesHead;
129 tempChildResource && ret == OC_STACK_OK; tempChildResource = tempChildResource->next)
131 OCResource* temp = tempChildResource->rsrcResource;
134 ret = BuildResponseRepresentation(temp, &linkArr[i++], &ehRequest->devAddr);
138 if (ret == OC_STACK_OK)
140 colPayload = OCRepPayloadCreate();
143 if (0 == strcmp(OC_RSRVD_INTERFACE_DEFAULT, ifQueryParam))
145 //TODO : Add resource type filtering once collections
146 // start supporting queries.
147 OCRepPayloadAddResourceType(colPayload, OC_RSRVD_RESOURCE_TYPE_COLLECTION);
148 for (OCResourceType *types = collResource->rsrcType; types; types = types->next)
150 if (0 != strcmp(OC_RSRVD_RESOURCE_TYPE_COLLECTION, types->resourcetypename))
152 OCRepPayloadAddResourceType(colPayload, types->resourcetypename);
155 for (OCResourceInterface *itf = collResource->rsrcInterface; itf; itf = itf->next)
157 OCRepPayloadAddInterface(colPayload, itf->name);
159 AddRTSBaslinePayload(linkArr, i, &colPayload);
161 OCRepPayloadSetPropObjectArrayAsOwner(colPayload, OC_RSRVD_LINKS, linkArr, dim);
166 if (ret == OC_STACK_OK)
172 ehResult = (ret == OC_STACK_NO_RESOURCE) ? OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR;
174 ret = SendResponse(colPayload, ehRequest, collResource, ehResult);
175 OIC_LOG_PAYLOAD(DEBUG, (OCPayload *)colPayload);
180 static OCStackResult HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
184 return OC_STACK_INVALID_PARAM;
187 OCStackResult stackRet = OC_STACK_OK;
188 char *storeQuery = NULL;
189 OCRepPayload *payload = OCRepPayloadCreate();
190 OCResource *collResource = (OCResource *)ehRequest->resource;
191 VERIFY_PARAM_NON_NULL(TAG, payload, "Failed creating RepPayload");
193 if (stackRet == OC_STACK_OK)
196 if (collResource->rsrcChildResourcesHead)
198 storeQuery = OICStrdup(ehRequest->query);
199 ehRequest->query = NULL;
200 OIC_LOG_V(DEBUG, TAG, "Query : %s", ehRequest->query);
204 for (OCChildResource *tempChildResource = collResource->rsrcChildResourcesHead;
205 tempChildResource; tempChildResource = tempChildResource->next, numRes++)
207 OCResource* tempRsrcResource = tempChildResource->rsrcResource;
208 if (tempRsrcResource)
210 // Note that all entity handlers called through a collection
211 // will get the same pointer to ehRequest, the only difference
212 // is ehRequest->resource
213 ehRequest->resource = (OCResourceHandle) tempRsrcResource;
214 OCEntityHandlerResult ehResult = tempRsrcResource->entityHandler(OC_REQUEST_FLAG,
215 ehRequest, tempRsrcResource->entityHandlerCallbackParam);
217 // The default collection handler is returning as OK
218 if (stackRet != OC_STACK_SLOW_RESOURCE)
220 stackRet = OC_STACK_OK;
222 // if a single resource is slow, then entire response will be treated
224 if (ehResult == OC_EH_SLOW)
226 OIC_LOG(INFO, TAG, "This is a slow resource");
227 OCServerRequest *request =
228 GetServerRequestUsingHandle(ehRequest->requestHandle);
231 request->slowFlag = 1;
233 stackRet = EntityHandlerCodeToOCStackCode(ehResult);
241 ehRequest->resource = (OCResourceHandle) collResource;
243 ehRequest->query = OICStrdup(storeQuery);
248 return OC_STACK_NO_MEMORY;
251 OCStackResult DefaultCollectionEntityHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest *ehRequest)
253 if (!ehRequest || !ehRequest->query)
255 return OC_STACK_INVALID_PARAM;
257 // Delete is not supported for any interface query method.
258 if (ehRequest->method == OC_REST_DELETE || flag != OC_REQUEST_FLAG)
260 return OC_STACK_ERROR;
262 OIC_LOG_V(INFO, TAG, "DefaultCollectionEntityHandler with query %s", ehRequest->query);
264 char *ifQueryParam = NULL;
265 char *rtQueryParam = NULL;
266 OCStackResult result = ExtractFiltersFromQuery(ehRequest->query, &ifQueryParam, &rtQueryParam);
267 if (result != OC_STACK_OK)
269 result = OC_STACK_NO_RESOURCE;
274 ifQueryParam = OICStrdup(OC_RSRVD_INTERFACE_LL);
276 if (0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_LL) || 0 == strcmp (ifQueryParam, OC_RSRVD_INTERFACE_DEFAULT))
278 if (ehRequest->method == OC_REST_PUT || ehRequest->method == OC_REST_POST)
280 result = OC_STACK_ERROR;
284 result = HandleLinkedListInterface(ehRequest, ifQueryParam);
287 else if (0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_BATCH))
289 OCServerRequest *request = GetServerRequestUsingHandle(ehRequest->requestHandle);
292 request->numResponses = GetNumOfResourcesInCollection((OCResource *)ehRequest->resource);
293 request->ehResponseHandler = HandleAggregateResponse;
294 result = HandleBatchInterface(ehRequest);
297 else if (0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_GROUP))
299 OIC_LOG_V(INFO, TAG, "IF_COLLECTION %d with request ::\n", ehRequest->method);
300 OIC_LOG_PAYLOAD(INFO, ehRequest->payload);
301 result = BuildCollectionGroupActionCBORResponse(ehRequest->method, (OCResource *) ehRequest->resource, ehRequest);
304 if (result != OC_STACK_OK)
306 result = SendResponse(NULL, ehRequest, (OCResource *)ehRequest->resource, OC_EH_BAD_REQ);
308 OICFree(ifQueryParam);
309 OICFree(rtQueryParam);