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"
31 #include "ocendpoint.h"
33 #include "ocstackinternal.h"
35 #include "oic_string.h"
36 #include "payload_logging.h"
37 #include "cainterface.h"
38 #define TAG "OIC_RI_COLLECTION"
40 static bool AddRTSBaselinePayload(OCRepPayload **linkArray, int size, OCRepPayload **colPayload)
43 for (int j = 0; j < size; j++)
45 size_t rtDim[MAX_REP_ARRAY_DEPTH] = {0};
47 OCRepPayloadGetStringArray(linkArray[j], OC_RSRVD_RESOURCE_TYPE, &rt, rtDim);
48 arraySize += rtDim[0];
49 for (size_t l = 0; l < rtDim[0]; l++)
56 for (OCStringLL *rsrcType = (*colPayload)->types; rsrcType; rsrcType = rsrcType->next, arraySize++);
58 OIC_LOG_V(DEBUG, TAG, "Number of RTS elements : %zd", arraySize);
59 size_t dim[MAX_REP_ARRAY_DEPTH] = {arraySize, 0, 0};
60 char **rts = (char **)OICMalloc(sizeof(char *) * arraySize);
63 OIC_LOG(ERROR, TAG, "Memory allocation failed!");
64 return OC_STACK_NO_MEMORY;
67 for (int j = 0; j < size; j++)
69 size_t rtDim[MAX_REP_ARRAY_DEPTH] = {0};
71 OCRepPayloadGetStringArray(linkArray[j], OC_RSRVD_RESOURCE_TYPE, &rt, rtDim);
72 for (size_t l = 0; l < rtDim[0]; l++)
74 rts[k++] = OICStrdup(rt[l]);
79 for (OCStringLL *rsrcType = (*colPayload)->types; rsrcType; rsrcType = rsrcType->next, size++)
81 rts[k++] = OICStrdup(rsrcType->value);
84 bool b = OCRepPayloadSetStringArrayAsOwner(*colPayload, OC_RSRVD_RTS, rts, dim);
88 for (size_t j = 0; j < arraySize; j++)
98 static OCStackResult SendResponse(const OCRepPayload *payload, const OCEntityHandlerRequest *ehRequest,
99 const OCResource* collResource, OCEntityHandlerResult ehResult)
101 OCEntityHandlerResponse response = {0};
102 response.ehResult = ehResult;
103 response.payload = (OCPayload*)payload;
104 response.persistentBufferFlag = 0;
105 response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
106 response.resourceHandle = (OCResourceHandle) collResource;
107 return OCDoResponse(&response);
110 uint8_t GetNumOfResourcesInCollection(const OCResource *collResource)
113 for (OCChildResource *tempChildResource = collResource->rsrcChildResourcesHead;
114 tempChildResource; tempChildResource = tempChildResource->next)
121 static OCStackResult HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest, char *ifQueryParam)
125 return OC_STACK_INVALID_PARAM;
128 OCResource *collResource = (OCResource *)ehRequest->resource;
131 return OC_STACK_INVALID_PARAM;
134 uint8_t size = GetNumOfResourcesInCollection(collResource);
135 OCRepPayload *colPayload = NULL;
136 OCEntityHandlerResult ehResult = OC_EH_ERROR;
137 OCStackResult ret = OC_STACK_OK;
138 size_t dim[MAX_REP_ARRAY_DEPTH] = {size, 0, 0};
139 OCRepPayload **linkArr = NULL;
141 if (!(linkArr = OCLinksPayloadArrayCreate(collResource->uri, ehRequest, NULL)))
143 OIC_LOG_V(ERROR, TAG, "Failed getting LinksPayloadArray");
144 ret = OC_STACK_ERROR;
150 ret = OC_STACK_NO_RESOURCE;
154 bool isOCFContentFormat = true;
155 OCRequestIsOCFContentFormat(ehRequest, &isOCFContentFormat);
156 // from the OCF1.0 linklist specification, ll has array of links
157 if ((0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_LL) && isOCFContentFormat))
159 for (int n = 0; n < (int)size - 1; n++)
161 linkArr[n]->next = linkArr[n + 1];
163 colPayload = linkArr[0];
169 colPayload = OCRepPayloadCreate();
170 VERIFY_PARAM_NON_NULL(TAG, linkArr, "Failed creating LinksPayloadArray");
171 if (0 == strcmp(OC_RSRVD_INTERFACE_DEFAULT, ifQueryParam))
173 //TODO : Add resource type filtering once collections
174 // start supporting queries.
175 OCRepPayloadAddResourceType(colPayload, OC_RSRVD_RESOURCE_TYPE_COLLECTION);
176 for (OCResourceType *types = collResource->rsrcType; types; types = types->next)
178 if (0 != strcmp(OC_RSRVD_RESOURCE_TYPE_COLLECTION, types->resourcetypename))
180 OCRepPayloadAddResourceType(colPayload, types->resourcetypename);
183 for (OCResourceInterface *itf = collResource->rsrcInterface; itf; itf = itf->next)
185 OCRepPayloadAddInterface(colPayload, itf->name);
187 AddRTSBaselinePayload(linkArr, size, &colPayload);
189 OCRepPayloadSetPropObjectArrayAsOwner(colPayload, OC_RSRVD_LINKS, linkArr, dim);
192 if (ret == OC_STACK_OK)
198 ehResult = (ret == OC_STACK_NO_RESOURCE) ? OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR;
200 ret = SendResponse(colPayload, ehRequest, collResource, ehResult);
201 OIC_LOG_V(INFO, TAG, "Send Response result from HandleLinkedListInterface = %d", (int)ret);
202 OIC_LOG_PAYLOAD(DEBUG, (OCPayload *)colPayload);
203 OCRepPayloadDestroy(colPayload);
208 static OCStackResult HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
212 return OC_STACK_INVALID_PARAM;
215 OCStackResult stackRet = OC_STACK_OK;
216 char *storeQuery = NULL;
217 OCResource *collResource = (OCResource *)ehRequest->resource;
219 if (stackRet == OC_STACK_OK)
222 if (collResource->rsrcChildResourcesHead)
224 storeQuery = ehRequest->query;
225 ehRequest->query = NULL;
226 OIC_LOG_V(DEBUG, TAG, "Query : %s", ehRequest->query);
230 for (OCChildResource *tempChildResource = collResource->rsrcChildResourcesHead;
231 tempChildResource; tempChildResource = tempChildResource->next, numRes++)
233 OCResource* tempRsrcResource = tempChildResource->rsrcResource;
234 if (tempRsrcResource)
236 // Note that all entity handlers called through a collection
237 // will get the same pointer to ehRequest, the only difference
238 // is ehRequest->resource
239 ehRequest->resource = (OCResourceHandle) tempRsrcResource;
240 OCEntityHandlerResult ehResult = tempRsrcResource->entityHandler(OC_REQUEST_FLAG,
241 ehRequest, tempRsrcResource->entityHandlerCallbackParam);
243 // The default collection handler is returning as OK
244 if (stackRet != OC_STACK_SLOW_RESOURCE)
246 stackRet = OC_STACK_OK;
248 // if a single resource is slow, then entire response will be treated
250 if (ehResult == OC_EH_SLOW)
252 OIC_LOG(INFO, TAG, "This is a slow resource");
253 ((OCServerRequest *)ehRequest->requestHandle)->slowFlag = 1;
254 stackRet = EntityHandlerCodeToOCStackCode(ehResult);
262 ehRequest->resource = (OCResourceHandle) collResource;
264 ehRequest->query = storeQuery;
268 OCStackResult DefaultCollectionEntityHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest *ehRequest)
270 if (!ehRequest || !ehRequest->query)
272 return OC_STACK_INVALID_PARAM;
274 // Delete is not supported for any interface query method.
275 if (ehRequest->method == OC_REST_DELETE || flag != OC_REQUEST_FLAG)
277 return OC_STACK_ERROR;
279 OIC_LOG_V(INFO, TAG, "DefaultCollectionEntityHandler with query %s", ehRequest->query);
281 char *ifQueryParam = NULL;
282 char *rtQueryParam = NULL;
283 OCStackResult result = ExtractFiltersFromQuery(ehRequest->query, &ifQueryParam, &rtQueryParam);
284 if (result != OC_STACK_OK)
286 result = OC_STACK_NO_RESOURCE;
291 ifQueryParam = OICStrdup(OC_RSRVD_INTERFACE_LL);
294 VERIFY_PARAM_NON_NULL(TAG, ifQueryParam, "Invalid Parameter ifQueryParam");
296 if (0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_LL) || 0 == strcmp (ifQueryParam, OC_RSRVD_INTERFACE_DEFAULT))
298 if (ehRequest->method == OC_REST_PUT || ehRequest->method == OC_REST_POST)
300 result = OC_STACK_ERROR;
304 result = HandleLinkedListInterface(ehRequest, ifQueryParam);
307 else if (0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_BATCH))
309 OCServerRequest *request = GetServerRequestUsingHandle((OCServerRequest *)ehRequest->requestHandle);
312 request->numResponses = GetNumOfResourcesInCollection((OCResource *)ehRequest->resource);
313 request->ehResponseHandler = HandleAggregateResponse;
314 result = HandleBatchInterface(ehRequest);
317 else if (0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_GROUP))
319 OIC_LOG_V(INFO, TAG, "IF_COLLECTION %d with request ::\n", ehRequest->method);
320 OIC_LOG_PAYLOAD(INFO, ehRequest->payload);
321 result = BuildCollectionGroupActionCBORResponse(ehRequest->method, (OCResource *) ehRequest->resource, ehRequest);
324 if (result != OC_STACK_OK)
326 result = SendResponse(NULL, ehRequest, (OCResource *)ehRequest->resource, OC_EH_BAD_REQ);
328 OICFree(ifQueryParam);
329 OICFree(rtQueryParam);
333 static bool addPolicyPayload(OCResourceHandle* resourceHandle, OCDevAddr* devAddr,
334 bool isOCFContentFormat, OCRepPayload** outPolicy)
336 if (resourceHandle == NULL || devAddr == NULL || outPolicy == NULL) return false;
338 OCResourceProperty p = OCGetResourceProperties(resourceHandle);
339 OCRepPayload* policy = OCRepPayloadCreate();
342 OCRepPayloadSetPropInt(policy, OC_RSRVD_BITMAP, ((p & OC_DISCOVERABLE) | (p & OC_OBSERVABLE)));
343 if (!isOCFContentFormat)
345 OCRepPayloadSetPropBool(policy, OC_RSRVD_SECURE, p & OC_SECURE);
349 uint16_t securePort = 0;
352 if (devAddr->adapter == OC_ADAPTER_IP)
354 if (devAddr->flags & OC_IP_USE_V6)
356 securePort = caglobals.ip.u6s.port;
358 else if (devAddr->flags & OC_IP_USE_V4)
360 securePort = caglobals.ip.u4s.port;
364 OCRepPayloadSetPropInt(policy, OC_RSRVD_HOSTING_PORT, securePort);
366 #if defined(TCP_ADAPTER) && defined(__WITH_TLS__)
370 uint16_t tlsPort = 0;
371 GetTCPPortInfo(devAddr, &tlsPort, true);
372 OCRepPayloadSetPropInt(policy, OC_RSRVD_TLS_PORT, tlsPort);
378 if (!(p & OC_SECURE))
384 uint16_t tcpPort = 0;
385 GetTCPPortInfo(devAddr, &tcpPort, false);
386 OCRepPayloadSetPropInt(policy, OC_RSRVD_TCP_PORT, tcpPort);
403 static bool translateEndpointsPayload(OCEndpointPayload* epPayloadOrg,
404 size_t size, OCRepPayload*** outArrayPayload)
407 OCRepPayload** arrayPayload = (OCRepPayload**)OICMalloc(sizeof(OCRepPayload*) * (size));
408 VERIFY_PARAM_NON_NULL(TAG, arrayPayload, "Failed creating arrayPayload");
409 VERIFY_PARAM_NON_NULL(TAG, epPayloadOrg, "Invalid Parameter epPayload");
410 VERIFY_PARAM_NON_NULL(TAG, outArrayPayload, "Invalid Parameter outArrayPayload");
411 OCEndpointPayload* epPayload = epPayloadOrg;
413 for (size_t i = 0; (i < size) && (epPayload != NULL) ; i++)
415 arrayPayload[i] = OCRepPayloadCreate();
416 if (!arrayPayload[i])
418 for (size_t j = 0; j < i; j++)
420 OCRepPayloadDestroy(arrayPayload[j]);
425 char* createdEPStr = OCCreateEndpointString(epPayload);
426 OIC_LOG_V(DEBUG, TAG, " OCCreateEndpointString() = %s", createdEPStr);
427 OCRepPayloadSetPropString(arrayPayload[i], OC_RSRVD_ENDPOINT, createdEPStr);
429 // in case of pri as 1, skip set property
430 if (epPayload->pri != 1 )
431 OCRepPayloadSetPropInt(arrayPayload[i], OC_RSRVD_PRIORITY, epPayload->pri);
433 epPayload = epPayload->next;
436 *outArrayPayload = arrayPayload;
438 OCEndpointPayloadDestroy(epPayloadOrg);
439 if (result == false) OICFree(arrayPayload);
443 OCRepPayload** BuildCollectionLinksPayloadArray(const char* resourceUri,
444 bool isOCFContentFormat, OCDevAddr* devAddr, size_t* createdArraySize)
447 OCRepPayload** arrayPayload = NULL;
448 size_t childCount = 0;
450 const OCResourceHandle colResourceHandle = OCGetResourceHandleAtUri(resourceUri);
451 VERIFY_PARAM_NON_NULL(TAG, colResourceHandle, "Failed geting colResourceHandle");
453 const OCChildResource* childResource = ((OCResource*)colResourceHandle)->rsrcChildResourcesHead;
454 VERIFY_PARAM_NON_NULL(TAG, childResource, "Failed geting childResource");
456 //children resources count calculation
457 const OCChildResource* childCountResource = childResource;
460 childCountResource = childCountResource->next;
461 } while (childCountResource);
462 arrayPayload = (OCRepPayload**)OICMalloc(sizeof(OCRepPayload*) * (childCount));
463 VERIFY_PARAM_NON_NULL(TAG, arrayPayload, "Failed creating arrayPayload");
465 OCResource* iterResource = childResource->rsrcResource;
466 for (size_t i = 0; i < childCount; i++)
468 arrayPayload[i] = OCRepPayloadCreate();
469 if (!arrayPayload[i])
471 for (size_t j = 0; j < i; j++)
473 OCRepPayloadDestroy(arrayPayload[j]);
479 OCRepPayloadSetUri(arrayPayload[i], iterResource->uri);
481 for (OCResourceType* resType = iterResource->rsrcType; resType;
482 resType = resType->next)
484 OCRepPayloadAddResourceType(arrayPayload[i], resType->resourcetypename);
487 for (OCResourceInterface* resInterface = iterResource->rsrcInterface; resInterface;
488 resInterface = resInterface->next)
490 OCRepPayloadAddInterface(arrayPayload[i], resInterface->name);
493 OCRepPayload* outPolicy = NULL;
494 //Policy Map will have tls and tcp properties for legacy support,
495 // in case contents format is cbor instead of vnd.ocf/cbor
496 if (!addPolicyPayload((OCResourceHandle*)iterResource, devAddr, isOCFContentFormat,
498 !OCRepPayloadSetPropObjectAsOwner(arrayPayload[i], OC_RSRVD_POLICY, outPolicy))
500 OCRepPayloadDestroy(outPolicy);
501 for (size_t j = 0; j <= i; j++)
503 OCRepPayloadDestroy(arrayPayload[j]);
509 //EP is added in case contents format is vnd.ocf/cbor
510 if (isOCFContentFormat)
512 CAEndpoint_t *info = NULL;
513 size_t networkSize = 0;
515 CAGetNetworkInformation(&info, &networkSize);
516 OIC_LOG_V(DEBUG, TAG, "Network Information size = %d", (int) networkSize);
518 OCEndpointPayload *listHead = NULL;
519 CreateEndpointPayloadList((OCResource*)colResourceHandle,
520 devAddr, info, networkSize, &listHead, &epSize, NULL);
522 OIC_LOG_V(DEBUG, TAG, "Result of CreateEndpointPayloadList() = %s",
523 listHead ? "true":"false");
525 OCRepPayload** epArrayPayload = NULL;
526 size_t epsDim[MAX_REP_ARRAY_DEPTH] = { epSize, 0, 0 };
528 if (!translateEndpointsPayload(listHead, epSize, &epArrayPayload) ||
529 !OCRepPayloadSetPropObjectArrayAsOwner(arrayPayload[i],
530 OC_RSRVD_ENDPOINTS, epArrayPayload, epsDim))
534 for (size_t j = 0; j < epSize; j++)
536 OCRepPayloadDestroy(epArrayPayload[j]);
538 OICFree(epArrayPayload);
541 for (size_t j = 0; j <= i; j++)
543 OCRepPayloadDestroy(arrayPayload[j]);
550 childResource = childResource->next;
553 iterResource = childResource->rsrcResource;
559 if (!result && (arrayPayload != NULL))
561 OICFree(arrayPayload);
565 if (arrayPayload != NULL && createdArraySize != NULL)
566 *createdArraySize = childCount;
567 else if (createdArraySize != NULL)
568 *createdArraySize = 0;