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
32 #include "iotivity_config.h"
40 #include "ocresource.h"
41 #include "ocresourcehandler.h"
42 #include "ocobserve.h"
43 #include "occollection.h"
44 #include "oic_malloc.h"
45 #include "oic_string.h"
47 #include "ocpayload.h"
48 #include "secureresourcemanager.h"
50 #include "cainterface.h"
51 #include "ocpayload.h"
52 #include "oickeepalive.h"
53 #include "platform_features.h"
54 #include "payload_logging.h"
55 #include "ocendpoint.h"
56 #include "ocstackinternal.h"
58 #ifdef ROUTING_GATEWAY
59 #include "routingmanager.h"
63 #define TAG "OIC_RI_RESOURCE"
65 // using 1k as block size since most persistent storage implementations use a power of 2.
66 #define INTROSPECTION_FILE_SIZE_BLOCK 1024
68 #define VERIFY_SUCCESS(op) { if (op != (OC_STACK_OK)) \
69 {OIC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
71 extern OCResource *headResource;
74 * Prepares a Payload for response.
76 static OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
77 OCDiscoveryPayload *payload,
79 CAEndpoint_t *networkInfo,
82 //-----------------------------------------------------------------------------
83 // Default resource entity handler function
84 //-----------------------------------------------------------------------------
85 OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag,
86 OCEntityHandlerRequest * request, void* callbackParam)
88 //TODO ("Implement me!!!!");
89 // TODO: remove silence unused param warnings
93 return OC_EH_OK; // Making sure that the Default EH and the Vendor EH have matching signatures
96 /* This method will retrieve the port at which the secure resource is hosted */
97 static OCStackResult GetSecurePortInfo(OCDevAddr *endpoint, uint16_t *port)
101 if (endpoint->adapter == OC_ADAPTER_IP)
103 if (endpoint->flags & OC_IP_USE_V6)
105 p = caglobals.ip.u6s.port;
107 else if (endpoint->flags & OC_IP_USE_V4)
109 p = caglobals.ip.u4s.port;
118 /* This method will retrieve the tcp port */
119 static OCStackResult GetTCPPortInfo(OCDevAddr *endpoint, uint16_t *port, bool secured)
123 if (endpoint->adapter == OC_ADAPTER_IP)
125 if (endpoint->flags & OC_IP_USE_V4)
127 p = secured ? caglobals.tcp.ipv4s.port : caglobals.tcp.ipv4.port;
129 else if (endpoint->flags & OC_IP_USE_V6)
131 p = secured ? caglobals.tcp.ipv6s.port : caglobals.tcp.ipv6.port;
141 * Function will extract 0, 1 or 2 filters from query.
142 * More than 2 filters or unsupported filters will result in error.
143 * If both filters are of the same supported type, the 2nd one will be picked.
144 * Resource and device filters in the SAME query are NOT validated
145 * and resources will likely not clear filters.
147 OCStackResult ExtractFiltersFromQuery(const char *query, char **filterOne, char **filterTwo)
151 OIC_LOG_V(ERROR, TAG, "Query is empty!");
152 return OC_STACK_INVALID_QUERY;
156 char *queryDup = NULL;
157 char *restOfQuery = NULL;
158 char *keyValuePair = NULL;
159 int numKeyValuePairsParsed = 0;
164 queryDup = OICStrdup(query);
165 if (NULL == queryDup)
167 OIC_LOG_V(ERROR, TAG, "Creating duplicate string failed!");
168 return OC_STACK_NO_MEMORY;
171 OIC_LOG_V(INFO, TAG, "Extracting params from %s", queryDup);
173 OCStackResult eCode = OC_STACK_INVALID_QUERY;
174 if (strnlen(queryDup, MAX_QUERY_LENGTH) >= MAX_QUERY_LENGTH)
176 OIC_LOG(ERROR, TAG, "Query exceeds maximum length.");
180 keyValuePair = strtok_r (queryDup, OC_QUERY_SEPARATOR, &restOfQuery);
184 if (numKeyValuePairsParsed >= 2)
186 OIC_LOG(ERROR, TAG, "More than 2 queries params in URI.");
190 key = strtok_r(keyValuePair, OC_KEY_VALUE_DELIMITER, &value);
196 else if (strncasecmp(key, OC_RSRVD_INTERFACE, sizeof(OC_RSRVD_INTERFACE) - 1) == 0)
198 *filterOne = value; // if
200 else if (strncasecmp(key, OC_RSRVD_RESOURCE_TYPE, sizeof(OC_RSRVD_INTERFACE) - 1) == 0)
202 *filterTwo = value; // rt
206 OIC_LOG_V(ERROR, TAG, "Unsupported query key: %s", key);
209 ++numKeyValuePairsParsed;
211 keyValuePair = strtok_r(NULL, OC_QUERY_SEPARATOR, &restOfQuery);
216 *filterOne = OICStrdup(*filterOne);
217 if (NULL == *filterOne)
219 OIC_LOG_V(ERROR, TAG, "Creating duplicate string failed!");
220 eCode = OC_STACK_NO_MEMORY;
227 *filterTwo = OICStrdup(*filterTwo);
228 if (NULL == *filterTwo)
230 OIC_LOG_V(ERROR, TAG, "Creating duplicate string failed!");
232 eCode = OC_STACK_NO_MEMORY;
238 OIC_LOG_V(INFO, TAG, "Extracted params if: %s and rt: %s.", *filterOne, *filterTwo);
248 static OCVirtualResources GetTypeOfVirtualURI(const char *uriInRequest)
250 if (strcmp(uriInRequest, OC_RSRVD_WELL_KNOWN_URI) == 0)
252 return OC_WELL_KNOWN_URI;
254 else if (strcmp(uriInRequest, OC_RSRVD_DEVICE_URI) == 0)
256 return OC_DEVICE_URI;
258 else if (strcmp(uriInRequest, OC_RSRVD_PLATFORM_URI) == 0)
260 return OC_PLATFORM_URI;
262 else if (strcmp(uriInRequest, OC_RSRVD_RESOURCE_TYPES_URI) == 0)
264 return OC_RESOURCE_TYPES_URI;
266 else if (strcmp(uriInRequest, OC_RSRVD_INTROSPECTION_URI) == 0)
268 return OC_INTROSPECTION_URI;
270 else if (strcmp(uriInRequest, OC_RSRVD_INTROSPECTION_PAYLOAD_URI) == 0)
272 return OC_INTROSPECTION_PAYLOAD_URI;
274 #ifdef ROUTING_GATEWAY
275 else if (0 == strcmp(uriInRequest, OC_RSRVD_GATEWAY_URI))
277 return OC_GATEWAY_URI;
281 else if (strcmp(uriInRequest, OC_RSRVD_PRESENCE_URI) == 0)
285 #endif //WITH_PRESENCE
288 else if (0 == strcmp(uriInRequest, OC_RSRVD_WELL_KNOWN_MQ_URI))
290 return OC_MQ_BROKER_URI;
295 else if (strcmp(uriInRequest, OC_RSRVD_KEEPALIVE_URI) == 0)
297 return OC_KEEPALIVE_RESOURCE_URI;
301 return OC_UNKNOWN_URI;
304 static OCStackResult getQueryParamsForFiltering (OCVirtualResources uri, char *query,
305 char **filterOne, char **filterTwo)
307 if(!filterOne || !filterTwo)
309 return OC_STACK_INVALID_PARAM;
316 if (uri == OC_PRESENCE)
318 //Nothing needs to be done, except for pass a OC_PRESENCE query through as OC_STACK_OK.
319 OIC_LOG(INFO, TAG, "OC_PRESENCE Request for virtual resource.");
324 OCStackResult result = OC_STACK_OK;
328 result = ExtractFiltersFromQuery(query, filterOne, filterTwo);
334 static OCStackResult BuildDevicePlatformPayload(const OCResource *resourcePtr, OCRepPayload** payload,
337 OCRepPayload *tempPayload = OCRepPayloadCreate();
341 OCRepPayloadDestroy(tempPayload);
342 return OC_STACK_INVALID_PARAM;
347 return OC_STACK_NO_MEMORY;
352 const char *deviceId = OCGetServerInstanceIDString();
355 OIC_LOG(ERROR, TAG, "Failed retrieving device id.");
356 return OC_STACK_ERROR;
358 OCRepPayloadSetPropString(tempPayload, OC_RSRVD_DEVICE_ID, deviceId);
361 for (OCResourceType *resType = resourcePtr->rsrcType; resType; resType = resType->next)
363 OCRepPayloadAddResourceType(tempPayload, resType->resourcetypename);
366 for (OCResourceInterface *resInterface = resourcePtr->rsrcInterface; resInterface;
367 resInterface = resInterface->next)
369 OCRepPayloadAddInterface(tempPayload, resInterface->name);
372 for (OCAttribute *resAttrib = resourcePtr->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
374 if (resAttrib->attrName && resAttrib->attrValue)
376 if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName))
378 char *dmv = OCCreateString((OCStringLL *)resAttrib->attrValue);
381 OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, dmv);
387 OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, (char *)resAttrib->attrValue);
394 *payload = tempPayload;
398 OCRepPayloadAppend(*payload, tempPayload);
404 OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr,
405 OCRepPayload** payload, OCDevAddr *devAddr)
407 OCRepPayload *tempPayload = OCRepPayloadCreate();
411 OCRepPayloadDestroy(tempPayload);
412 return OC_STACK_INVALID_PARAM;
417 return OC_STACK_NO_MEMORY;
420 OCRepPayloadSetPropString(tempPayload, OC_RSRVD_HREF, resourcePtr->uri);
422 uint8_t numElement = 0;
423 if (OC_STACK_OK == OCGetNumberOfResourceTypes((OCResource *)resourcePtr, &numElement))
425 size_t rtDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
426 char **rt = (char **)OICMalloc(sizeof(char *) * numElement);
427 for (uint8_t i = 0; i < numElement; ++i)
429 const char *value = OCGetResourceTypeName((OCResource *)resourcePtr, i);
430 OIC_LOG_V(DEBUG, TAG, "value: %s", value);
431 rt[i] = OICStrdup(value);
433 OCRepPayloadSetStringArrayAsOwner(tempPayload, OC_RSRVD_RESOURCE_TYPE, rt, rtDim);
437 if (OC_STACK_OK == OCGetNumberOfResourceInterfaces((OCResource *)resourcePtr, &numElement))
439 size_t ifDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
440 char **itf = (char **)OICMalloc(sizeof(char *) * numElement);
441 for (uint8_t i = 0; i < numElement; ++i)
443 const char *value = OCGetResourceInterfaceName((OCResource *)resourcePtr, i);
444 OIC_LOG_V(DEBUG, TAG, "value: %s", value);
445 itf[i] = OICStrdup(value);
447 OCRepPayloadSetStringArrayAsOwner(tempPayload, OC_RSRVD_INTERFACE, itf, ifDim);
450 for (OCAttribute *resAttrib = resourcePtr->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
452 if (resAttrib->attrName && resAttrib->attrValue)
454 OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, (char *)resAttrib->attrValue);
458 OCResourceProperty p = OCGetResourceProperties((OCResourceHandle *)resourcePtr);
459 OCRepPayload *policy = OCRepPayloadCreate();
462 OCPayloadDestroy((OCPayload *)tempPayload);
463 return OC_STACK_NO_MEMORY;
465 OCRepPayloadSetPropInt(policy, OC_RSRVD_BITMAP, ((p & OC_DISCOVERABLE) | (p & OC_OBSERVABLE)));
468 OCRepPayloadSetPropBool(policy, OC_RSRVD_SECURE, p & OC_SECURE);
469 uint16_t securePort = 0;
470 if (GetSecurePortInfo(devAddr, &securePort) != OC_STACK_OK)
474 OCRepPayloadSetPropInt(policy, OC_RSRVD_HOSTING_PORT, securePort);
476 OCRepPayloadSetPropObjectAsOwner(tempPayload, OC_RSRVD_POLICY, policy);
480 *payload = tempPayload;
484 OCRepPayloadAppend(*payload, tempPayload);
490 static size_t GetIntrospectionDataSize(const OCPersistentStorage *ps)
493 char buffer[INTROSPECTION_FILE_SIZE_BLOCK];
501 fp = ps->open(OC_INTROSPECTION_FILE_NAME, "rb");
504 size_t bytesRead = 0;
507 bytesRead = ps->read(buffer, 1, INTROSPECTION_FILE_SIZE_BLOCK, fp);
515 OCStackResult GetIntrospectionDataFromPS(char **data, size_t *size)
517 OIC_LOG(DEBUG, TAG, "GetIntrospectionDataFromPS IN");
520 uint8_t *fsData = NULL;
522 OCStackResult ret = OC_STACK_ERROR;
523 OCPersistentStorage *ps = NULL;
525 if (!data || *data || !size)
527 return OC_STACK_INVALID_PARAM;
530 ps = OCGetPersistentStorageHandler();
533 OIC_LOG(ERROR, TAG, "Persistent Storage handler is NULL");
537 fileSize = GetIntrospectionDataSize(ps);
538 OIC_LOG_V(DEBUG, TAG, "File Read Size: %zu", fileSize);
541 // allocate one more byte to accomodate null terminator for string we are reading.
542 fsData = (uint8_t *)OICCalloc(1, fileSize + 1);
545 OIC_LOG(ERROR, TAG, "Could not allocate memory for introspection data");
549 fp = ps->open(OC_INTROSPECTION_FILE_NAME, "rb");
552 OIC_LOG(ERROR, TAG, "Could not open persistent storage file for introspection data");
555 if (ps->read(fsData, 1, fileSize, fp) == fileSize)
558 fsData[fileSize] = '\0';
559 *data = (char *)fsData;
564 OIC_LOG(DEBUG, TAG, "GetIntrospectionDataFromPS OUT");
578 OCStackResult BuildIntrospectionPayloadResponse(const OCResource *resourcePtr,
579 OCRepPayload** payload, OCDevAddr *devAddr)
581 OCRepPayload *tempPayload = NULL;
583 char *introspectionData = NULL;
585 ret = GetIntrospectionDataFromPS(&introspectionData, &size);
586 if (OC_STACK_OK == ret)
588 OCRepPayload *tempPayload = OCRepPayloadCreate();
591 if (OCRepPayloadSetPropStringAsOwner(tempPayload, OC_RSRVD_INTROSPECTION_DATA_NAME, introspectionData))
593 *payload = tempPayload;
598 ret = OC_STACK_NO_MEMORY;
601 if (ret != OC_STACK_OK)
603 OICFree(introspectionData);
604 OCRepPayloadDestroy(tempPayload);
610 OCRepPayload *BuildUrlInfoWithProtocol(const char *protocol)
612 OCStackResult result = OC_STACK_OK;
613 OCRepPayload *urlInfoPayload = OCRepPayloadCreate();
616 OIC_LOG_V(ERROR, TAG, "Failed to create a new RepPayload");
617 result = OC_STACK_NO_MEMORY;
621 if (!OCRepPayloadSetPropString(urlInfoPayload, OC_RSRVD_INTROSPECTION_URL, OC_RSRVD_INTROSPECTION_PAYLOAD_URI))
623 OIC_LOG_V(ERROR, TAG, "Failed to add url");
624 result = OC_STACK_ERROR;
627 if (!OCRepPayloadSetPropString(urlInfoPayload, OC_RSRVD_INTROSPECTION_PROTOCOL, protocol))
629 OIC_LOG_V(ERROR, TAG, "Failed to add protocol");
630 result = OC_STACK_ERROR;
633 if (!OCRepPayloadSetPropString(urlInfoPayload, OC_RSRVD_INTROSPECTION_CONTENT_TYPE, OC_RSRVD_INTROSPECTION_CONTENT_TYPE_VALUE))
635 OIC_LOG_V(ERROR, TAG, "Failed to add content type");
636 result = OC_STACK_ERROR;
639 if (!OCRepPayloadSetPropInt(urlInfoPayload, OC_RSRVD_INTROSPECTION_VERSION, OC_RSRVD_INTROSPECTION_VERSION_VALUE))
641 OIC_LOG_V(ERROR, TAG, "Failed to add version");
642 result = OC_STACK_ERROR;
647 if (result != OC_STACK_OK)
649 OCRepPayloadDestroy(urlInfoPayload);
650 urlInfoPayload = NULL;
652 return urlInfoPayload;
655 OCStackResult AddProtocolToLL(OCStringLL **protoLL, const char *protocol)
657 OCStringLL* cur = *protoLL;
658 // Check if protocol is already in list
661 if (strcmp(cur->value, protocol) == 0)
669 // The intent of the protocol list is to collect all unique protocols available on this
670 // endpoint. Set an error that can be used to skip processing this protocol further as
671 // it already exists in the list.
672 return OC_STACK_INVALID_PARAM;
676 cur = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
679 return OC_STACK_NO_MEMORY;
683 cur->value = OICStrdup(protocol);
687 return OC_STACK_NO_MEMORY;
690 cur->next = *protoLL;
695 void FreeProtocolLL(OCStringLL *protoLL)
697 OCStringLL* cur = protoLL;
700 OCStringLL *temp = cur;
702 OICFree(temp->value);
707 OCStackResult BuildIntrospectionResponseRepresentation(const OCResource *resourcePtr,
708 OCRepPayload** payload, OCDevAddr *devAddr)
710 size_t dimensions[3] = { 0, 0, 0 };
711 OCRepPayload *tempPayload = NULL;
712 OCRepPayload **urlInfoPayload = NULL;
713 OCStringLL *protoLL = NULL;
714 OCStackResult ret = OC_STACK_OK;
715 OCResourceType *resType = NULL;
716 OCResourceInterface *resInterface = NULL;
720 ret = OC_STACK_INVALID_PARAM;
724 tempPayload = OCRepPayloadCreate();
727 ret = OC_STACK_NO_MEMORY;
731 if (!OCRepPayloadSetUri(tempPayload, resourcePtr->uri))
733 OIC_LOG_V(ERROR, TAG, "Failed to set payload URI");
734 ret = OC_STACK_ERROR;
738 resType = resourcePtr->rsrcType;
741 if (!OCRepPayloadAddResourceType(tempPayload, resType->resourcetypename))
743 OIC_LOG_V(ERROR, TAG, "Failed at add resource type");
744 ret = OC_STACK_ERROR;
747 resType = resType->next;
750 resInterface = resourcePtr->rsrcInterface;
753 if (!OCRepPayloadAddInterface(tempPayload, resInterface->name))
755 OIC_LOG_V(ERROR, TAG, "Failed to add interface");
756 ret = OC_STACK_ERROR;
759 resInterface = resInterface->next;
761 if (!OCRepPayloadSetPropString(tempPayload, OC_RSRVD_INTROSPECTION_NAME, OC_RSRVD_INTROSPECTION_NAME_VALUE))
763 OIC_LOG_V(ERROR, TAG, "Failed to set Name property.");
764 ret = OC_STACK_ERROR;
768 // Figure out which protocols this endpoint supports
769 if (resourcePtr->endpointType & OC_COAP)
771 if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAP_STR))
776 if (resourcePtr->endpointType & OC_COAPS)
778 if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAPS_STR))
784 if (resourcePtr->endpointType & OC_COAP_TCP)
786 if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAP_STR))
791 if (resourcePtr->endpointType & OC_COAPS_TCP)
793 if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAPS_STR))
800 if (resourcePtr->endpointType & OC_HTTP)
802 if (OC_STACK_OK == AddProtocolToLL(&protoLL, HTTP_STR))
807 if (resourcePtr->endpointType & OC_HTTPS)
809 if (OC_STACK_OK == AddProtocolToLL(&protoLL, HTTPS_STR))
816 if (resourcePtr->endpointType & OC_COAP_RFCOMM)
818 if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAP_STR))
824 // Add a urlInfo object for each protocol supported
825 if (dimensions[0] >= 0)
827 urlInfoPayload = (OCRepPayload **)OICMalloc(dimensions[0] * sizeof(OCRepPayload));
830 OCStringLL *proto = protoLL;
834 urlInfoPayload[i] = BuildUrlInfoWithProtocol(proto->value);
835 if (!urlInfoPayload[i])
837 OIC_LOG_V(ERROR, TAG, "Unable to build urlInfo object for protocol");
838 ret = OC_STACK_ERROR;
844 if (!OCRepPayloadSetPropObjectArrayAsOwner(tempPayload,
845 OC_RSRVD_INTROSPECTION_URL_INFO,
849 OIC_LOG_V(ERROR, TAG, "Unable to add urlInfo object to introspection payload ");
850 ret = OC_STACK_ERROR;
856 OIC_LOG_V(ERROR, TAG, "Unable to allocate memory for urlInfo ");
857 ret = OC_STACK_NO_MEMORY;
864 *payload = tempPayload;
868 OCRepPayloadAppend(*payload, tempPayload);
871 if (ret != OC_STACK_OK)
873 OCRepPayloadDestroy(tempPayload);
876 OICFree(urlInfoPayload);
879 FreeProtocolLL(protoLL);
884 OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
885 OCDiscoveryPayload *payload,
887 CAEndpoint_t *networkInfo,
890 if (!resourcePtr || !payload)
892 return OC_STACK_INVALID_PARAM;
894 uint16_t securePort = 0;
895 if (resourcePtr->resourceProperties & OC_SECURE)
897 if (GetSecurePortInfo(devAddr, &securePort) != OC_STACK_OK)
903 bool isVirtual = false;
904 if (GetTypeOfVirtualURI(resourcePtr->uri) != OC_UNKNOWN_URI)
909 uint16_t tcpPort = 0;
910 GetTCPPortInfo(devAddr, &tcpPort, (resourcePtr->resourceProperties & OC_SECURE));
912 OCDiscoveryPayloadAddResourceWithEps(payload, resourcePtr, securePort,
913 isVirtual, networkInfo, infoSize, devAddr, tcpPort);
915 OCDiscoveryPayloadAddResourceWithEps(payload, resourcePtr, securePort,
916 isVirtual, networkInfo, infoSize, devAddr);
922 OCResource *FindResourceByUri(const char* resourceUri)
929 OCResource * pointer = headResource;
932 if (strcmp(resourceUri, pointer->uri) == 0)
936 pointer = pointer->next;
938 OIC_LOG_V(INFO, TAG, "Resource %s not found", resourceUri);
942 OCStackResult CheckRequestsEndpoint(const OCDevAddr *reqDevAddr,
943 OCTpsSchemeFlags resTpsFlags)
947 OIC_LOG(ERROR, TAG, "OCDevAddr* is NULL!!!");
948 return OC_STACK_INVALID_PARAM;
951 OCTpsSchemeFlags reqTpsFlags = OC_NO_TPS;
952 OCStackResult result = OCGetMatchedTpsFlags((CATransportAdapter_t)reqDevAddr->adapter,
953 (CATransportFlags_t)reqDevAddr->flags, &reqTpsFlags);
955 if (result != OC_STACK_OK)
957 OIC_LOG_V(ERROR, TAG, "Failed at get TPS flags. errcode is %d", result);
961 // bit compare between request tps flags and resource tps flags
962 if (reqTpsFlags & resTpsFlags)
964 OIC_LOG(INFO, TAG, "Request come from registered TPS");
969 OIC_LOG(ERROR, TAG, "Request come from unregistered TPS!!!");
970 return OC_STACK_BAD_ENDPOINT;
974 OCStackResult DetermineResourceHandling (const OCServerRequest *request,
975 ResourceHandling *handling,
976 OCResource **resource)
978 if(!request || !handling || !resource)
980 return OC_STACK_INVALID_PARAM;
983 OIC_LOG_V(INFO, TAG, "DetermineResourceHandling for %s", request->resourceUrl);
985 // Check if virtual resource
986 if (GetTypeOfVirtualURI(request->resourceUrl) != OC_UNKNOWN_URI)
988 OIC_LOG_V (INFO, TAG, "%s is virtual", request->resourceUrl);
989 *handling = OC_RESOURCE_VIRTUAL;
990 *resource = headResource;
993 if (strlen((const char*)(request->resourceUrl)) == 0)
995 // Resource URL not specified
996 *handling = OC_RESOURCE_NOT_SPECIFIED;
997 return OC_STACK_NO_RESOURCE;
1001 OCResource *resourcePtr = FindResourceByUri((const char*)request->resourceUrl);
1002 *resource = resourcePtr;
1004 // Checking resource TPS flags if resource exist in stack.
1007 OCStackResult result = CheckRequestsEndpoint(&(request->devAddr), resourcePtr->endpointType);
1009 if (result != OC_STACK_OK)
1011 if (result == OC_STACK_BAD_ENDPOINT)
1013 OIC_LOG(ERROR, TAG, "Request come from bad endpoint. ignore request!!!");
1014 return OC_STACK_BAD_ENDPOINT;
1018 OIC_LOG_V(ERROR, TAG, "Failed at get tps flag errcode: %d", result);
1026 if(defaultDeviceHandler)
1028 *handling = OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER;
1032 // Resource does not exist
1033 // and default device handler does not exist
1034 *handling = OC_RESOURCE_NOT_SPECIFIED;
1035 return OC_STACK_NO_RESOURCE;
1038 if (resourcePtr && resourcePtr->rsrcChildResourcesHead != NULL)
1040 // Collection resource
1041 if (resourcePtr->entityHandler != defaultResourceEHandler)
1043 *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER;
1048 *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER;
1054 // Resource not a collection
1055 if (resourcePtr->entityHandler != defaultResourceEHandler)
1057 *handling = OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER;
1062 *handling = OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER;
1069 OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
1071 OCStackResult result;
1078 result = OC_STACK_OK;
1081 result = OC_STACK_SLOW_RESOURCE;
1084 result = OC_STACK_ERROR;
1086 case OC_EH_FORBIDDEN:
1087 result = OC_STACK_FORBIDDEN_REQ;
1089 case OC_EH_INTERNAL_SERVER_ERROR:
1090 result = OC_STACK_INTERNAL_SERVER_ERROR;
1092 case OC_EH_RESOURCE_CREATED:
1093 result = OC_STACK_RESOURCE_CREATED;
1095 case OC_EH_RESOURCE_DELETED:
1096 result = OC_STACK_RESOURCE_DELETED;
1099 result = OC_STACK_RESOURCE_CHANGED;
1101 case OC_EH_RESOURCE_NOT_FOUND:
1102 result = OC_STACK_NO_RESOURCE;
1105 result = OC_STACK_ERROR;
1111 static bool resourceMatchesRTFilter(OCResource *resource, char *resourceTypeFilter)
1118 // Null is analogous to no filter.i.e. query is of form /oic/res?if=oic.if.baseline or /oic/res,
1119 // without rt query.
1120 if (NULL == resourceTypeFilter)
1125 // Empty resourceType filter is analogous to error query
1126 // It is an error as query is of form /oic/res?rt=
1127 if (0 == strlen(resourceTypeFilter))
1132 for (OCResourceType *rtPtr = resource->rsrcType; rtPtr; rtPtr = rtPtr->next)
1134 if (0 == strcmp(rtPtr->resourcetypename, resourceTypeFilter))
1140 OIC_LOG_V(INFO, TAG, "%s does not contain rt=%s.", resource->uri, resourceTypeFilter);
1144 static bool resourceMatchesIFFilter(OCResource *resource, char *interfaceFilter)
1151 // Null is analogous to no filter i.e. query is of form /oic/res?rt=core.light or /oic/res,
1152 // without if query.
1153 if (NULL == interfaceFilter)
1158 // Empty interface filter is analogous to error query
1159 // It is an error as query is of form /oic/res?if=
1160 if (0 == strlen(interfaceFilter))
1165 for (OCResourceInterface *ifPtr = resource->rsrcInterface; ifPtr; ifPtr = ifPtr->next)
1167 if (0 == strcmp(ifPtr->name, interfaceFilter) ||
1168 0 == strcmp(OC_RSRVD_INTERFACE_LL, interfaceFilter) ||
1169 0 == strcmp(OC_RSRVD_INTERFACE_DEFAULT, interfaceFilter))
1175 OIC_LOG_V(INFO, TAG, "%s does not contain if=%s.", resource->uri, interfaceFilter);
1180 * If the filters are null, they will be assumed to NOT be present
1181 * and the resource will not be matched against them.
1182 * Function will return true if all non null AND non empty filters passed in find a match.
1184 static bool includeThisResourceInResponse(OCResource *resource,
1185 char *interfaceFilter,
1186 char *resourceTypeFilter)
1190 OIC_LOG(ERROR, TAG, "Invalid resource");
1194 if (resource->resourceProperties & OC_EXPLICIT_DISCOVERABLE)
1197 * At least one valid filter should be available to
1198 * include the resource in discovery response
1200 if (!(resourceTypeFilter && *resourceTypeFilter))
1202 OIC_LOG_V(INFO, TAG, "%s no query string for EXPLICIT_DISCOVERABLE\
1203 resource", resource->uri);
1207 else if (!(resource->resourceProperties & OC_ACTIVE) ||
1208 !(resource->resourceProperties & OC_DISCOVERABLE))
1210 OIC_LOG_V(INFO, TAG, "%s not ACTIVE or DISCOVERABLE", resource->uri);
1214 return resourceMatchesIFFilter(resource, interfaceFilter) &&
1215 resourceMatchesRTFilter(resource, resourceTypeFilter);
1218 OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCResource *resource,
1219 OCPayload *discoveryPayload, OCEntityHandlerResult ehResult)
1221 OCEntityHandlerResponse *response = NULL;
1222 OCStackResult result = OC_STACK_ERROR;
1224 response = (OCEntityHandlerResponse *)OICCalloc(1, sizeof(*response));
1225 VERIFY_PARAM_NON_NULL(TAG, response, "Failed allocating OCEntityHandlerResponse");
1227 response->ehResult = ehResult;
1228 response->payload = discoveryPayload;
1229 response->persistentBufferFlag = 0;
1230 response->requestHandle = (OCRequestHandle) request;
1231 response->resourceHandle = (OCResourceHandle) resource;
1233 result = OCDoResponse(response);
1239 return OC_STACK_NO_MEMORY;
1242 static OCStackResult EHRequest(OCEntityHandlerRequest *ehRequest, OCPayloadType type,
1243 OCServerRequest *request, OCResource *resource)
1245 return FormOCEntityHandlerRequest(ehRequest,
1246 (OCRequestHandle)request,
1249 (OCResourceHandle)resource,
1253 request->payloadSize,
1254 request->numRcvdVendorSpecificHeaderOptions,
1255 request->rcvdVendorSpecificHeaderOptions,
1256 (OCObserveAction)request->observationOption,
1263 * Find resource at the resource directory server. This resource is not local resource but a
1266 * @param resource The resource to check the matching resource URI.
1267 * @param interfaceQuery The interface query parameter.
1268 * @param resourceTypeQuery The resourceType query parameter.
1269 * @param discPayload The payload that will be added with the resource information if found at RD.
1271 * @return ::OC_STACK_OK if the resource is found else ::OC_STACK_NO_RESOURCE.
1272 * In case if build is not with flag RD_SERVER, it returns ::OC_STACK_NO_RESOURCE.
1274 static OCStackResult findResourceAtRD(const OCResource* resource, const char *interfaceQuery,
1275 const char *resourceTypeQuery, OCDiscoveryPayload *discPayload)
1277 if (strcmp(resource->uri, OC_RSRVD_RD_URI) == 0)
1279 if (OC_STACK_OK == OCRDDatabaseCheckResources(interfaceQuery, resourceTypeQuery, discPayload))
1285 return OC_STACK_NO_RESOURCE;
1290 * Creates a discovery payload and add device id information. This information is included in all
1291 * /oic/res response.
1293 * @param payload payload that will have memory alllocated and device id information added.
1295 * @return ::OC_STACK_OK if successful in allocating memory and adding ID information.
1296 * ::OC_STACK_NO_MEMORY if failed allocating the memory.
1298 static OCStackResult discoveryPayloadCreateAndAddDeviceId(OCPayload **payload)
1302 OIC_LOG(DEBUG, TAG, "Payload is already allocated");
1306 *payload = (OCPayload *) OCDiscoveryPayloadCreate();
1307 VERIFY_PARAM_NON_NULL(TAG, *payload, "Failed adding device id to discovery payload.");
1310 OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)*payload;
1311 discPayload->sid = (char *)OICCalloc(1, UUID_STRING_SIZE);
1312 VERIFY_PARAM_NON_NULL(TAG, discPayload->sid, "Failed adding device id to discovery payload.");
1314 const char* uid = OCGetServerInstanceIDString();
1317 memcpy(discPayload->sid, uid, UUID_STRING_SIZE);
1323 OCPayloadDestroy(*payload);
1324 return OC_STACK_NO_MEMORY;
1328 * Add the common properties to the payload, they are only included in case of oic.if.baseline response.
1330 * @param discPayload payload that will have the baseline information included.
1332 * @return ::OC_STACK_OK if successful in adding all the information. ::OC_STACK_NO_MEMORY if failed
1333 * allocating the memory for the baseline information.
1335 static OCStackResult addDiscoveryBaselineCommonProperties(OCDiscoveryPayload *discPayload)
1339 OIC_LOG(ERROR, TAG, "Payload is not allocated");
1340 return OC_STACK_INVALID_PARAM;
1343 OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, (void **)&discPayload->name);
1345 discPayload->type = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1346 VERIFY_PARAM_NON_NULL(TAG, discPayload->type, "Failed adding rt to discovery payload.");
1347 discPayload->type->value = OICStrdup(OC_RSRVD_RESOURCE_TYPE_RES);
1348 VERIFY_PARAM_NON_NULL(TAG, discPayload->type, "Failed adding rt value to discovery payload.");
1350 OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_LL);
1351 OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_DEFAULT);
1352 VERIFY_PARAM_NON_NULL(TAG, discPayload->iface, "Failed adding if to discovery payload.");
1357 return OC_STACK_NO_MEMORY;
1360 static bool isUnicast(OCServerRequest *request)
1362 bool isMulticast = request->devAddr.flags & OC_MULTICAST;
1363 return (isMulticast == false &&
1364 (request->devAddr.adapter != OC_ADAPTER_RFCOMM_BTEDR) &&
1365 (request->devAddr.adapter != OC_ADAPTER_GATT_BTLE));
1368 static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource)
1370 if (!request || !resource)
1372 return OC_STACK_INVALID_PARAM;
1375 OCPayload* payload = NULL;
1376 char *interfaceQuery = NULL;
1377 char *resourceTypeQuery = NULL;
1378 char *dataModelVersions = NULL;
1380 OIC_LOG(INFO, TAG, "Entering HandleVirtualResource");
1382 OCVirtualResources virtualUriInRequest = GetTypeOfVirtualURI (request->resourceUrl);
1385 if (OC_KEEPALIVE_RESOURCE_URI == virtualUriInRequest)
1387 // Received request for a keepalive
1388 OIC_LOG(INFO, TAG, "Request is for KeepAlive Request");
1389 return HandleKeepAliveRequest(request, resource);
1393 OCStackResult discoveryResult = OC_STACK_ERROR;
1394 if (request->method == OC_REST_PUT || request->method == OC_REST_POST ||
1395 request->method == OC_REST_DELETE)
1397 OIC_LOG_V(ERROR, TAG, "Resource : %s not permitted for method: %d",
1398 request->resourceUrl, request->method);
1399 return OC_STACK_UNAUTHORIZED_REQ;
1402 // Step 1: Generate the response to discovery request
1403 if (virtualUriInRequest == OC_WELL_KNOWN_URI
1405 || virtualUriInRequest == OC_MQ_BROKER_URI
1409 char *interfaceQuery = NULL;
1410 char *resourceTypeQuery = NULL;
1412 CAEndpoint_t *networkInfo = NULL;
1413 uint32_t infoSize = 0;
1415 CAResult_t caResult = CAGetNetworkInformation(&networkInfo, &infoSize);
1416 if (CA_STATUS_FAILED == caResult)
1418 OIC_LOG(ERROR, TAG, "CAGetNetworkInformation has error on parsing network infomation");
1419 return OC_STACK_ERROR;
1422 discoveryResult = getQueryParamsForFiltering (virtualUriInRequest, request->query,
1423 &interfaceQuery, &resourceTypeQuery);
1424 VERIFY_SUCCESS(discoveryResult);
1426 if (!interfaceQuery && !resourceTypeQuery)
1428 // If no query is sent, default interface is used i.e. oic.if.ll.
1429 interfaceQuery = OICStrdup(OC_RSRVD_INTERFACE_LL);
1432 discoveryResult = discoveryPayloadCreateAndAddDeviceId(&payload);
1433 VERIFY_PARAM_NON_NULL(TAG, payload, "Failed creating Discovery Payload.");
1434 VERIFY_SUCCESS(discoveryResult);
1436 OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)payload;
1437 if (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_DEFAULT))
1439 discoveryResult = addDiscoveryBaselineCommonProperties(discPayload);
1440 VERIFY_SUCCESS(discoveryResult);
1442 OCResourceProperty prop = OC_DISCOVERABLE;
1444 prop = (OC_MQ_BROKER_URI == virtualUriInRequest) ? OC_MQ_BROKER : prop;
1446 for (; resource && discoveryResult == OC_STACK_OK; resource = resource->next)
1448 // This case will handle when no resource type and it is oic.if.ll.
1449 // Do not assume check if the query is ll
1450 if (!resourceTypeQuery &&
1451 (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_LL)))
1453 // Only include discoverable type
1454 if (resource->resourceProperties & prop)
1456 discoveryResult = BuildVirtualResourceResponse(resource,
1463 else if (includeThisResourceInResponse(resource, interfaceQuery, resourceTypeQuery))
1465 discoveryResult = BuildVirtualResourceResponse(resource,
1473 discoveryResult = OC_STACK_OK;
1476 if (discPayload->resources == NULL)
1478 discoveryResult = OC_STACK_NO_RESOURCE;
1483 OICFree(networkInfo);
1486 else if (virtualUriInRequest == OC_DEVICE_URI)
1488 OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_DEVICE_URI);
1489 VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Device URI not found.");
1490 discoveryResult = BuildDevicePlatformPayload(resourcePtr, (OCRepPayload **)&payload, true);
1492 else if (virtualUriInRequest == OC_PLATFORM_URI)
1494 OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_PLATFORM_URI);
1495 VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Platform URI not found.");
1496 discoveryResult = BuildDevicePlatformPayload(resourcePtr, (OCRepPayload **)&payload, false);
1498 #ifdef ROUTING_GATEWAY
1499 else if (OC_GATEWAY_URI == virtualUriInRequest)
1501 // Received request for a gateway
1502 OIC_LOG(INFO, TAG, "Request is for Gateway Virtual Request");
1503 discoveryResult = RMHandleGatewayRequest(request, resource);
1506 else if (OC_INTROSPECTION_URI == virtualUriInRequest)
1508 // Received request for introspection
1509 OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_INTROSPECTION_URI);
1510 VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Introspection URI not found.");
1511 discoveryResult = BuildIntrospectionResponseRepresentation(resourcePtr, (OCRepPayload **)&payload, &request->devAddr);
1512 OIC_LOG(INFO, TAG, "Request is for Introspection");
1514 else if (OC_INTROSPECTION_PAYLOAD_URI == virtualUriInRequest)
1516 // Received request for introspection payload
1517 OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_INTROSPECTION_PAYLOAD_URI);
1518 VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Introspection Payload URI not found.");
1519 discoveryResult = BuildIntrospectionPayloadResponse(resourcePtr, (OCRepPayload **)&payload, &request->devAddr);
1520 OIC_LOG(INFO, TAG, "Request is for Introspection Payload");
1523 * Step 2: Send the discovery response
1525 * Iotivity should respond to discovery requests in below manner:
1526 * 1)If query filter matching fails and discovery request is multicast,
1527 * it should NOT send any response.
1528 * 2)If query filter matching fails and discovery request is unicast,
1529 * it should send an error(RESOURCE_NOT_FOUND - 404) response.
1530 * 3)If Server does not have any 'DISCOVERABLE' resources and discovery
1531 * request is multicast, it should NOT send any response.
1532 * 4)If Server does not have any 'DISCOVERABLE' resources and discovery
1533 * request is unicast, it should send an error(RESOURCE_NOT_FOUND - 404) response.
1536 #ifdef WITH_PRESENCE
1537 if ((virtualUriInRequest == OC_PRESENCE) &&
1538 (resource->resourceProperties & OC_ACTIVE))
1540 // Need to send ACK when the request is CON.
1541 if (request->qos == OC_HIGH_QOS)
1543 CAEndpoint_t endpoint = { .adapter = CA_DEFAULT_ADAPTER };
1544 CopyDevAddrToEndpoint(&request->devAddr, &endpoint);
1545 SendDirectStackResponse(&endpoint, request->coapID, CA_EMPTY, CA_MSG_ACKNOWLEDGE,
1546 0, NULL, NULL, 0, NULL, CA_RESPONSE_FOR_RES);
1548 FindAndDeleteServerRequest(request);
1550 // Presence uses observer notification api to respond via SendPresenceNotification.
1551 SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
1556 // Gateway uses the RMHandleGatewayRequest to respond to the request.
1557 if (OC_GATEWAY_URI != virtualUriInRequest)
1560 OIC_LOG_PAYLOAD(DEBUG, payload);
1561 if(discoveryResult == OC_STACK_OK)
1564 SendNonPersistantDiscoveryResponse(request, resource, payload, OC_EH_OK);
1566 else // Error handling
1568 if (isUnicast(request))
1570 OIC_LOG_V(ERROR, TAG, "Sending a (%d) error to (%d) discovery request",
1571 discoveryResult, virtualUriInRequest);
1572 SendNonPersistantDiscoveryResponse(request, resource, NULL,
1573 (discoveryResult == OC_STACK_NO_RESOURCE) ?
1574 OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR);
1578 // Ignoring the discovery request as per RFC 7252, Section #8.2
1579 OIC_LOG(INFO, TAG, "Silently ignoring the request since no useful data to send.");
1580 // the request should be removed.
1581 // since it never remove and causes a big memory waste.
1582 FindAndDeleteServerRequest(request);
1584 discoveryResult = OC_STACK_CONTINUE;
1591 OICFree(interfaceQuery);
1594 if (resourceTypeQuery)
1596 OICFree(resourceTypeQuery);
1598 OCPayloadDestroy(payload);
1599 if (dataModelVersions)
1601 OICFree(dataModelVersions);
1603 // To ignore the message, OC_STACK_CONTINUE is sent
1604 return discoveryResult;
1607 static OCStackResult
1608 HandleDefaultDeviceEntityHandler(OCServerRequest *request)
1612 return OC_STACK_INVALID_PARAM;
1615 OCEntityHandlerResult ehResult = OC_EH_ERROR;
1616 OCEntityHandlerRequest ehRequest = {0};
1617 OIC_LOG(INFO, TAG, "Entering HandleResourceWithDefaultDeviceEntityHandler");
1618 OCStackResult result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, NULL);
1619 VERIFY_SUCCESS(result);
1621 // At this point we know for sure that defaultDeviceHandler exists
1622 ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
1623 (char*) request->resourceUrl, defaultDeviceHandlerCallbackParameter);
1624 if(ehResult == OC_EH_SLOW)
1626 OIC_LOG(INFO, TAG, "This is a slow resource");
1627 request->slowFlag = 1;
1629 else if(ehResult == OC_EH_ERROR)
1631 FindAndDeleteServerRequest(request);
1633 result = EntityHandlerCodeToOCStackCode(ehResult);
1635 OCPayloadDestroy(ehRequest.payload);
1639 static OCStackResult
1640 HandleResourceWithEntityHandler(OCServerRequest *request,
1641 OCResource *resource)
1643 if(!request || ! resource)
1645 return OC_STACK_INVALID_PARAM;
1648 OCStackResult result = OC_STACK_ERROR;
1649 OCEntityHandlerResult ehResult = OC_EH_ERROR;
1650 OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
1651 ResourceObserver *resObs = NULL;
1653 OCEntityHandlerRequest ehRequest = {0};
1655 OIC_LOG(INFO, TAG, "Entering HandleResourceWithEntityHandler");
1656 OCPayloadType type = PAYLOAD_TYPE_REPRESENTATION;
1657 // check the security resource
1658 if (request && request->resourceUrl && SRMIsSecurityResourceURI(request->resourceUrl))
1660 type = PAYLOAD_TYPE_SECURITY;
1664 result = EHRequest(&ehRequest, type, request, resource);
1665 VERIFY_SUCCESS(result);
1667 if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
1669 OIC_LOG(INFO, TAG, "No observation requested");
1670 ehFlag = OC_REQUEST_FLAG;
1672 else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER)
1674 OIC_LOG(INFO, TAG, "Observation registration requested");
1676 ResourceObserver *obs = GetObserverUsingToken (request->requestToken,
1677 request->tokenLength);
1681 OIC_LOG (INFO, TAG, "Observer with this token already present");
1682 OIC_LOG (INFO, TAG, "Possibly re-transmitted CON OBS request");
1683 OIC_LOG (INFO, TAG, "Not adding observer. Not responding to client");
1684 OIC_LOG (INFO, TAG, "The first request for this token is already ACKED.");
1686 // server requests are usually free'd when the response is sent out
1687 // for the request in ocserverrequest.c : HandleSingleResponse()
1688 // Since we are making an early return and not responding, the server request
1689 // needs to be deleted.
1690 FindAndDeleteServerRequest (request);
1694 result = GenerateObserverId(&ehRequest.obsInfo.obsId);
1695 VERIFY_SUCCESS(result);
1697 result = AddObserver ((const char*)(request->resourceUrl),
1698 (const char *)(request->query),
1699 ehRequest.obsInfo.obsId, request->requestToken, request->tokenLength,
1700 resource, request->qos, request->acceptFormat,
1701 request->acceptVersion, &request->devAddr);
1703 if(result == OC_STACK_OK)
1705 OIC_LOG(INFO, TAG, "Added observer successfully");
1706 request->observeResult = OC_STACK_OK;
1707 ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
1709 else if (result == OC_STACK_RESOURCE_ERROR)
1711 OIC_LOG(INFO, TAG, "The Resource is not active, discoverable or observable");
1712 request->observeResult = OC_STACK_ERROR;
1713 ehFlag = OC_REQUEST_FLAG;
1717 // The error in observeResult for the request will be used when responding to this
1718 // request by omitting the observation option/sequence number.
1719 request->observeResult = OC_STACK_ERROR;
1720 OIC_LOG(ERROR, TAG, "Observer Addition failed");
1721 ehFlag = OC_REQUEST_FLAG;
1722 FindAndDeleteServerRequest(request);
1727 else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER)
1729 OIC_LOG(INFO, TAG, "Deregistering observation requested");
1731 resObs = GetObserverUsingToken (request->requestToken, request->tokenLength);
1735 // Stack does not contain this observation request
1736 // Either token is incorrect or observation list is corrupted
1737 result = OC_STACK_ERROR;
1740 ehRequest.obsInfo.obsId = resObs->observeId;
1741 ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
1743 result = DeleteObserverUsingToken (request->requestToken, request->tokenLength);
1745 if(result == OC_STACK_OK)
1747 OIC_LOG(INFO, TAG, "Removed observer successfully");
1748 request->observeResult = OC_STACK_OK;
1749 // There should be no observe option header for de-registration response.
1750 // Set as an invalid value here so we can detect it later and remove the field in response.
1751 request->observationOption = MAX_SEQUENCE_NUMBER + 1;
1755 request->observeResult = OC_STACK_ERROR;
1756 OIC_LOG(ERROR, TAG, "Observer Removal failed");
1757 FindAndDeleteServerRequest(request);
1763 result = OC_STACK_ERROR;
1767 ehResult = resource->entityHandler(ehFlag, &ehRequest, resource->entityHandlerCallbackParam);
1768 if(ehResult == OC_EH_SLOW)
1770 OIC_LOG(INFO, TAG, "This is a slow resource");
1771 request->slowFlag = 1;
1773 else if(ehResult == OC_EH_ERROR)
1775 FindAndDeleteServerRequest(request);
1777 result = EntityHandlerCodeToOCStackCode(ehResult);
1779 OCPayloadDestroy(ehRequest.payload);
1783 static OCStackResult HandleCollectionResourceDefaultEntityHandler(OCServerRequest *request,
1784 OCResource *resource)
1786 if (!request || !resource)
1788 return OC_STACK_INVALID_PARAM;
1791 OCEntityHandlerRequest ehRequest = {0};
1792 OCStackResult result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, resource);
1793 if(result == OC_STACK_OK)
1795 result = DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest);
1798 OCPayloadDestroy(ehRequest.payload);
1803 ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request)
1805 OCStackResult ret = OC_STACK_OK;
1807 switch (resHandling)
1809 case OC_RESOURCE_VIRTUAL:
1811 ret = HandleVirtualResource (request, resource);
1814 case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER:
1816 ret = HandleDefaultDeviceEntityHandler(request);
1819 case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
1821 OIC_LOG(INFO, TAG, "OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER");
1822 return OC_STACK_ERROR;
1824 case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
1826 ret = HandleResourceWithEntityHandler (request, resource);
1829 case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
1831 ret = HandleResourceWithEntityHandler (request, resource);
1834 case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
1836 ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
1839 case OC_RESOURCE_NOT_SPECIFIED:
1841 ret = OC_STACK_NO_RESOURCE;
1846 OIC_LOG(INFO, TAG, "Invalid Resource Determination");
1847 return OC_STACK_ERROR;
1853 OCStackResult OCSetPlatformInfo(OCPlatformInfo info)
1855 OCResource *resource = NULL;
1856 if (!info.platformID || !info.manufacturerName)
1858 OIC_LOG(ERROR, TAG, "No value specified.");
1861 if (0 == strlen(info.platformID) || 0 == strlen(info.manufacturerName))
1863 OIC_LOG(ERROR, TAG, "The passed value cannot be empty");
1866 if ((info.manufacturerName && strlen(info.manufacturerName) > MAX_PLATFORM_NAME_LENGTH) ||
1867 (info.manufacturerUrl && strlen(info.manufacturerUrl) > MAX_PLATFORM_URL_LENGTH) ||
1868 (info.modelNumber && strlen(info.modelNumber) > MAX_PLATFORM_NAME_LENGTH) ||
1869 (info.platformVersion && strlen(info.platformVersion) > MAX_PLATFORM_NAME_LENGTH) ||
1870 (info.operatingSystemVersion && strlen(info.operatingSystemVersion) > MAX_PLATFORM_NAME_LENGTH) ||
1871 (info.hardwareVersion && strlen(info.hardwareVersion) > MAX_PLATFORM_NAME_LENGTH) ||
1872 (info.firmwareVersion && strlen(info.firmwareVersion) > MAX_PLATFORM_NAME_LENGTH) ||
1873 (info.supportUrl && strlen(info.supportUrl) > MAX_PLATFORM_URL_LENGTH))
1875 OIC_LOG(ERROR, TAG, "The passed value is bigger than permitted.");
1880 * @todo (IOT-1541) There are several versions of a UUID structure and conversion
1881 * methods scattered around the IoTivity code base. They need to be combined
1884 uint8_t uuid[UUID_SIZE];
1885 if (!OCConvertStringToUuid(info.platformID, uuid))
1887 OIC_LOG(ERROR, TAG, "Platform ID is not a UUID.");
1891 resource = FindResourceByUri(OC_RSRVD_PLATFORM_URI);
1894 OIC_LOG(ERROR, TAG, "Platform Resource does not exist.");
1897 OIC_LOG(INFO, TAG, "Entering OCSetPlatformInfo");
1898 VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_PLATFORM_ID, info.platformID));
1899 VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_NAME, info.manufacturerName));
1900 OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_URL, info.manufacturerUrl);
1901 OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MODEL_NUM, info.modelNumber);
1902 OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_DATE, info.dateOfManufacture);
1903 OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_PLATFORM_VERSION, info.platformVersion);
1904 OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_OS_VERSION, info.operatingSystemVersion);
1905 OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_HARDWARE_VERSION, info.hardwareVersion);
1906 OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_FIRMWARE_VERSION, info.firmwareVersion);
1907 OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_SUPPORT_URL, info.supportUrl);
1908 OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_SYSTEM_TIME, info.systemTime);
1909 OIC_LOG(INFO, TAG, "Platform parameter initialized successfully.");
1913 return OC_STACK_INVALID_PARAM;
1916 OCStackResult OCSetDeviceInfo(OCDeviceInfo info)
1918 OCResource *resource = FindResourceByUri(OC_RSRVD_DEVICE_URI);
1921 OIC_LOG(ERROR, TAG, "Device Resource does not exist.");
1924 if (!info.deviceName || info.deviceName[0] == '\0')
1926 OIC_LOG(ERROR, TAG, "Null or empty device name.");
1927 return OC_STACK_INVALID_PARAM;
1930 if (OCGetServerInstanceIDString() == NULL)
1932 OIC_LOG(INFO, TAG, "Device ID generation failed");
1936 VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, info.deviceName));
1937 for (OCStringLL *temp = info.types; temp; temp = temp->next)
1941 VERIFY_SUCCESS(OCBindResourceTypeToResource(resource, temp->value));
1944 VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_SPEC_VERSION, info.specVersion ?
1945 info.specVersion: OC_SPEC_VERSION));
1947 if (info.dataModelVersions)
1949 char *dmv = OCCreateString(info.dataModelVersions);
1950 VERIFY_PARAM_NON_NULL(TAG, dmv, "Failed allocating dataModelVersions");
1951 OCStackResult r = OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION, dmv);
1957 VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION,
1958 OC_DATA_MODEL_VERSION));
1960 OIC_LOG(INFO, TAG, "Device parameter initialized successfully.");
1964 return OC_STACK_ERROR;
1967 OCStackResult OCGetAttribute(const OCResource *resource, const char *attribute, void **value)
1969 if (!resource || !attribute)
1971 return OC_STACK_INVALID_PARAM;
1973 if (0 == strlen(attribute))
1975 return OC_STACK_INVALID_PARAM;
1977 for (OCAttribute *temp = resource->rsrcAttributes; temp; temp = temp->next)
1979 if (0 == strcmp(attribute, temp->attrName))
1981 // A special case as this type return OCStringLL
1982 if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, attribute))
1984 *value = CloneOCStringLL((OCStringLL *)temp->attrValue);
1989 *value = OICStrdup((char *)temp->attrValue);
1994 return OC_STACK_NO_RESOURCE;
1997 OCStackResult OCGetPropertyValue(OCPayloadType type, const char *prop, void **value)
2001 return OC_STACK_INVALID_PARAM;
2003 if (strlen(prop) == 0)
2005 return OC_STACK_INVALID_PARAM;
2011 OCStackResult res = OC_STACK_NO_RESOURCE;
2012 if (PAYLOAD_TYPE_DEVICE == type || PAYLOAD_TYPE_PLATFORM == type)
2014 const char *pathType = (type == PAYLOAD_TYPE_DEVICE) ? OC_RSRVD_DEVICE_URI : OC_RSRVD_PLATFORM_URI;
2015 OCResource *resource = FindResourceByUri(pathType);
2018 return OC_STACK_NO_RESOURCE;
2021 res = OCGetAttribute(resource, prop, value);
2026 OCStackResult OCSetAttribute(OCResource* resource, const char* attribute, const void* value)
2028 // See if the attribute already exists in the list.
2029 OCAttribute *resAttrib = NULL;
2030 for (resAttrib = resource->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
2032 if (0 == strcmp(attribute, resAttrib->attrName))
2034 // Found, free the old value.
2035 if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName))
2037 OCFreeOCStringLL((OCStringLL *)resAttrib->attrValue);
2041 OICFree((char *)resAttrib->attrValue);
2047 // If not already in the list, add it.
2048 if (NULL == resAttrib)
2050 resAttrib = (OCAttribute *)OICCalloc(1, sizeof(OCAttribute));
2051 VERIFY_PARAM_NON_NULL(TAG, resAttrib, "Failed allocating OCAttribute");
2052 resAttrib->attrName = OICStrdup(attribute);
2053 VERIFY_PARAM_NON_NULL(TAG, resAttrib->attrName, "Failed allocating attribute name");
2054 resAttrib->next = resource->rsrcAttributes;
2055 resource->rsrcAttributes = resAttrib;
2058 // Fill in the new value.
2059 if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, attribute))
2061 resAttrib->attrValue = OCCreateOCStringLL((char *)value);
2065 resAttrib->attrValue = OICStrdup((char *)value);
2067 VERIFY_PARAM_NON_NULL(TAG, resAttrib->attrValue, "Failed allocating attribute value");
2072 OCDeleteResourceAttributes(resAttrib);
2073 return OC_STACK_NO_MEMORY;
2077 OCStackResult OCSetPropertyValue(OCPayloadType type, const char *prop, const void *value)
2079 if (!prop || !value)
2081 return OC_STACK_INVALID_PARAM;
2083 if (strlen(prop) == 0)
2085 return OC_STACK_INVALID_PARAM;
2088 OCStackResult res = OC_STACK_ERROR;
2089 if (PAYLOAD_TYPE_DEVICE == type || PAYLOAD_TYPE_PLATFORM == type)
2091 const char *pathType = (type == PAYLOAD_TYPE_DEVICE) ? OC_RSRVD_DEVICE_URI : OC_RSRVD_PLATFORM_URI;
2092 OCResource *resource = FindResourceByUri(pathType);
2095 OIC_LOG(ERROR, TAG, "Resource does not exist.");
2099 res = OCSetAttribute(resource, prop, value);