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
28 #include "ocresource.h"
30 #include "ocresourcehandler.h"
31 #include "ocobserve.h"
32 #include "occollection.h"
33 #include "oic_malloc.h"
34 #include "oic_string.h"
39 #include "cainterface.h"
43 #define TAG PCF("ocresource")
44 #define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
45 {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
47 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
48 TAG, PCF(#arg " is NULL")); return (retVal); } }
50 extern OCResource *headResource;
51 static OCPlatformInfo savedPlatformInfo = {};
52 static OCDeviceInfo savedDeviceInfo = {};
54 static const char * VIRTUAL_RSRCS[] =
65 //-----------------------------------------------------------------------------
66 // Default resource entity handler function
67 //-----------------------------------------------------------------------------
68 OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag,
69 OCEntityHandlerRequest * request, void* callbackParam)
71 //TODO ("Implement me!!!!");
72 // TODO: remove silence unused param warnings
76 return OC_EH_OK; // Making sure that the Default EH and the Vendor EH have matching signatures
79 /* This method will retrieve the port at which the secure resource is hosted */
80 static OCStackResult GetSecurePortInfo(CATransportAdapter_t connType, uint16_t *port)
82 CAEndpoint_t* info = NULL;
84 OCStackResult ret = OC_STACK_ERROR;
86 CAResult_t caResult = CAGetNetworkInformation(&info, &size);
87 if ((caResult == CA_STATUS_OK) && info && size)
91 if ((info[size].flags & CA_SECURE) && info[size].adapter == connType)
93 if (info[size].adapter == CA_ADAPTER_IP)
95 *port = info[size].port;
108 * Encodes platform info into json and returns a string on the heap.
109 * Caller responsible for freeing the string.
111 static char* GetJSONStringFromPlatformInfo(OCPlatformInfo info)
113 cJSON *rootObj = cJSON_CreateObject();
120 cJSON *repObj = NULL;
121 char *jsonEncodedInfo = NULL;
123 cJSON_AddItemToObject (rootObj, OC_RSRVD_HREF,
124 cJSON_CreateString(GetVirtualResourceUri(OC_PLATFORM_URI)));
126 cJSON_AddItemToObject (rootObj, OC_RSRVD_REPRESENTATION, repObj = cJSON_CreateObject());
134 cJSON_AddItemToObject (repObj, OC_RSRVD_PLATFORM_ID,
135 cJSON_CreateString(info.platformID));
138 if (info.manufacturerName)
140 cJSON_AddItemToObject (repObj, OC_RSRVD_MFG_NAME,
141 cJSON_CreateString(info.manufacturerName));
144 if (info.manufacturerUrl)
146 cJSON_AddItemToObject (repObj, OC_RSRVD_MFG_URL,
147 cJSON_CreateString(info.manufacturerUrl));
150 if (info.modelNumber)
152 cJSON_AddItemToObject (repObj, OC_RSRVD_MODEL_NUM,
153 cJSON_CreateString(info.modelNumber));
156 if (info.dateOfManufacture)
158 cJSON_AddItemToObject (repObj, OC_RSRVD_MFG_DATE,
159 cJSON_CreateString(info.dateOfManufacture));
162 if (info.platformVersion)
164 cJSON_AddItemToObject (repObj, OC_RSRVD_PLATFORM_VERSION,
165 cJSON_CreateString(info.platformVersion));
168 if (info.operatingSystemVersion)
170 cJSON_AddItemToObject (repObj, OC_RSRVD_OS_VERSION,
171 cJSON_CreateString(info.operatingSystemVersion));
174 if (info.hardwareVersion)
176 cJSON_AddItemToObject (repObj, OC_RSRVD_HARDWARE_VERSION,
177 cJSON_CreateString(info.hardwareVersion));
180 if (info.firmwareVersion)
182 cJSON_AddItemToObject (repObj, OC_RSRVD_FIRMWARE_VERSION,
183 cJSON_CreateString(info.firmwareVersion));
188 cJSON_AddItemToObject (repObj, OC_RSRVD_SUPPORT_URL,
189 cJSON_CreateString(info.supportUrl));
194 cJSON_AddItemToObject (repObj, OC_RSRVD_SYSTEM_TIME,
195 cJSON_CreateString(info.systemTime));
198 jsonEncodedInfo = cJSON_PrintUnformatted (rootObj);
200 cJSON_Delete(rootObj);
202 return jsonEncodedInfo;
206 * Encodes device info into json and returns a string on the heap.
207 * Caller responsible for freeing the string.
209 static char* GetJSONStringFromDeviceInfo(OCDeviceInfo info)
211 cJSON *rootObj = cJSON_CreateObject();
218 cJSON *repObj = NULL;
219 char *jsonEncodedInfo = NULL;
221 cJSON_AddItemToObject (rootObj, OC_RSRVD_HREF,
222 cJSON_CreateString(GetVirtualResourceUri(OC_DEVICE_URI)));
224 cJSON_AddItemToObject (rootObj, OC_RSRVD_REPRESENTATION, repObj = cJSON_CreateObject());
231 cJSON_AddItemToObject (repObj, OC_RSRVD_DEVICE_ID,
232 cJSON_CreateString(OCGetServerInstanceIDString()));
236 cJSON_AddItemToObject (repObj, OC_RSRVD_DEVICE_NAME,
237 cJSON_CreateString(info.deviceName));
240 cJSON_AddItemToObject (repObj, OC_RSRVD_SPEC_VERSION,
241 cJSON_CreateString(OC_SPEC_VERSION));
243 cJSON_AddItemToObject (repObj, OC_RSRVD_DATA_MODEL_VERSION,
244 cJSON_CreateString(OC_DATA_MODEL_VERSION));
246 jsonEncodedInfo = cJSON_PrintUnformatted (rootObj);
248 cJSON_Delete(rootObj);
250 return jsonEncodedInfo;
254 * Function will extract 0, 1 or 2 filters from query.
255 * More than 2 filters or unsupported filters will result in error.
256 * If both filters are of the same supported type, the 2nd one will be picked.
257 * Resource and device filters in the SAME query are NOT validated
258 * and resources will likely not clear filters.
260 static OCStackResult ExtractFiltersFromQuery(char *query, char **filterOne, char **filterTwo)
265 char *restOfQuery = NULL;
266 int numKeyValuePairsParsed = 0;
271 OC_LOG_V(INFO, TAG, PCF("Received query %s for param extraction"), query);
273 char *keyValuePair = strtok_r (query, OC_QUERY_SEPARATOR, &restOfQuery);
277 if (numKeyValuePairsParsed >= 2)
279 OC_LOG(ERROR, TAG, PCF("More than 2 queries params in URI."));
280 return OC_STACK_INVALID_QUERY;
283 key = strtok_r(keyValuePair, OC_KEY_VALUE_DELIMITER, &value);
287 return OC_STACK_INVALID_QUERY;
289 else if (strcmp (key, OC_RSRVD_INTERFACE) == 0)
291 *filterOne = value; // if
293 else if (strcmp (key, OC_RSRVD_RESOURCE_TYPE) == 0)
295 *filterTwo = value; // rt
299 OC_LOG_V(ERROR, TAG, "Unsupported query key: %s", key);
300 return OC_STACK_INVALID_QUERY;
302 ++numKeyValuePairsParsed;
304 keyValuePair = strtok_r(NULL, OC_QUERY_SEPARATOR, &restOfQuery);
307 OC_LOG_V(INFO, TAG, "Extracted params %s and %s.", *filterOne, *filterTwo);
311 static OCVirtualResources GetTypeOfVirtualURI(char *uriInRequest)
313 if (strcmp (uriInRequest, GetVirtualResourceUri(OC_WELL_KNOWN_URI)) == 0)
315 return OC_WELL_KNOWN_URI;
317 else if (strcmp (uriInRequest, GetVirtualResourceUri(OC_DEVICE_URI)) == 0)
319 return OC_DEVICE_URI;
321 else if (strcmp (uriInRequest, GetVirtualResourceUri(OC_PLATFORM_URI)) == 0)
323 return OC_PLATFORM_URI;
334 static OCStackResult getQueryParamsForFiltering (OCVirtualResources uri, char *query,
335 char **filterOne, char **filterTwo)
337 if(!filterOne || !filterTwo)
339 return OC_STACK_INVALID_PARAM;
346 if (uri == OC_PRESENCE)
348 //Nothing needs to be done, except for pass a OC_PRESENCE query through as OC_STACK_OK.
349 OC_LOG(INFO, TAG, PCF("OC_PRESENCE Request for virtual resource."));
354 OCStackResult result = OC_STACK_OK;
358 result = ExtractFiltersFromQuery(query, filterOne, filterTwo);
364 OCStackResult copyStringIfEnoughSpace(char* dest, const char *src, uint16_t *remaining)
366 if (!dest || !src || !remaining)
368 return OC_STACK_INVALID_PARAM;
371 size_t srcLen = strlen(src);
373 if (srcLen < *remaining)
375 OICStrcpy(dest, *remaining, src);
376 *remaining = *remaining - srcLen;
381 return OC_STACK_ERROR;
385 OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr, char *out,
386 uint16_t *remaining, CATransportAdapter_t adapter )
388 if(!resourcePtr || !out || !remaining)
390 return OC_STACK_INVALID_PARAM;
393 OCResourceType *resourceTypePtr = NULL;
394 OCResourceInterface *interfacePtr = NULL;
395 cJSON *resObj = NULL;
396 cJSON *policyObj = NULL;
397 cJSON *rtArray = NULL;
398 char *jsonStr = NULL;
399 OCStackResult ret = OC_STACK_OK;
401 OC_LOG_V(INFO, TAG, PCF("Encoding resource %s"), resourcePtr->uri);
403 resObj = cJSON_CreateObject();
408 cJSON_AddItemToObject (resObj, OC_RSRVD_HREF, cJSON_CreateString(resourcePtr->uri));
411 cJSON_AddItemToObject (resObj, OC_RSRVD_RESOURCE_TYPE, rtArray = cJSON_CreateArray());
412 resourceTypePtr = resourcePtr->rsrcType;
413 while (resourceTypePtr)
415 cJSON_AddItemToArray (rtArray,
416 cJSON_CreateString(resourceTypePtr->resourcetypename));
417 resourceTypePtr = resourceTypePtr->next;
420 cJSON_AddItemToObject (resObj, OC_RSRVD_INTERFACE, rtArray = cJSON_CreateArray());
421 interfacePtr = resourcePtr->rsrcInterface;
424 cJSON_AddItemToArray (rtArray, cJSON_CreateString(interfacePtr->name));
425 interfacePtr = interfacePtr->next;
429 cJSON_AddItemToObject (resObj, OC_RSRVD_POLICY, policyObj = cJSON_CreateObject());
433 cJSON_AddNumberToObject (policyObj, OC_RSRVD_BITMAP,
434 resourcePtr->resourceProperties & (OC_OBSERVABLE|OC_DISCOVERABLE));
435 // Set secure flag for secure resources
436 if (resourcePtr->resourceProperties & OC_SECURE)
438 cJSON_AddNumberToObject(policyObj, OC_RSRVD_SECURE, OC_RESOURCE_SECURE);
439 //Set the IP port also as secure resources are hosted on a different port
441 if (GetSecurePortInfo(adapter, &port) == OC_STACK_OK)
443 cJSON_AddNumberToObject(policyObj, OC_RSRVD_HOSTING_PORT, port);
449 cJSON_Delete(resObj);
450 return OC_STACK_NO_MEMORY;
453 jsonStr = cJSON_PrintUnformatted (resObj);
457 cJSON_Delete(resObj);
458 return OC_STACK_NO_MEMORY;
461 ret = copyStringIfEnoughSpace(out, jsonStr, remaining);
463 cJSON_Delete (resObj);
469 OCStackResult BuildVirtualResourceResponseForDevice(char *out, uint16_t *remaining)
471 if(!out || !remaining)
473 return OC_STACK_INVALID_PARAM;
476 OCStackResult ret = OC_STACK_ERROR;
477 char *jsonStr = NULL;
479 jsonStr = GetJSONStringFromDeviceInfo(savedDeviceInfo);
483 ret = copyStringIfEnoughSpace(out, jsonStr, remaining);
488 OC_LOG(ERROR, TAG, PCF("Error encoding save device info."));
489 ret = OC_STACK_ERROR;
494 OCStackResult BuildVirtualResourceResponseForPlatform(char *out, uint16_t *remaining)
496 if(!out || !remaining)
498 return OC_STACK_INVALID_PARAM;
501 OCStackResult ret = OC_STACK_ERROR;
502 char *jsonStr = NULL;
504 jsonStr = GetJSONStringFromPlatformInfo(savedPlatformInfo);
508 ret = copyStringIfEnoughSpace(out, jsonStr, remaining);
513 OC_LOG(ERROR, TAG, PCF("Error encoding save platform info."));
514 ret = OC_STACK_ERROR;
520 const char * GetVirtualResourceUri( OCVirtualResources resource)
522 if (resource < OC_MAX_VIRTUAL_RESOURCES)
524 return VIRTUAL_RSRCS[resource];
530 bool IsVirtualResource(const char* resourceUri)
537 for (int i = 0; i < OC_MAX_VIRTUAL_RESOURCES; i++)
539 if (strcmp(resourceUri, GetVirtualResourceUri((OCVirtualResources)i)) == 0)
547 uint8_t IsCollectionResource (OCResource *resource)
554 for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
556 if (resource->rsrcResources[i])
564 OCResource *FindResourceByUri(const char* resourceUri)
571 OCResource * pointer = headResource;
574 if (strcmp(resourceUri, pointer->uri) == 0)
578 pointer = pointer->next;
580 OC_LOG(INFO, TAG, PCF("Resource not found"));
585 OCStackResult DetermineResourceHandling (const OCServerRequest *request,
586 ResourceHandling *handling,
587 OCResource **resource)
589 if(!request || !handling || !resource)
591 return OC_STACK_INVALID_PARAM;
594 OC_LOG(INFO, TAG, PCF("Entering DetermineResourceHandling"));
596 const OCDevAddr *devAddr = &request->devAddr;
598 // Check if virtual resource
599 if (IsVirtualResource((const char*)request->resourceUrl))
601 *handling = OC_RESOURCE_VIRTUAL;
602 *resource = headResource;
605 if (strlen((const char*)(request->resourceUrl)) == 0)
607 // Resource URL not specified
608 *handling = OC_RESOURCE_NOT_SPECIFIED;
609 return OC_STACK_NO_RESOURCE;
613 OCResource *resourcePtr = NULL;
614 resourcePtr = FindResourceByUri((const char*)request->resourceUrl);
615 *resource = resourcePtr;
618 if(defaultDeviceHandler)
620 *handling = OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER;
624 // Resource does not exist
625 // and default device handler does not exist
626 *handling = OC_RESOURCE_NOT_SPECIFIED;
627 return OC_STACK_NO_RESOURCE;
630 // secure resource will entertain only authorized requests
631 if ((resourcePtr->resourceProperties & OC_SECURE) && ((devAddr->flags & OC_FLAG_SECURE) == 0))
633 OC_LOG(ERROR, TAG, PCF("Un-authorized request. Ignoring"));
634 return OC_STACK_RESOURCE_ERROR;
637 if (IsCollectionResource (resourcePtr))
639 // Collection resource
640 if (resourcePtr->entityHandler != defaultResourceEHandler)
642 *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER;
647 *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER;
653 // Resource not a collection
654 if (resourcePtr->entityHandler != defaultResourceEHandler)
656 *handling = OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER;
661 *handling = OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER;
668 OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
670 OCStackResult result;
675 result = OC_STACK_OK;
678 result = OC_STACK_SLOW_RESOURCE;
681 result = OC_STACK_ERROR;
683 case OC_EH_FORBIDDEN:
684 result = OC_STACK_RESOURCE_ERROR;
686 case OC_EH_RESOURCE_CREATED:
687 result = OC_STACK_RESOURCE_CREATED;
689 case OC_EH_RESOURCE_DELETED:
690 result = OC_STACK_RESOURCE_DELETED;
692 case OC_EH_RESOURCE_NOT_FOUND:
693 result = OC_STACK_NO_RESOURCE;
696 result = OC_STACK_ERROR;
702 static bool resourceMatchesRTFilter(OCResource *resource, char *resourceTypeFilter)
709 // Null or empty is analogous to no filter.
710 if (resourceTypeFilter == NULL || *resourceTypeFilter == 0)
715 OCResourceType *resourceTypePtr = resource->rsrcType;
717 while (resourceTypePtr)
719 if (strcmp (resourceTypePtr->resourcetypename, resourceTypeFilter) == 0)
723 resourceTypePtr = resourceTypePtr->next;
726 OC_LOG_V(INFO, TAG, PCF("%s does not contain rt=%s."), resource->uri, resourceTypeFilter);
730 static bool resourceMatchesIFFilter(OCResource *resource, char *interfaceFilter)
737 // Null or empty is analogous to no filter.
738 if (interfaceFilter == NULL || *interfaceFilter == 0)
743 OCResourceInterface *interfacePtr = resource->rsrcInterface;
747 if (strcmp (interfacePtr->name, interfaceFilter) == 0)
751 interfacePtr = interfacePtr->next;
754 OC_LOG_V(INFO, TAG, PCF("%s does not contain if=%s."), resource->uri, interfaceFilter);
759 * If the filters are null, they will be assumed to NOT be present
760 * and the resource will not be matched against them.
761 * Function will return true if all non null AND non empty filters passed in find a match.
763 static bool includeThisResourceInResponse(OCResource *resource,
764 char *interfaceFilter,
765 char *resourceTypeFilter)
769 OC_LOG(ERROR, TAG, PCF("Invalid resource"));
773 if ( !(resource->resourceProperties & OC_ACTIVE) ||
774 !(resource->resourceProperties & OC_DISCOVERABLE))
776 OC_LOG_V(INFO, TAG, PCF("%s not ACTIVE or DISCOVERABLE"), resource->uri);
780 return resourceMatchesIFFilter(resource, interfaceFilter) &&
781 resourceMatchesRTFilter(resource, resourceTypeFilter);
785 OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCResource *resource,
786 char *discoveryPayload)
788 OCEntityHandlerResponse response = {};
790 response.ehResult = OC_EH_OK;
791 response.payload = discoveryPayload;
792 response.payloadSize = strlen((const char *)discoveryPayload) + 1;
793 response.persistentBufferFlag = 0;
794 response.requestHandle = (OCRequestHandle) request;
795 response.resourceHandle = (OCResourceHandle) resource;
797 return OCDoResponse(&response);
800 static OCStackResult appendDeviceIDAndOpenLinksArray (char *out, uint16_t *remaining)
802 if (!out || !remaining)
804 return OC_STACK_INVALID_PARAM;
807 const char *deviceID = OCGetServerInstanceIDString();
809 char deviceIDJSONField[MAX_RESPONSE_LENGTH] = {};
811 // Format is : {"di":"UUID","links":[
812 sprintf (deviceIDJSONField, "{\"%s\":\"%s\"%s\"%s\":[", OC_RSRVD_DEVICE_ID, deviceID,
813 OC_JSON_SEPARATOR_STR, OC_RSRVD_LINKS);
815 uint16_t lenDeviceIDJSON = strlen(deviceIDJSONField);
817 if (lenDeviceIDJSON > *remaining)
819 return OC_STACK_ERROR;
823 OICStrcat(out, *remaining, deviceIDJSONField);
824 *remaining -= lenDeviceIDJSON;
830 static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource)
832 if (!request || !resource)
834 return OC_STACK_INVALID_PARAM;
837 OCStackResult discoveryResult = OC_STACK_ERROR;
838 char *filterOne = NULL;
839 char *filterTwo = NULL;
840 uint16_t remaining = 0;
842 char discoveryBuffer[MAX_RESPONSE_LENGTH] = {};
844 OC_LOG(INFO, TAG, PCF("Entering HandleVirtualResource"));
846 OCVirtualResources virtualUriInRequest = GetTypeOfVirtualURI (request->resourceUrl);
848 remaining = MAX_RESPONSE_LENGTH - sizeof ('\0');
850 if (virtualUriInRequest == OC_WELL_KNOWN_URI)
852 discoveryResult = getQueryParamsForFiltering (virtualUriInRequest, request->query,
853 &filterOne, &filterTwo);
854 if (discoveryResult != OC_STACK_OK)
856 OC_LOG_V(ERROR, TAG, "Error (%d) validating query.\n", discoveryResult);
857 return discoveryResult;
859 char *ptrIntoBuffer = discoveryBuffer;
861 discoveryResult = appendDeviceIDAndOpenLinksArray(ptrIntoBuffer, &remaining);
863 while(resource && discoveryResult == OC_STACK_OK)
865 if(includeThisResourceInResponse(resource, filterOne, filterTwo))
867 ptrIntoBuffer += strlen(ptrIntoBuffer);
869 discoveryResult = BuildVirtualResourceResponse(resource, ptrIntoBuffer,
870 &remaining, (CATransportAdapter_t)request->devAddr.adapter);
872 if (discoveryResult != OC_STACK_OK)
874 OC_LOG_V(INFO, TAG, "Error (%d) encoding %s", discoveryResult, resource->uri);
878 ptrIntoBuffer += strlen(ptrIntoBuffer);
879 if (remaining > sizeof(OC_JSON_SEPARATOR))
881 *ptrIntoBuffer = OC_JSON_SEPARATOR;
887 OC_LOG(INFO, TAG, PCF("Out of space in buffer"));
892 resource = resource->next;
895 size_t lenDiscoveryBuff = strlen (discoveryBuffer);
897 // Traling separator replaced with closing of "links" array.
898 // discoveryBuffer guaranteed to be null terminated as "remaining"
899 // accounts for '\0' when initialized.
900 if (lenDiscoveryBuff > 0 && discoveryBuffer[lenDiscoveryBuff - 1] == OC_JSON_SEPARATOR)
902 discoveryBuffer[lenDiscoveryBuff - 1] = ']';
906 // If No trailing separator then close links array anyway.
907 discoveryBuffer[lenDiscoveryBuff] = ']';
910 ptrIntoBuffer += strlen(ptrIntoBuffer);
912 // Close array element brace.
913 if (remaining > sizeof ('}'))
915 *ptrIntoBuffer = '}';
920 discoveryResult = OC_STACK_ERROR;
924 else if (virtualUriInRequest == OC_DEVICE_URI)
926 discoveryResult = BuildVirtualResourceResponseForDevice(discoveryBuffer, &remaining);
928 else if (virtualUriInRequest == OC_PLATFORM_URI)
930 discoveryResult = BuildVirtualResourceResponseForPlatform(discoveryBuffer, &remaining);
936 if(resource->resourceProperties & OC_ACTIVE)
938 discoveryResult = SendPresenceNotification(resource->rsrcType,
939 OC_PRESENCE_TRIGGER_CHANGE);
944 // Presence uses observer notification api to respond via SendPresenceNotification.
945 if (virtualUriInRequest != OC_PRESENCE)
947 if(discoveryResult == OC_STACK_OK)
949 discoveryResult = SendNonPersistantDiscoveryResponse(request, resource,
954 OC_LOG_V(ERROR, TAG, "Error (%d) building (%d) discovery response. "\
955 "Not responding to request.", discoveryResult, virtualUriInRequest);
959 return discoveryResult;
963 HandleDefaultDeviceEntityHandler (OCServerRequest *request)
967 return OC_STACK_INVALID_PARAM;
970 OCStackResult result = OC_STACK_OK;
971 OCEntityHandlerResult ehResult = OC_EH_ERROR;
972 OCEntityHandlerRequest ehRequest = {};
974 OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithDefaultDeviceEntityHandler"));
975 result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
976 request->method, (OCResourceHandle) NULL, request->query,
977 request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
978 request->rcvdVendorSpecificHeaderOptions,
979 (OCObserveAction)request->observationOption, (OCObservationId)0);
980 VERIFY_SUCCESS(result, OC_STACK_OK);
982 // At this point we know for sure that defaultDeviceHandler exists
983 ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
984 (char*) request->resourceUrl, defaultDeviceHandlerCallbackParameter);
985 if(ehResult == OC_EH_SLOW)
987 OC_LOG(INFO, TAG, PCF("This is a slow resource"));
988 request->slowFlag = 1;
990 else if(ehResult == OC_EH_ERROR)
992 FindAndDeleteServerRequest(request);
994 result = EntityHandlerCodeToOCStackCode(ehResult);
1000 HandleResourceWithEntityHandler (OCServerRequest *request,
1001 OCResource *resource,
1002 uint8_t collectionResource)
1004 if(!request || ! resource)
1006 return OC_STACK_INVALID_PARAM;
1009 OCStackResult result = OC_STACK_ERROR;
1010 OCEntityHandlerResult ehResult = OC_EH_ERROR;
1011 OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
1012 ResourceObserver *resObs = NULL;
1014 OCEntityHandlerRequest ehRequest = {};
1016 OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithEntityHandler"));
1018 result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
1019 request->method, (OCResourceHandle) resource, request->query,
1020 request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
1021 request->rcvdVendorSpecificHeaderOptions,
1022 (OCObserveAction)request->observationOption, 0);
1023 VERIFY_SUCCESS(result, OC_STACK_OK);
1025 if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
1027 OC_LOG(INFO, TAG, PCF("No observation requested"));
1028 ehFlag = OC_REQUEST_FLAG;
1030 else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER && !collectionResource)
1032 OC_LOG(INFO, TAG, PCF("Observation registration requested"));
1034 result = GenerateObserverId(&ehRequest.obsInfo.obsId);
1035 VERIFY_SUCCESS(result, OC_STACK_OK);
1037 result = AddObserver ((const char*)(request->resourceUrl),
1038 (const char *)(request->query),
1039 ehRequest.obsInfo.obsId, request->requestToken, request->tokenLength,
1040 resource, request->qos,
1043 if(result == OC_STACK_OK)
1045 OC_LOG(INFO, TAG, PCF("Added observer successfully"));
1046 request->observeResult = OC_STACK_OK;
1047 ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
1051 result = OC_STACK_OK;
1053 // The error in observeResult for the request will be used when responding to this
1054 // request by omitting the observation option/sequence number.
1055 request->observeResult = OC_STACK_ERROR;
1056 OC_LOG(ERROR, TAG, PCF("Observer Addition failed"));
1057 ehFlag = OC_REQUEST_FLAG;
1061 else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER &&
1062 !collectionResource)
1064 OC_LOG(INFO, TAG, PCF("Deregistering observation requested"));
1066 resObs = GetObserverUsingToken (request->requestToken, request->tokenLength);
1070 // Stack does not contain this observation request
1071 // Either token is incorrect or observation list is corrupted
1072 result = OC_STACK_ERROR;
1075 ehRequest.obsInfo.obsId = resObs->observeId;
1076 ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
1078 result = DeleteObserverUsingToken (request->requestToken, request->tokenLength);
1080 if(result == OC_STACK_OK)
1082 OC_LOG(INFO, TAG, PCF("Removed observer successfully"));
1083 request->observeResult = OC_STACK_OK;
1087 result = OC_STACK_OK;
1088 request->observeResult = OC_STACK_ERROR;
1089 OC_LOG(ERROR, TAG, PCF("Observer Removal failed"));
1094 result = OC_STACK_ERROR;
1098 ehResult = resource->entityHandler(ehFlag, &ehRequest, resource->entityHandlerCallbackParam);
1099 if(ehResult == OC_EH_SLOW)
1101 OC_LOG(INFO, TAG, PCF("This is a slow resource"));
1102 request->slowFlag = 1;
1104 else if(ehResult == OC_EH_ERROR)
1106 FindAndDeleteServerRequest(request);
1108 result = EntityHandlerCodeToOCStackCode(ehResult);
1113 static OCStackResult
1114 HandleCollectionResourceDefaultEntityHandler (OCServerRequest *request,
1115 OCResource *resource)
1117 if(!request || !resource)
1119 return OC_STACK_INVALID_PARAM;
1122 OCStackResult result = OC_STACK_ERROR;
1123 OCEntityHandlerRequest ehRequest = {};
1125 result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
1126 request->method, (OCResourceHandle) resource, request->query,
1127 request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
1128 request->rcvdVendorSpecificHeaderOptions,
1129 (OCObserveAction)request->observationOption, (OCObservationId) 0);
1130 if(result != OC_STACK_OK)
1135 return (DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest));
1139 ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request)
1141 OCStackResult ret = OC_STACK_OK;
1143 switch (resHandling)
1145 case OC_RESOURCE_VIRTUAL:
1147 ret = HandleVirtualResource (request, resource);
1150 case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER:
1152 ret = HandleDefaultDeviceEntityHandler(request);
1155 case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
1157 OC_LOG(INFO, TAG, PCF("OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER"));
1158 return OC_STACK_ERROR;
1160 case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
1162 ret = HandleResourceWithEntityHandler (request, resource, 0);
1165 case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
1167 ret = HandleResourceWithEntityHandler (request, resource, 1);
1170 case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
1172 ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
1175 case OC_RESOURCE_NOT_SPECIFIED:
1177 ret = OC_STACK_NO_RESOURCE;
1182 OC_LOG(INFO, TAG, PCF("Invalid Resource Determination"));
1183 return OC_STACK_ERROR;
1189 void DeletePlatformInfo()
1191 OC_LOG(INFO, TAG, PCF("Deleting platform info."));
1193 OICFree(savedPlatformInfo.platformID);
1194 savedPlatformInfo.platformID = NULL;
1196 OICFree(savedPlatformInfo.manufacturerName);
1197 savedPlatformInfo.manufacturerName = NULL;
1199 OICFree(savedPlatformInfo.manufacturerUrl);
1200 savedPlatformInfo.manufacturerUrl = NULL;
1202 OICFree(savedPlatformInfo.modelNumber);
1203 savedPlatformInfo.modelNumber = NULL;
1205 OICFree(savedPlatformInfo.dateOfManufacture);
1206 savedPlatformInfo.dateOfManufacture = NULL;
1208 OICFree(savedPlatformInfo.platformVersion);
1209 savedPlatformInfo.platformVersion = NULL;
1211 OICFree(savedPlatformInfo.operatingSystemVersion);
1212 savedPlatformInfo.operatingSystemVersion = NULL;
1214 OICFree(savedPlatformInfo.hardwareVersion);
1215 savedPlatformInfo.hardwareVersion = NULL;
1217 OICFree(savedPlatformInfo.firmwareVersion);
1218 savedPlatformInfo.firmwareVersion = NULL;
1220 OICFree(savedPlatformInfo.supportUrl);
1221 savedPlatformInfo.supportUrl = NULL;
1223 OICFree(savedPlatformInfo.systemTime);
1224 savedPlatformInfo.systemTime = NULL;
1227 static OCStackResult DeepCopyPlatFormInfo(OCPlatformInfo info)
1229 savedPlatformInfo.platformID = OICStrdup(info.platformID);
1230 savedPlatformInfo.manufacturerName = OICStrdup(info.manufacturerName);
1231 savedPlatformInfo.manufacturerUrl = OICStrdup(info.manufacturerUrl);
1232 savedPlatformInfo.modelNumber = OICStrdup(info.modelNumber);
1233 savedPlatformInfo.dateOfManufacture = OICStrdup(info.dateOfManufacture);
1234 savedPlatformInfo.platformVersion = OICStrdup(info.platformVersion);
1235 savedPlatformInfo.operatingSystemVersion = OICStrdup(info.operatingSystemVersion);
1236 savedPlatformInfo.hardwareVersion = OICStrdup(info.hardwareVersion);
1237 savedPlatformInfo.firmwareVersion = OICStrdup(info.firmwareVersion);
1238 savedPlatformInfo.supportUrl = OICStrdup(info.supportUrl);
1239 savedPlatformInfo.systemTime = OICStrdup(info.systemTime);
1241 if ((!savedPlatformInfo.platformID && info.platformID)||
1242 (!savedPlatformInfo.manufacturerName && info.manufacturerName)||
1243 (!savedPlatformInfo.manufacturerUrl && info.manufacturerUrl)||
1244 (!savedPlatformInfo.modelNumber && info.modelNumber)||
1245 (!savedPlatformInfo.dateOfManufacture && info.dateOfManufacture)||
1246 (!savedPlatformInfo.platformVersion && info.platformVersion)||
1247 (!savedPlatformInfo.operatingSystemVersion && info.operatingSystemVersion)||
1248 (!savedPlatformInfo.hardwareVersion && info.hardwareVersion)||
1249 (!savedPlatformInfo.firmwareVersion && info.firmwareVersion)||
1250 (!savedPlatformInfo.supportUrl && info.supportUrl)||
1251 (!savedPlatformInfo.systemTime && info.systemTime))
1253 DeletePlatformInfo();
1254 return OC_STACK_INVALID_PARAM;
1261 OCStackResult SavePlatformInfo(OCPlatformInfo info)
1263 DeletePlatformInfo();
1265 OCStackResult res = DeepCopyPlatFormInfo(info);
1267 if (res != OC_STACK_OK)
1269 OC_LOG_V(ERROR, TAG, PCF("Failed to save platform info. errno(%d)"), res);
1273 OC_LOG(ERROR, TAG, PCF("Platform info saved."));
1279 void DeleteDeviceInfo()
1281 OC_LOG(INFO, TAG, PCF("Deleting device info."));
1283 OICFree(savedDeviceInfo.deviceName);
1284 savedDeviceInfo.deviceName = NULL;
1287 static OCStackResult DeepCopyDeviceInfo(OCDeviceInfo info)
1289 savedDeviceInfo.deviceName = OICStrdup(info.deviceName);
1291 if(!savedDeviceInfo.deviceName && info.deviceName)
1294 return OC_STACK_NO_MEMORY;
1300 OCStackResult SaveDeviceInfo(OCDeviceInfo info)
1302 OCStackResult res = OC_STACK_OK;
1306 res = DeepCopyDeviceInfo(info);
1308 VERIFY_SUCCESS(res, OC_STACK_OK);
1310 if(OCGetServerInstanceID() == NULL)
1312 OC_LOG(INFO, TAG, PCF("Device ID generation failed"));
1313 res = OC_STACK_ERROR;
1317 OC_LOG(INFO, TAG, PCF("Device initialized successfully."));