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"
48 #include "ocpayload.h"
49 #include "secureresourcemanager.h"
51 #include "cainterface.h"
52 #include "ocpayload.h"
54 #ifdef ROUTING_GATEWAY
55 #include "routingmanager.h"
59 #include "rd_database.h"
63 #define TAG "OIC_RI_RESOURCE"
65 #define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
66 {OIC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
68 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OIC_LOG((logLevel), \
69 TAG, #arg " is NULL"); return (retVal); } }
71 #include "platform_features.h"
73 extern OCResource *headResource;
74 static OCPlatformInfo savedPlatformInfo = {0};
75 static OCDeviceInfo savedDeviceInfo = {0};
78 * Prepares a Payload for response.
80 static OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
81 OCDiscoveryPayload* payload,
84 //-----------------------------------------------------------------------------
85 // Default resource entity handler function
86 //-----------------------------------------------------------------------------
87 OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag,
88 OCEntityHandlerRequest * request, void* callbackParam)
90 //TODO ("Implement me!!!!");
91 // TODO: remove silence unused param warnings
95 return OC_EH_OK; // Making sure that the Default EH and the Vendor EH have matching signatures
98 /* This method will retrieve the port at which the secure resource is hosted */
99 static OCStackResult GetSecurePortInfo(OCDevAddr *endpoint, uint16_t *port)
103 if (endpoint->adapter == OC_ADAPTER_IP)
105 if (endpoint->flags & OC_IP_USE_V6)
107 p = caglobals.ip.u6s.port;
109 else if (endpoint->flags & OC_IP_USE_V4)
111 p = caglobals.ip.u4s.port;
120 /* This method will retrieve the tcp port */
121 static OCStackResult GetTCPPortInfo(OCDevAddr *endpoint, uint16_t *port)
125 if (endpoint->adapter == OC_ADAPTER_IP)
127 if (endpoint->flags & OC_IP_USE_V4)
129 p = caglobals.tcp.ipv4.port;
131 else if (endpoint->flags & OC_IP_USE_V6)
133 p = caglobals.tcp.ipv6.port;
143 * Function will extract 0, 1 or 2 filters from query.
144 * More than 2 filters or unsupported filters will result in error.
145 * If both filters are of the same supported type, the 2nd one will be picked.
146 * Resource and device filters in the SAME query are NOT validated
147 * and resources will likely not clear filters.
149 static OCStackResult ExtractFiltersFromQuery(char *query, char **filterOne, char **filterTwo)
153 char *queryDup = NULL;
154 char *restOfQuery = NULL;
155 char *keyValuePair = NULL;
156 int numKeyValuePairsParsed = 0;
161 queryDup = OICStrdup(query);
162 if (NULL == queryDup)
164 OIC_LOG_V(ERROR, TAG, "Creating duplicate string failed!");
165 return OC_STACK_NO_MEMORY;
168 OIC_LOG_V(INFO, TAG, "Extracting params from %s", queryDup);
170 OCStackResult eCode = OC_STACK_INVALID_QUERY;
171 if (strnlen(queryDup, MAX_QUERY_LENGTH) >= MAX_QUERY_LENGTH)
173 OIC_LOG(ERROR, TAG, "Query exceeds maximum length.");
177 keyValuePair = strtok_r (queryDup, OC_QUERY_SEPARATOR, &restOfQuery);
181 if (numKeyValuePairsParsed >= 2)
183 OIC_LOG(ERROR, TAG, "More than 2 queries params in URI.");
187 key = strtok_r(keyValuePair, OC_KEY_VALUE_DELIMITER, &value);
193 else if (strncasecmp(key, OC_RSRVD_INTERFACE, sizeof(OC_RSRVD_INTERFACE) - 1) == 0)
195 *filterOne = value; // if
197 else if (strncasecmp(key, OC_RSRVD_RESOURCE_TYPE, sizeof(OC_RSRVD_INTERFACE) - 1) == 0)
199 *filterTwo = value; // rt
203 OIC_LOG_V(ERROR, TAG, "Unsupported query key: %s", key);
206 ++numKeyValuePairsParsed;
208 keyValuePair = strtok_r(NULL, OC_QUERY_SEPARATOR, &restOfQuery);
213 *filterOne = OICStrdup(*filterOne);
214 if (NULL == *filterOne)
216 OIC_LOG_V(ERROR, TAG, "Creating duplicate string failed!");
217 eCode = OC_STACK_NO_MEMORY;
224 *filterTwo = OICStrdup(*filterTwo);
225 if (NULL == *filterTwo)
227 OIC_LOG_V(ERROR, TAG, "Creating duplicate string failed!");
229 eCode = OC_STACK_NO_MEMORY;
235 OIC_LOG_V(INFO, TAG, "Extracted params if: %s and rt: %s.", *filterOne, *filterTwo);
245 static OCVirtualResources GetTypeOfVirtualURI(const char *uriInRequest)
247 if (strcmp(uriInRequest, OC_RSRVD_WELL_KNOWN_URI) == 0)
249 return OC_WELL_KNOWN_URI;
251 else if (strcmp(uriInRequest, OC_RSRVD_DEVICE_URI) == 0)
253 return OC_DEVICE_URI;
255 else if (strcmp(uriInRequest, OC_RSRVD_PLATFORM_URI) == 0)
257 return OC_PLATFORM_URI;
259 else if (strcmp(uriInRequest, OC_RSRVD_RESOURCE_TYPES_URI) == 0)
261 return OC_RESOURCE_TYPES_URI;
263 #ifdef ROUTING_GATEWAY
264 else if (0 == strcmp(uriInRequest, OC_RSRVD_GATEWAY_URI))
266 return OC_GATEWAY_URI;
270 else if (strcmp(uriInRequest, OC_RSRVD_PRESENCE_URI) == 0)
274 #endif //WITH_PRESENCE
277 else if (0 == strcmp(uriInRequest, OC_RSRVD_WELL_KNOWN_MQ_URI))
279 return OC_MQ_BROKER_URI;
284 else if (strcmp(uriInRequest, OC_RSRVD_KEEPALIVE_URI) == 0)
286 return OC_KEEPALIVE_RESOURCE_URI;
290 return OC_UNKNOWN_URI;
293 static OCStackResult getQueryParamsForFiltering (OCVirtualResources uri, char *query,
294 char **filterOne, char **filterTwo)
296 if(!filterOne || !filterTwo)
298 return OC_STACK_INVALID_PARAM;
305 if (uri == OC_PRESENCE)
307 //Nothing needs to be done, except for pass a OC_PRESENCE query through as OC_STACK_OK.
308 OIC_LOG(INFO, TAG, "OC_PRESENCE Request for virtual resource.");
313 OCStackResult result = OC_STACK_OK;
317 result = ExtractFiltersFromQuery(query, filterOne, filterTwo);
323 OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr,
324 OCRepPayload** payload)
326 OCRepPayload *tempPayload = OCRepPayloadCreate();
330 OCRepPayloadDestroy(tempPayload);
331 return OC_STACK_INVALID_PARAM;
336 return OC_STACK_NO_MEMORY;
339 OCRepPayloadSetUri(tempPayload, resourcePtr->uri);
341 OCResourceType *resType = resourcePtr->rsrcType;
344 OCRepPayloadAddResourceType(tempPayload, resType->resourcetypename);
345 resType = resType->next;
348 OCResourceInterface *resInterface = resourcePtr->rsrcInterface;
351 OCRepPayloadAddInterface(tempPayload, resInterface->name);
352 resInterface = resInterface->next;
355 OCAttribute *resAttrib = resourcePtr->rsrcAttributes;
358 OCRepPayloadSetPropString(tempPayload, resAttrib->attrName,
359 resAttrib->attrValue);
360 resAttrib = resAttrib->next;
365 *payload = tempPayload;
369 OCRepPayloadAppend(*payload, tempPayload);
375 OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
376 OCDiscoveryPayload *payload, OCDevAddr *devAddr)
378 if (!resourcePtr || !payload)
380 return OC_STACK_INVALID_PARAM;
382 uint16_t securePort = 0;
383 if (resourcePtr->resourceProperties & OC_SECURE)
385 if (GetSecurePortInfo(devAddr, &securePort) != OC_STACK_OK)
392 uint16_t tcpPort = 0;
393 if (GetTCPPortInfo(devAddr, &tcpPort) != OC_STACK_OK)
397 OCDiscoveryPayloadAddResource(payload, resourcePtr, securePort, tcpPort);
399 OCDiscoveryPayloadAddResource(payload, resourcePtr, securePort);
405 uint8_t IsCollectionResource (OCResource *resource)
412 if(resource->rsrcChildResourcesHead != NULL)
420 OCResource *FindResourceByUri(const char* resourceUri)
427 OCResource * pointer = headResource;
430 if (strcmp(resourceUri, pointer->uri) == 0)
434 pointer = pointer->next;
436 OIC_LOG_V(INFO, TAG, "Resource %s not found", resourceUri);
441 OCStackResult DetermineResourceHandling (const OCServerRequest *request,
442 ResourceHandling *handling,
443 OCResource **resource)
445 if(!request || !handling || !resource)
447 return OC_STACK_INVALID_PARAM;
450 OIC_LOG_V(INFO, TAG, "DetermineResourceHandling for %s", request->resourceUrl);
452 // Check if virtual resource
453 if (GetTypeOfVirtualURI(request->resourceUrl) != OC_UNKNOWN_URI)
455 OIC_LOG_V (INFO, TAG, "%s is virtual", request->resourceUrl);
456 *handling = OC_RESOURCE_VIRTUAL;
457 *resource = headResource;
460 if (strlen((const char*)(request->resourceUrl)) == 0)
462 // Resource URL not specified
463 *handling = OC_RESOURCE_NOT_SPECIFIED;
464 return OC_STACK_NO_RESOURCE;
468 OCResource *resourcePtr = FindResourceByUri((const char*)request->resourceUrl);
469 *resource = resourcePtr;
472 if(defaultDeviceHandler)
474 *handling = OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER;
478 // Resource does not exist
479 // and default device handler does not exist
480 *handling = OC_RESOURCE_NOT_SPECIFIED;
481 return OC_STACK_NO_RESOURCE;
484 if (IsCollectionResource (resourcePtr))
486 // Collection resource
487 if (resourcePtr->entityHandler != defaultResourceEHandler)
489 *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER;
494 *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER;
500 // Resource not a collection
501 if (resourcePtr->entityHandler != defaultResourceEHandler)
503 *handling = OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER;
508 *handling = OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER;
515 OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
517 OCStackResult result;
524 result = OC_STACK_OK;
527 result = OC_STACK_SLOW_RESOURCE;
530 result = OC_STACK_ERROR;
532 case OC_EH_FORBIDDEN:
533 result = OC_STACK_FORBIDDEN_REQ;
535 case OC_EH_INTERNAL_SERVER_ERROR:
536 result = OC_STACK_INTERNAL_SERVER_ERROR;
538 case OC_EH_RESOURCE_CREATED:
539 result = OC_STACK_RESOURCE_CREATED;
541 case OC_EH_RESOURCE_DELETED:
542 result = OC_STACK_RESOURCE_DELETED;
545 result = OC_STACK_RESOURCE_CHANGED;
547 case OC_EH_RESOURCE_NOT_FOUND:
548 result = OC_STACK_NO_RESOURCE;
551 result = OC_STACK_ERROR;
557 static bool resourceMatchesRTFilter(OCResource *resource, char *resourceTypeFilter)
564 // Null or empty is analogous to no filter.
565 if (resourceTypeFilter == NULL || *resourceTypeFilter == 0)
570 OCResourceType *resourceTypePtr = resource->rsrcType;
572 while (resourceTypePtr)
574 if (strcmp (resourceTypePtr->resourcetypename, resourceTypeFilter) == 0)
578 resourceTypePtr = resourceTypePtr->next;
581 OIC_LOG_V(INFO, TAG, "%s does not contain rt=%s.", resource->uri, resourceTypeFilter);
585 static bool resourceMatchesIFFilter(OCResource *resource, char *interfaceFilter)
592 // Null or empty is analogous to no filter.
593 if (interfaceFilter == NULL || *interfaceFilter == 0)
598 OCResourceInterface *interfacePtr = resource->rsrcInterface;
602 if ((strcmp (interfacePtr->name, interfaceFilter) == 0) &&
603 (strcmp (OC_RSRVD_INTERFACE_LL, interfaceFilter) == 0 ||
604 strcmp (OC_RSRVD_INTERFACE_DEFAULT, interfaceFilter) == 0))
608 interfacePtr = interfacePtr->next;
611 OIC_LOG_V(INFO, TAG, "%s does not contain if=%s.", resource->uri, interfaceFilter);
616 * If the filters are null, they will be assumed to NOT be present
617 * and the resource will not be matched against them.
618 * Function will return true if all non null AND non empty filters passed in find a match.
620 static bool includeThisResourceInResponse(OCResource *resource,
621 char *interfaceFilter,
622 char *resourceTypeFilter)
626 OIC_LOG(ERROR, TAG, "Invalid resource");
630 if (resource->resourceProperties & OC_EXPLICIT_DISCOVERABLE)
633 * At least one valid filter should be available to
634 * include the resource in discovery response
636 if (!(resourceTypeFilter && *resourceTypeFilter))
638 OIC_LOG_V(INFO, TAG, "%s no query string for EXPLICIT_DISCOVERABLE \
639 resource", resource->uri);
643 else if ( !(resource->resourceProperties & OC_ACTIVE) ||
644 !(resource->resourceProperties & OC_DISCOVERABLE))
646 OIC_LOG_V(INFO, TAG, "%s not ACTIVE or DISCOVERABLE", resource->uri);
650 return resourceMatchesIFFilter(resource, interfaceFilter) &&
651 resourceMatchesRTFilter(resource, resourceTypeFilter);
655 OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCResource *resource,
656 OCPayload *discoveryPayload, OCEntityHandlerResult ehResult)
658 OCEntityHandlerResponse response = {0};
660 response.ehResult = ehResult;
661 response.payload = discoveryPayload;
662 response.persistentBufferFlag = 0;
663 response.requestHandle = (OCRequestHandle) request;
664 response.resourceHandle = (OCResourceHandle) resource;
666 return OCDoResponse(&response);
669 static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource)
671 if (!request || !resource)
673 return OC_STACK_INVALID_PARAM;
676 OCStackResult discoveryResult = OC_STACK_ERROR;
677 OCPayload* payload = NULL;
679 OIC_LOG(INFO, TAG, "Entering HandleVirtualResource");
681 OCVirtualResources virtualUriInRequest = GetTypeOfVirtualURI (request->resourceUrl);
683 // Step 1: Generate the response to discovery request
684 if (virtualUriInRequest == OC_WELL_KNOWN_URI
686 || virtualUriInRequest == OC_MQ_BROKER_URI
690 if (request->method == OC_REST_PUT || request->method == OC_REST_POST || request->method == OC_REST_DELETE)
692 OIC_LOG_V(ERROR, TAG, "Resource : %s not permitted for method: %d", request->resourceUrl, request->method);
693 return OC_STACK_UNAUTHORIZED_REQ;
696 char *interfaceQuery = NULL;
697 char *resourceTypeQuery = NULL;
699 discoveryResult = getQueryParamsForFiltering (virtualUriInRequest, request->query,
700 &interfaceQuery, &resourceTypeQuery);
701 if (!interfaceQuery && !resourceTypeQuery)
703 interfaceQuery = OICStrdup(OC_RSRVD_INTERFACE_LL);
706 if (discoveryResult == OC_STACK_OK)
708 payload = (OCPayload *)OCDiscoveryPayloadCreate();
712 OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)payload;
713 bool foundResourceAtRD = false;
715 if (!resourceTypeQuery && interfaceQuery && (0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_LL)))
717 OCResourceProperty prop = OC_DISCOVERABLE;
719 if (OC_MQ_BROKER_URI == virtualUriInRequest)
725 for (; resource && discoveryResult == OC_STACK_OK; resource = resource->next)
727 foundResourceAtRD = false;
729 if (strcmp(resource->uri, OC_RSRVD_RD_URI) == 0)
731 if (OC_STACK_OK == OCRDDatabaseCheckResources(interfaceQuery, resourceTypeQuery, discPayload))
733 foundResourceAtRD = true;
734 discoveryResult = OC_STACK_OK;
738 if (!foundResourceAtRD && (resource->resourceProperties & prop))
740 discoveryResult = BuildVirtualResourceResponse(resource, discPayload, &request->devAddr);
746 if (interfaceQuery && (0 != strcmp(interfaceQuery, OC_RSRVD_INTERFACE_LL)))
748 discPayload->uri = OICStrdup(OC_RSRVD_WELL_KNOWN_URI);
749 VERIFY_NON_NULL(discPayload->uri, ERROR, OC_STACK_NO_MEMORY);
750 if (savedDeviceInfo.deviceName)
752 discPayload->name = OICStrdup(savedDeviceInfo.deviceName);
753 VERIFY_NON_NULL(discPayload->name, ERROR, OC_STACK_NO_MEMORY);
755 discPayload->type = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
756 VERIFY_NON_NULL(discPayload->type, ERROR, OC_STACK_NO_MEMORY);
757 discPayload->type->value = OICStrdup(OC_RSRVD_RESOURCE_TYPE_RES);
758 VERIFY_NON_NULL(discPayload->type->value, ERROR, OC_STACK_NO_MEMORY);
759 OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_LL);
760 OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_DEFAULT);
761 VERIFY_NON_NULL(discPayload->iface, ERROR, OC_STACK_NO_MEMORY);
763 for (;resource && discoveryResult == OC_STACK_OK; resource = resource->next)
766 if (strcmp(resource->uri, OC_RSRVD_RD_URI) == 0)
768 if (OC_STACK_OK == OCRDDatabaseCheckResources(interfaceQuery, resourceTypeQuery, discPayload))
770 foundResourceAtRD = true;
771 discoveryResult = OC_STACK_OK;
775 if (!foundResourceAtRD && includeThisResourceInResponse(resource, interfaceQuery, resourceTypeQuery))
777 discoveryResult = BuildVirtualResourceResponse(resource, discPayload, &request->devAddr);
780 // Set discoveryResult appropriately if no 'valid' resources are available
781 if (discPayload->resources == NULL && !foundResourceAtRD)
783 discoveryResult = OC_STACK_NO_RESOURCE;
786 if (discoveryResult == OC_STACK_OK && foundResourceAtRD == false)
788 discPayload->sid = (char *)OICCalloc(1, UUID_STRING_SIZE);
789 VERIFY_NON_NULL(discPayload->sid, ERROR, OC_STACK_NO_MEMORY);
791 const char* uid = OCGetServerInstanceIDString();
794 memcpy(discPayload->sid, uid, UUID_STRING_SIZE);
800 discoveryResult = OC_STACK_NO_MEMORY;
806 OIC_LOG_V(ERROR, TAG, "Error (%d) parsing query.", discoveryResult);
811 OICFree(interfaceQuery);
814 if (resourceTypeQuery)
816 OICFree(resourceTypeQuery);
819 else if (virtualUriInRequest == OC_DEVICE_URI)
821 if (request->method == OC_REST_PUT || request->method == OC_REST_POST || request->method == OC_REST_DELETE)
823 OIC_LOG_V(ERROR, TAG, "Resource : %s not permitted for method: %d", request->resourceUrl, request->method);
824 return OC_STACK_UNAUTHORIZED_REQ;
827 const char* deviceId = OCGetServerInstanceIDString();
830 discoveryResult = OC_STACK_ERROR;
834 char *dataModelVersions = OCCreateString(savedDeviceInfo.dataModelVersions);
835 if (!dataModelVersions)
837 discoveryResult = OC_STACK_NO_MEMORY;
841 payload = (OCPayload*) OCDevicePayloadCreate(deviceId, savedDeviceInfo.deviceName,
842 savedDeviceInfo.types, savedDeviceInfo.specVersion, dataModelVersions);
845 discoveryResult = OC_STACK_NO_MEMORY;
849 discoveryResult = OC_STACK_OK;
851 OICFree(dataModelVersions);
855 else if (virtualUriInRequest == OC_PLATFORM_URI)
857 if (request->method == OC_REST_PUT || request->method == OC_REST_POST || request->method == OC_REST_DELETE)
859 OIC_LOG_V(ERROR, TAG, "Resource : %s not permitted for method: %d", request->resourceUrl, request->method);
860 return OC_STACK_UNAUTHORIZED_REQ;
863 payload = (OCPayload*)OCPlatformPayloadCreate(&savedPlatformInfo);
866 discoveryResult = OC_STACK_NO_MEMORY;
870 discoveryResult = OC_STACK_OK;
873 #ifdef ROUTING_GATEWAY
874 else if (OC_GATEWAY_URI == virtualUriInRequest)
876 // Received request for a gateway
877 OIC_LOG(INFO, TAG, "Request is for Gateway Virtual Request");
878 discoveryResult = RMHandleGatewayRequest(request, resource);
883 else if (OC_KEEPALIVE_RESOURCE_URI == virtualUriInRequest)
885 // Received request for a keepalive
886 OIC_LOG(INFO, TAG, "Request is for KeepAlive Request");
887 discoveryResult = HandleKeepAliveRequest(request, resource);
891 * Step 2: Send the discovery response
893 * Iotivity should respond to discovery requests in below manner:
894 * 1)If query filter matching fails and discovery request is multicast,
895 * it should NOT send any response.
896 * 2)If query filter matching fails and discovery request is unicast,
897 * it should send an error(RESOURCE_NOT_FOUND - 404) response.
898 * 3)If Server does not have any 'DISCOVERABLE' resources and discovery
899 * request is multicast, it should NOT send any response.
900 * 4)If Server does not have any 'DISCOVERABLE' resources and discovery
901 * request is unicast, it should send an error(RESOURCE_NOT_FOUND - 404) response.
905 if ((virtualUriInRequest == OC_PRESENCE) &&
906 (resource->resourceProperties & OC_ACTIVE))
908 // Need to send ACK when the request is CON.
909 if (request->qos == OC_HIGH_QOS)
911 CAEndpoint_t endpoint = { .adapter = CA_DEFAULT_ADAPTER };
912 CopyDevAddrToEndpoint(&request->devAddr, &endpoint);
913 SendDirectStackResponse(&endpoint, request->coapID, CA_EMPTY, CA_MSG_ACKNOWLEDGE,
914 0, NULL, NULL, 0, NULL, CA_RESPONSE_FOR_RES);
916 FindAndDeleteServerRequest(request);
918 // Presence uses observer notification api to respond via SendPresenceNotification.
919 SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
924 // Gateway uses the RMHandleGatewayRequest to respond to the request.
925 if (OC_GATEWAY_URI != virtualUriInRequest)
929 // KeepAlive uses the HandleKeepAliveRequest to respond to the request.
930 if (OC_KEEPALIVE_RESOURCE_URI != virtualUriInRequest)
933 if(discoveryResult == OC_STACK_OK)
935 SendNonPersistantDiscoveryResponse(request, resource, payload, OC_EH_OK);
937 else if(((request->devAddr.flags & OC_MULTICAST) == false) &&
938 (request->devAddr.adapter != OC_ADAPTER_RFCOMM_BTEDR) &&
939 (request->devAddr.adapter != OC_ADAPTER_GATT_BTLE))
941 OIC_LOG_V(ERROR, TAG, "Sending a (%d) error to (%d) discovery request",
942 discoveryResult, virtualUriInRequest);
943 SendNonPersistantDiscoveryResponse(request, resource, NULL,
944 (discoveryResult == OC_STACK_NO_RESOURCE) ?
945 OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR);
949 // Ignoring the discovery request as per RFC 7252, Section #8.2
950 OIC_LOG(INFO, TAG, "Silently ignoring the request since no useful data to send.");
951 // the request should be removed.
952 // since it never remove and causes a big memory waste.
953 FindAndDeleteServerRequest(request);
958 OCPayloadDestroy(payload);
964 HandleDefaultDeviceEntityHandler (OCServerRequest *request)
968 return OC_STACK_INVALID_PARAM;
971 OCStackResult result = OC_STACK_OK;
972 OCEntityHandlerResult ehResult = OC_EH_ERROR;
973 OCEntityHandlerRequest ehRequest = {0};
975 OIC_LOG(INFO, TAG, "Entering HandleResourceWithDefaultDeviceEntityHandler");
976 result = FormOCEntityHandlerRequest(&ehRequest,
977 (OCRequestHandle) request,
980 (OCResourceHandle) NULL, request->query,
981 PAYLOAD_TYPE_REPRESENTATION,
983 request->payloadSize,
984 request->numRcvdVendorSpecificHeaderOptions,
985 request->rcvdVendorSpecificHeaderOptions,
986 (OCObserveAction)request->observationOption,
989 VERIFY_SUCCESS(result, OC_STACK_OK);
991 // At this point we know for sure that defaultDeviceHandler exists
992 ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
993 (char*) request->resourceUrl, defaultDeviceHandlerCallbackParameter);
994 if(ehResult == OC_EH_SLOW)
996 OIC_LOG(INFO, TAG, "This is a slow resource");
997 request->slowFlag = 1;
999 else if(ehResult == OC_EH_ERROR)
1001 FindAndDeleteServerRequest(request);
1003 result = EntityHandlerCodeToOCStackCode(ehResult);
1005 OCPayloadDestroy(ehRequest.payload);
1009 static OCStackResult
1010 HandleResourceWithEntityHandler (OCServerRequest *request,
1011 OCResource *resource,
1012 uint8_t collectionResource)
1014 OC_UNUSED(collectionResource);
1016 if(!request || ! resource)
1018 return OC_STACK_INVALID_PARAM;
1021 OCStackResult result = OC_STACK_ERROR;
1022 OCEntityHandlerResult ehResult = OC_EH_ERROR;
1023 OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
1024 ResourceObserver *resObs = NULL;
1026 OCEntityHandlerRequest ehRequest = {0};
1028 OIC_LOG(INFO, TAG, "Entering HandleResourceWithEntityHandler");
1029 OCPayloadType type = PAYLOAD_TYPE_REPRESENTATION;
1030 // check the security resource
1031 if (request && request->resourceUrl && SRMIsSecurityResourceURI(request->resourceUrl))
1033 type = PAYLOAD_TYPE_SECURITY;
1037 result = FormOCEntityHandlerRequest(&ehRequest,
1038 (OCRequestHandle)request,
1041 (OCResourceHandle)resource,
1045 request->payloadSize,
1046 request->numRcvdVendorSpecificHeaderOptions,
1047 request->rcvdVendorSpecificHeaderOptions,
1048 (OCObserveAction)request->observationOption,
1051 VERIFY_SUCCESS(result, OC_STACK_OK);
1053 if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
1055 OIC_LOG(INFO, TAG, "No observation requested");
1056 ehFlag = OC_REQUEST_FLAG;
1058 else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER)
1060 OIC_LOG(INFO, TAG, "Observation registration requested");
1062 ResourceObserver *obs = GetObserverUsingToken (request->requestToken,
1063 request->tokenLength);
1067 OIC_LOG (INFO, TAG, "Observer with this token already present");
1068 OIC_LOG (INFO, TAG, "Possibly re-transmitted CON OBS request");
1069 OIC_LOG (INFO, TAG, "Not adding observer. Not responding to client");
1070 OIC_LOG (INFO, TAG, "The first request for this token is already ACKED.");
1072 // server requests are usually free'd when the response is sent out
1073 // for the request in ocserverrequest.c : HandleSingleResponse()
1074 // Since we are making an early return and not responding, the server request
1075 // needs to be deleted.
1076 FindAndDeleteServerRequest (request);
1080 result = GenerateObserverId(&ehRequest.obsInfo.obsId);
1081 VERIFY_SUCCESS(result, OC_STACK_OK);
1083 result = AddObserver ((const char*)(request->resourceUrl),
1084 (const char *)(request->query),
1085 ehRequest.obsInfo.obsId, request->requestToken, request->tokenLength,
1086 resource, request->qos, request->acceptFormat,
1089 if(result == OC_STACK_OK)
1091 OIC_LOG(INFO, TAG, "Added observer successfully");
1092 request->observeResult = OC_STACK_OK;
1093 ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
1095 else if (result == OC_STACK_RESOURCE_ERROR)
1097 OIC_LOG(INFO, TAG, "The Resource is not active, discoverable or observable");
1098 request->observeResult = OC_STACK_ERROR;
1099 ehFlag = OC_REQUEST_FLAG;
1103 // The error in observeResult for the request will be used when responding to this
1104 // request by omitting the observation option/sequence number.
1105 request->observeResult = OC_STACK_ERROR;
1106 OIC_LOG(ERROR, TAG, "Observer Addition failed");
1107 ehFlag = OC_REQUEST_FLAG;
1108 FindAndDeleteServerRequest(request);
1113 else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER)
1115 OIC_LOG(INFO, TAG, "Deregistering observation requested");
1117 resObs = GetObserverUsingToken (request->requestToken, request->tokenLength);
1121 // Stack does not contain this observation request
1122 // Either token is incorrect or observation list is corrupted
1123 result = OC_STACK_ERROR;
1126 ehRequest.obsInfo.obsId = resObs->observeId;
1127 ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
1129 result = DeleteObserverUsingToken (request->requestToken, request->tokenLength);
1131 if(result == OC_STACK_OK)
1133 OIC_LOG(INFO, TAG, "Removed observer successfully");
1134 request->observeResult = OC_STACK_OK;
1135 // There should be no observe option header for de-registration response.
1136 // Set as an invalid value here so we can detect it later and remove the field in response.
1137 request->observationOption = MAX_SEQUENCE_NUMBER + 1;
1141 request->observeResult = OC_STACK_ERROR;
1142 OIC_LOG(ERROR, TAG, "Observer Removal failed");
1143 FindAndDeleteServerRequest(request);
1149 result = OC_STACK_ERROR;
1153 ehResult = resource->entityHandler(ehFlag, &ehRequest, resource->entityHandlerCallbackParam);
1154 if(ehResult == OC_EH_SLOW)
1156 OIC_LOG(INFO, TAG, "This is a slow resource");
1157 request->slowFlag = 1;
1159 else if(ehResult == OC_EH_ERROR)
1161 FindAndDeleteServerRequest(request);
1163 result = EntityHandlerCodeToOCStackCode(ehResult);
1165 OCPayloadDestroy(ehRequest.payload);
1169 static OCStackResult
1170 HandleCollectionResourceDefaultEntityHandler (OCServerRequest *request,
1171 OCResource *resource)
1173 if(!request || !resource)
1175 return OC_STACK_INVALID_PARAM;
1178 OCStackResult result = OC_STACK_ERROR;
1179 OCEntityHandlerRequest ehRequest = {0};
1181 result = FormOCEntityHandlerRequest(&ehRequest,
1182 (OCRequestHandle)request,
1185 (OCResourceHandle)resource,
1187 PAYLOAD_TYPE_REPRESENTATION,
1189 request->payloadSize,
1190 request->numRcvdVendorSpecificHeaderOptions,
1191 request->rcvdVendorSpecificHeaderOptions,
1192 (OCObserveAction)request->observationOption,
1195 if(result == OC_STACK_OK)
1197 result = DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest);
1200 OCPayloadDestroy(ehRequest.payload);
1205 ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request)
1207 OCStackResult ret = OC_STACK_OK;
1209 switch (resHandling)
1211 case OC_RESOURCE_VIRTUAL:
1213 ret = HandleVirtualResource (request, resource);
1216 case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER:
1218 ret = HandleDefaultDeviceEntityHandler(request);
1221 case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
1223 OIC_LOG(INFO, TAG, "OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER");
1224 return OC_STACK_ERROR;
1226 case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
1228 ret = HandleResourceWithEntityHandler (request, resource, 0);
1231 case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
1233 ret = HandleResourceWithEntityHandler (request, resource, 1);
1236 case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
1238 ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
1241 case OC_RESOURCE_NOT_SPECIFIED:
1243 ret = OC_STACK_NO_RESOURCE;
1248 OIC_LOG(INFO, TAG, "Invalid Resource Determination");
1249 return OC_STACK_ERROR;
1255 void DeletePlatformInfo()
1257 OIC_LOG(INFO, TAG, "Deleting platform info.");
1259 OICFree(savedPlatformInfo.platformID);
1260 savedPlatformInfo.platformID = NULL;
1262 OICFree(savedPlatformInfo.manufacturerName);
1263 savedPlatformInfo.manufacturerName = NULL;
1265 OICFree(savedPlatformInfo.manufacturerUrl);
1266 savedPlatformInfo.manufacturerUrl = NULL;
1268 OICFree(savedPlatformInfo.modelNumber);
1269 savedPlatformInfo.modelNumber = NULL;
1271 OICFree(savedPlatformInfo.dateOfManufacture);
1272 savedPlatformInfo.dateOfManufacture = NULL;
1274 OICFree(savedPlatformInfo.platformVersion);
1275 savedPlatformInfo.platformVersion = NULL;
1277 OICFree(savedPlatformInfo.operatingSystemVersion);
1278 savedPlatformInfo.operatingSystemVersion = NULL;
1280 OICFree(savedPlatformInfo.hardwareVersion);
1281 savedPlatformInfo.hardwareVersion = NULL;
1283 OICFree(savedPlatformInfo.firmwareVersion);
1284 savedPlatformInfo.firmwareVersion = NULL;
1286 OICFree(savedPlatformInfo.supportUrl);
1287 savedPlatformInfo.supportUrl = NULL;
1289 OICFree(savedPlatformInfo.systemTime);
1290 savedPlatformInfo.systemTime = NULL;
1293 static OCStackResult DeepCopyPlatFormInfo(OCPlatformInfo info)
1295 savedPlatformInfo.platformID = OICStrdup(info.platformID);
1296 savedPlatformInfo.manufacturerName = OICStrdup(info.manufacturerName);
1297 savedPlatformInfo.manufacturerUrl = OICStrdup(info.manufacturerUrl);
1298 savedPlatformInfo.modelNumber = OICStrdup(info.modelNumber);
1299 savedPlatformInfo.dateOfManufacture = OICStrdup(info.dateOfManufacture);
1300 savedPlatformInfo.platformVersion = OICStrdup(info.platformVersion);
1301 savedPlatformInfo.operatingSystemVersion = OICStrdup(info.operatingSystemVersion);
1302 savedPlatformInfo.hardwareVersion = OICStrdup(info.hardwareVersion);
1303 savedPlatformInfo.firmwareVersion = OICStrdup(info.firmwareVersion);
1304 savedPlatformInfo.supportUrl = OICStrdup(info.supportUrl);
1305 savedPlatformInfo.systemTime = OICStrdup(info.systemTime);
1307 if ((!savedPlatformInfo.platformID && info.platformID)||
1308 (!savedPlatformInfo.manufacturerName && info.manufacturerName)||
1309 (!savedPlatformInfo.manufacturerUrl && info.manufacturerUrl)||
1310 (!savedPlatformInfo.modelNumber && info.modelNumber)||
1311 (!savedPlatformInfo.dateOfManufacture && info.dateOfManufacture)||
1312 (!savedPlatformInfo.platformVersion && info.platformVersion)||
1313 (!savedPlatformInfo.operatingSystemVersion && info.operatingSystemVersion)||
1314 (!savedPlatformInfo.hardwareVersion && info.hardwareVersion)||
1315 (!savedPlatformInfo.firmwareVersion && info.firmwareVersion)||
1316 (!savedPlatformInfo.supportUrl && info.supportUrl)||
1317 (!savedPlatformInfo.systemTime && info.systemTime))
1319 DeletePlatformInfo();
1320 return OC_STACK_INVALID_PARAM;
1327 OCStackResult SavePlatformInfo(OCPlatformInfo info)
1329 DeletePlatformInfo();
1331 OCStackResult res = DeepCopyPlatFormInfo(info);
1333 if (res != OC_STACK_OK)
1335 OIC_LOG_V(ERROR, TAG, "Failed to save platform info. errno(%d)", res);
1339 OIC_LOG(INFO, TAG, "Platform info saved.");
1345 void DeleteDeviceInfo()
1347 OIC_LOG(INFO, TAG, "Deleting device info.");
1349 OICFree(savedDeviceInfo.deviceName);
1350 OCFreeOCStringLL(savedDeviceInfo.types);
1351 OICFree(savedDeviceInfo.specVersion);
1352 OCFreeOCStringLL(savedDeviceInfo.dataModelVersions);
1353 savedDeviceInfo.deviceName = NULL;
1354 savedDeviceInfo.specVersion = NULL;
1355 savedDeviceInfo.dataModelVersions = NULL;
1358 static OCStackResult DeepCopyDeviceInfo(OCDeviceInfo info)
1360 savedDeviceInfo.deviceName = OICStrdup(info.deviceName);
1362 if(!savedDeviceInfo.deviceName && info.deviceName)
1365 return OC_STACK_NO_MEMORY;
1370 savedDeviceInfo.types = CloneOCStringLL(info.types);
1371 OCStringLL *type = info.types;
1375 if (type && type->value && 0 == strcmp(type->value, OC_RSRVD_RESOURCE_TYPE_DEVICE))
1383 // Append the oic.wk.d at the start of rt link parameter value.
1384 OCStringLL *dest = (OCStringLL*)OICCalloc (1, sizeof (OCStringLL));
1388 return OC_STACK_NO_MEMORY;
1390 dest->value = OICStrdup (OC_RSRVD_RESOURCE_TYPE_DEVICE);
1394 return OC_STACK_NO_MEMORY;
1396 dest->next = savedDeviceInfo.types;
1397 savedDeviceInfo.types = dest;
1399 if(!savedDeviceInfo.types && info.types)
1402 return OC_STACK_NO_MEMORY;
1406 if (info.specVersion)
1408 savedDeviceInfo.specVersion = OICStrdup(info.specVersion);
1409 if(!savedDeviceInfo.specVersion && info.specVersion)
1412 return OC_STACK_NO_MEMORY;
1417 savedDeviceInfo.specVersion = OICStrdup(OC_SPEC_VERSION);
1418 if(!savedDeviceInfo.specVersion && OC_SPEC_VERSION)
1421 return OC_STACK_NO_MEMORY;
1425 if (info.dataModelVersions)
1427 savedDeviceInfo.dataModelVersions = CloneOCStringLL(info.dataModelVersions);
1428 if(!savedDeviceInfo.dataModelVersions && info.dataModelVersions)
1431 return OC_STACK_NO_MEMORY;
1436 savedDeviceInfo.dataModelVersions = (OCStringLL *)OICCalloc(1,sizeof(OCStringLL));
1437 if (!savedDeviceInfo.dataModelVersions)
1439 return OC_STACK_NO_MEMORY;
1441 savedDeviceInfo.dataModelVersions->value = OICStrdup(OC_DATA_MODEL_VERSION);
1442 if(!savedDeviceInfo.dataModelVersions->value && OC_DATA_MODEL_VERSION)
1445 return OC_STACK_NO_MEMORY;
1452 OCStackResult SaveDeviceInfo(OCDeviceInfo info)
1454 OCStackResult res = OC_STACK_OK;
1458 res = DeepCopyDeviceInfo(info);
1460 VERIFY_SUCCESS(res, OC_STACK_OK);
1462 if (OCGetServerInstanceIDString() == NULL)
1464 OIC_LOG(INFO, TAG, "Device ID generation failed");
1465 res = OC_STACK_ERROR;
1469 OIC_LOG(INFO, TAG, "Device initialized successfully.");