[IOT-1884] Allow IoTivity to generate and persist PIID
[platform/upstream/iotivity.git] / resource / csdk / stack / src / ocresource.c
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
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
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
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.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
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 #ifndef _GNU_SOURCE
29 #define _GNU_SOURCE
30 #endif
31
32 #include "iotivity_config.h"
33 #ifdef HAVE_STRING_H
34 #include <string.h>
35 #endif
36 #ifdef HAVE_STRINGS_H
37 #include <strings.h>
38 #endif
39
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"
46 #include "logger.h"
47 #include "ocpayload.h"
48 #include "secureresourcemanager.h"
49 #include "cacommon.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"
57 #include "oickeepalive.h"
58 #include "ocpayloadcbor.h"
59 #include "psinterface.h"
60
61 #ifdef ROUTING_GATEWAY
62 #include "routingmanager.h"
63 #endif
64
65 /// Module Name
66 #define TAG "OIC_RI_RESOURCE"
67
68 // Using 1k as block size since most persistent storage implementations use a power of 2.
69 #define INTROSPECTION_FILE_SIZE_BLOCK  1024
70
71 #define VERIFY_SUCCESS(op) { if (op != (OC_STACK_OK)) \
72             {OIC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
73
74 /**
75  * Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
76  * The value of payload size is increased up to CBOR_MAX_SIZE.
77  */
78 static const uint16_t CBOR_SIZE = 512;
79
80 /**
81  * Max cbor size payload.
82  */
83 static const uint16_t CBOR_MAX_SIZE = 4400;
84
85 extern OCResource *headResource;
86
87 /**
88  * Prepares a Payload for response.
89  */
90 static OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
91                                                   OCDiscoveryPayload *payload,
92                                                   OCDevAddr *endpoint,
93                                                   CAEndpoint_t *networkInfo,
94                                                   size_t infoSize);
95
96 /**
97  * Sets the value of an attribute on a resource.
98  */
99 static OCStackResult SetAttributeInternal(OCResource *resource,
100                                           const char *attribute,
101                                           const void *value,
102                                           bool updateDatabase);
103
104 //-----------------------------------------------------------------------------
105 // Default resource entity handler function
106 //-----------------------------------------------------------------------------
107 OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag,
108         OCEntityHandlerRequest * request, void* callbackParam)
109 {
110     //TODO ("Implement me!!!!");
111     // TODO:  remove silence unused param warnings
112     (void) flag;
113     (void) request;
114     (void) callbackParam;
115     return  OC_EH_OK; // Making sure that the Default EH and the Vendor EH have matching signatures
116 }
117
118 /* This method will retrieve the port at which the secure resource is hosted */
119 static OCStackResult GetSecurePortInfo(OCDevAddr *endpoint, uint16_t *port)
120 {
121     uint16_t p = 0;
122
123     if (endpoint->adapter == OC_ADAPTER_IP)
124     {
125         if (endpoint->flags & OC_IP_USE_V6)
126         {
127             p = caglobals.ip.u6s.port;
128         }
129         else if (endpoint->flags & OC_IP_USE_V4)
130         {
131             p = caglobals.ip.u4s.port;
132         }
133     }
134
135     *port = p;
136     return OC_STACK_OK;
137 }
138
139 #ifdef TCP_ADAPTER
140 /* This method will retrieve the tcp port */
141 static OCStackResult GetTCPPortInfo(OCDevAddr *endpoint, uint16_t *port, bool secured)
142 {
143     uint16_t p = 0;
144
145     if (endpoint->adapter == OC_ADAPTER_IP)
146     {
147         if (endpoint->flags & OC_IP_USE_V4)
148         {
149             p = secured ? caglobals.tcp.ipv4s.port : caglobals.tcp.ipv4.port;
150         }
151         else if (endpoint->flags & OC_IP_USE_V6)
152         {
153             p = secured ? caglobals.tcp.ipv6s.port : caglobals.tcp.ipv6.port;
154         }
155     }
156
157     *port = p;
158     return OC_STACK_OK;
159 }
160 #endif
161
162 /*
163  * Function will extract 0, 1 or 2 filters from query.
164  * More than 2 filters or unsupported filters will result in error.
165  * If both filters are of the same supported type, the 2nd one will be picked.
166  * Resource and device filters in the SAME query are NOT validated
167  * and resources will likely not clear filters.
168  */
169 OCStackResult ExtractFiltersFromQuery(const char *query, char **filterOne, char **filterTwo)
170 {
171     if (!query)
172     {
173         OIC_LOG(ERROR, TAG, "Query is empty!");
174         return OC_STACK_INVALID_QUERY;
175     }
176     char *key = NULL;
177     char *value = NULL;
178     char *queryDup = NULL;
179     char *restOfQuery = NULL;
180     char *keyValuePair = NULL;
181     int numKeyValuePairsParsed = 0;
182
183     *filterOne = NULL;
184     *filterTwo = NULL;
185
186     queryDup = OICStrdup(query);
187     if (NULL == queryDup)
188     {
189         OIC_LOG(ERROR, TAG, "Creating duplicate string failed!");
190         return OC_STACK_NO_MEMORY;
191     }
192
193     OIC_LOG_V(INFO, TAG, "Extracting params from %s", queryDup);
194
195     OCStackResult eCode = OC_STACK_INVALID_QUERY;
196     if (strnlen(queryDup, MAX_QUERY_LENGTH) >= MAX_QUERY_LENGTH)
197     {
198         OIC_LOG(ERROR, TAG, "Query exceeds maximum length.");
199         goto exit;
200     }
201
202     keyValuePair = strtok_r (queryDup, OC_QUERY_SEPARATOR, &restOfQuery);
203
204     while(keyValuePair)
205     {
206         if (numKeyValuePairsParsed >= 2)
207         {
208             OIC_LOG(ERROR, TAG, "More than 2 queries params in URI.");
209             goto exit;
210         }
211
212         key = strtok_r(keyValuePair, OC_KEY_VALUE_DELIMITER, &value);
213
214         if (!key || !value)
215         {
216             goto exit;
217         }
218         else if (strncasecmp(key, OC_RSRVD_INTERFACE, sizeof(OC_RSRVD_INTERFACE) - 1) == 0)
219         {
220             *filterOne = value;     // if
221         }
222         else if (strncasecmp(key, OC_RSRVD_RESOURCE_TYPE, sizeof(OC_RSRVD_INTERFACE) - 1) == 0)
223         {
224             *filterTwo = value;     // rt
225         }
226         else
227         {
228             OIC_LOG_V(ERROR, TAG, "Unsupported query key: %s", key);
229             goto exit;
230         }
231         ++numKeyValuePairsParsed;
232
233         keyValuePair = strtok_r(NULL, OC_QUERY_SEPARATOR, &restOfQuery);
234     }
235
236     if (*filterOne)
237     {
238         *filterOne = OICStrdup(*filterOne);
239         if (NULL == *filterOne)
240         {
241             OIC_LOG(ERROR, TAG, "Creating duplicate string failed!");
242             eCode = OC_STACK_NO_MEMORY;
243             goto exit;
244         }
245     }
246
247     if (*filterTwo)
248     {
249         *filterTwo = OICStrdup(*filterTwo);
250         if (NULL == *filterTwo)
251         {
252             OIC_LOG(ERROR, TAG, "Creating duplicate string failed!");
253             OICFree(*filterOne);
254             eCode = OC_STACK_NO_MEMORY;
255             goto exit;
256         }
257     }
258
259     OICFree(queryDup);
260     OIC_LOG_V(INFO, TAG, "Extracted params if: %s and rt: %s.", *filterOne, *filterTwo);
261     return OC_STACK_OK;
262
263 exit:
264     *filterOne = NULL;
265     *filterTwo = NULL;
266     OICFree(queryDup);
267     return eCode;
268 }
269
270 OCVirtualResources GetTypeOfVirtualURI(const char *uriInRequest)
271 {
272     if (strcmp(uriInRequest, OC_RSRVD_WELL_KNOWN_URI) == 0)
273     {
274         return OC_WELL_KNOWN_URI;
275     }
276     else if (strcmp(uriInRequest, OC_RSRVD_DEVICE_URI) == 0)
277     {
278         return OC_DEVICE_URI;
279     }
280     else if (strcmp(uriInRequest, OC_RSRVD_PLATFORM_URI) == 0)
281     {
282         return OC_PLATFORM_URI;
283     }
284     else if (strcmp(uriInRequest, OC_RSRVD_RESOURCE_TYPES_URI) == 0)
285     {
286         return OC_RESOURCE_TYPES_URI;
287     }
288     else if (strcmp(uriInRequest, OC_RSRVD_INTROSPECTION_URI) == 0)
289     {
290         return OC_INTROSPECTION_URI;
291     }
292     else if (strcmp(uriInRequest, OC_RSRVD_INTROSPECTION_PAYLOAD_URI) == 0)
293     {
294         return OC_INTROSPECTION_PAYLOAD_URI;
295     }
296 #ifdef ROUTING_GATEWAY
297     else if (0 == strcmp(uriInRequest, OC_RSRVD_GATEWAY_URI))
298     {
299         return OC_GATEWAY_URI;
300     }
301 #endif
302 #ifdef WITH_PRESENCE
303     else if (strcmp(uriInRequest, OC_RSRVD_PRESENCE_URI) == 0)
304     {
305         return OC_PRESENCE;
306     }
307 #endif //WITH_PRESENCE
308
309 #ifdef MQ_BROKER
310     else if (0 == strcmp(uriInRequest, OC_RSRVD_WELL_KNOWN_MQ_URI))
311     {
312         return OC_MQ_BROKER_URI;
313     }
314 #endif //MQ_BROKER
315
316 #ifdef TCP_ADAPTER
317     else if (strcmp(uriInRequest, OC_RSRVD_KEEPALIVE_URI) == 0)
318     {
319         return OC_KEEPALIVE_RESOURCE_URI;
320     }
321 #endif
322
323     return OC_UNKNOWN_URI;
324 }
325
326 static OCStackResult getQueryParamsForFiltering (OCVirtualResources uri, char *query,
327                                             char **filterOne, char **filterTwo)
328 {
329     if(!filterOne || !filterTwo)
330     {
331         return OC_STACK_INVALID_PARAM;
332     }
333
334     *filterOne = NULL;
335     *filterTwo = NULL;
336
337 #ifdef WITH_PRESENCE
338     if (uri == OC_PRESENCE)
339     {
340         //Nothing needs to be done, except for pass a OC_PRESENCE query through as OC_STACK_OK.
341         OIC_LOG(INFO, TAG, "OC_PRESENCE Request for virtual resource.");
342         return OC_STACK_OK;
343     }
344 #endif
345
346     OCStackResult result = OC_STACK_OK;
347
348     if (query && *query)
349     {
350         result = ExtractFiltersFromQuery(query, filterOne, filterTwo);
351     }
352
353     return result;
354 }
355
356 static OCStackResult BuildDevicePlatformPayload(const OCResource *resourcePtr, OCRepPayload** payload,
357     bool addDeviceId)
358 {
359     OCRepPayload *tempPayload = OCRepPayloadCreate();
360
361     if (!resourcePtr)
362     {
363         OCRepPayloadDestroy(tempPayload);
364         return OC_STACK_INVALID_PARAM;
365     }
366
367     if (!tempPayload)
368     {
369         return OC_STACK_NO_MEMORY;
370     }
371
372     if (addDeviceId)
373     {
374         const char *deviceId = OCGetServerInstanceIDString();
375         if (!deviceId)
376         {
377             OIC_LOG(ERROR, TAG, "Failed retrieving device id.");
378             return OC_STACK_ERROR;
379         }
380         OCRepPayloadSetPropString(tempPayload, OC_RSRVD_DEVICE_ID, deviceId);
381     }
382
383     for (OCResourceType *resType = resourcePtr->rsrcType; resType; resType = resType->next)
384     {
385         OCRepPayloadAddResourceType(tempPayload, resType->resourcetypename);
386     }
387
388     for (OCResourceInterface *resInterface = resourcePtr->rsrcInterface; resInterface;
389         resInterface = resInterface->next)
390     {
391         OCRepPayloadAddInterface(tempPayload, resInterface->name);
392     }
393
394     for (OCAttribute *resAttrib = resourcePtr->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
395     {
396         if (resAttrib->attrName && resAttrib->attrValue)
397         {
398             if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName))
399             {
400                 char *dmv = OCCreateString((OCStringLL *)resAttrib->attrValue);
401                 if (dmv)
402                 {
403                     OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, dmv);
404                     OICFree(dmv);
405                 }
406             }
407             else
408             {
409                 OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, (char *)resAttrib->attrValue);
410             }
411         }
412     }
413
414     if (!*payload)
415     {
416         *payload = tempPayload;
417     }
418     else
419     {
420         OCRepPayloadAppend(*payload, tempPayload);
421     }
422
423     return OC_STACK_OK;
424 }
425
426 OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr,
427                     OCRepPayload** payload, OCDevAddr *devAddr)
428 {
429     OCRepPayload *tempPayload = OCRepPayloadCreate();
430
431     if (!resourcePtr)
432     {
433         OCRepPayloadDestroy(tempPayload);
434         return OC_STACK_INVALID_PARAM;
435     }
436
437     if(!tempPayload)
438     {
439         return OC_STACK_NO_MEMORY;
440     }
441
442     OCRepPayloadSetPropString(tempPayload, OC_RSRVD_HREF, resourcePtr->uri);
443
444     uint8_t numElement = 0;
445     if (OC_STACK_OK == OCGetNumberOfResourceTypes((OCResource *)resourcePtr, &numElement))
446     {
447         size_t rtDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
448         char **rt = (char **)OICMalloc(sizeof(char *) * numElement);
449         for (uint8_t i = 0; i < numElement; ++i)
450         {
451             const char *value = OCGetResourceTypeName((OCResource *)resourcePtr, i);
452             OIC_LOG_V(DEBUG, TAG, "value: %s", value);
453             rt[i] = OICStrdup(value);
454         }
455         OCRepPayloadSetStringArrayAsOwner(tempPayload, OC_RSRVD_RESOURCE_TYPE, rt, rtDim);
456     }
457
458     numElement = 0;
459     if (OC_STACK_OK == OCGetNumberOfResourceInterfaces((OCResource *)resourcePtr, &numElement))
460     {
461         size_t ifDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
462         char **itf = (char **)OICMalloc(sizeof(char *) * numElement);
463         for (uint8_t i = 0; i < numElement; ++i)
464         {
465             const char *value = OCGetResourceInterfaceName((OCResource *)resourcePtr, i);
466             OIC_LOG_V(DEBUG, TAG, "value: %s", value);
467             itf[i] = OICStrdup(value);
468         }
469         OCRepPayloadSetStringArrayAsOwner(tempPayload, OC_RSRVD_INTERFACE, itf, ifDim);
470     }
471
472     for (OCAttribute *resAttrib = resourcePtr->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
473     {
474         if (resAttrib->attrName && resAttrib->attrValue)
475         {
476             OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, (char *)resAttrib->attrValue);
477         }
478     }
479
480     OCResourceProperty p = OCGetResourceProperties((OCResourceHandle *)resourcePtr);
481     OCRepPayload *policy = OCRepPayloadCreate();
482     if (!policy)
483     {
484         OCPayloadDestroy((OCPayload *)tempPayload);
485         return OC_STACK_NO_MEMORY;
486     }
487     OCRepPayloadSetPropInt(policy, OC_RSRVD_BITMAP, ((p & OC_DISCOVERABLE) | (p & OC_OBSERVABLE)));
488     if (p & OC_SECURE)
489     {
490         OCRepPayloadSetPropBool(policy, OC_RSRVD_SECURE, p & OC_SECURE);
491         uint16_t securePort = 0;
492         if (GetSecurePortInfo(devAddr, &securePort) != OC_STACK_OK)
493         {
494             securePort = 0;
495         }
496         OCRepPayloadSetPropInt(policy, OC_RSRVD_HOSTING_PORT, securePort);
497     }
498     OCRepPayloadSetPropObjectAsOwner(tempPayload, OC_RSRVD_POLICY, policy);
499
500     if (!*payload)
501     {
502         *payload = tempPayload;
503     }
504     else
505     {
506         OCRepPayloadAppend(*payload, tempPayload);
507     }
508
509     return OC_STACK_OK;
510 }
511
512 void CleanUpDeviceProperties(OCDeviceProperties **deviceProperties)
513 {
514     if (!deviceProperties || !(*deviceProperties))
515     {
516         return;
517     }
518
519     OICFreeAndSetToNull((void**)(deviceProperties));
520 }
521
522 static OCStackResult CreateDeviceProperties(const char *piid, OCDeviceProperties **deviceProperties)
523 {
524     OIC_LOG(DEBUG, TAG, "CreateDeviceProperties IN");
525
526     OCStackResult result = OC_STACK_OK;
527
528     if (!piid || !deviceProperties)
529     {
530         return OC_STACK_INVALID_PARAM;
531     }
532
533     *deviceProperties = (OCDeviceProperties*)OICCalloc(1, sizeof(OCDeviceProperties));
534     if (*deviceProperties)
535     {
536         OICStrcpy((*deviceProperties)->protocolIndependentId, UUID_STRING_SIZE, piid);
537     }
538     else
539     {
540         result = OC_STACK_NO_MEMORY;
541     }
542
543     OIC_LOG(DEBUG, TAG, "CreateDeviceProperties OUT");
544
545     return result;
546 }
547
548 static OCStackResult GenerateDeviceProperties(OCDeviceProperties **deviceProperties)
549 {
550     OCStackResult result = OC_STACK_OK;
551     OicUuid_t generatedProtocolIndependentId = {.id = {0}};
552     char* protocolIndependentId = NULL;
553
554     if (!deviceProperties)
555     {
556         return OC_STACK_INVALID_PARAM;
557     }
558
559     *deviceProperties = NULL;
560
561     // Generate a UUID for the Protocol Independent ID
562     if (OCGenerateUuid(generatedProtocolIndependentId.id))
563     {
564         protocolIndependentId = (char*)OICCalloc(UUID_STRING_SIZE, sizeof(char));
565         if (protocolIndependentId)
566         {
567             if (!OCConvertUuidToString(generatedProtocolIndependentId.id, protocolIndependentId))
568             {
569                 OIC_LOG(ERROR, TAG, "ConvertUuidToStr failed");
570                 result = OC_STACK_ERROR;
571             }
572         }
573         else
574         {
575             result = OC_STACK_NO_MEMORY;
576         }
577     }
578     else
579     {
580         OIC_LOG(FATAL, TAG, "Generate UUID for Device Properties Protocol Independent ID failed!");
581         result = OC_STACK_ERROR;
582     }
583
584     if (OC_STACK_OK == result)
585     {
586         result = CreateDeviceProperties(protocolIndependentId, deviceProperties);
587         if (OC_STACK_OK != result)
588         {
589             OIC_LOG(ERROR, TAG, "CreateDeviceProperties failed");
590         }
591     }
592
593     // Clean Up
594     OICFreeAndSetToNull((void**)&protocolIndependentId);
595
596     return result;
597 }
598
599 OCStackResult CBORPayloadToDeviceProperties(const uint8_t *payload, size_t size, OCDeviceProperties **deviceProperties)
600 {
601     OCStackResult result = OC_STACK_OK;
602     CborError cborResult = CborNoError;
603     char* protocolIndependentId = NULL;
604     CborParser parser;
605     CborValue dpCbor;
606     CborValue dpMap;
607
608     if (!payload || (size <= 0) || !deviceProperties)
609     {
610         return OC_STACK_INVALID_PARAM;
611     }
612
613     *deviceProperties = NULL;
614
615     cbor_parser_init(payload, size, 0, &parser, &dpCbor);
616
617     // Protocol Independent ID - Mandatory
618     cborResult = cbor_value_map_find_value(&dpCbor, OC_RSRVD_PROTOCOL_INDEPENDENT_ID, &dpMap);
619     if ((CborNoError == cborResult) && cbor_value_is_text_string(&dpMap))
620     {
621         size_t len = 0;
622
623         cborResult = cbor_value_dup_text_string(&dpMap, &protocolIndependentId, &len, NULL);
624         if (CborNoError != cborResult)
625         {
626             OIC_LOG(ERROR, TAG, "Failed to get Protocol Independent Id!");
627             result = OC_STACK_ERROR;
628         }
629     }
630     else
631     {
632         OIC_LOG(ERROR, TAG, "Protocol Independent Id is not present or invalid!");
633         result = OC_STACK_ERROR;
634     }
635
636     if (OC_STACK_OK == result)
637     {
638         result = CreateDeviceProperties(protocolIndependentId, deviceProperties);
639         if (OC_STACK_OK != result)
640         {
641             OIC_LOG(ERROR, TAG, "CreateDeviceProperties failed");
642         }
643     }
644
645     // Clean Up
646     OICFreeAndSetToNull((void**)&protocolIndependentId);
647
648     return result;
649 }
650
651 OCStackResult DevicePropertiesToCBORPayload(const OCDeviceProperties *deviceProperties, uint8_t **payload, size_t *size)
652 {
653     OCStackResult result = OC_STACK_OK;
654     CborError cborResult = CborNoError;
655     uint8_t *cborPayload = NULL;
656     size_t cborLen = CBOR_SIZE;
657     CborEncoder encoder;
658     CborEncoder dpMap;
659
660     if (!deviceProperties || !payload || !size || (*size > CBOR_MAX_SIZE))
661     {
662         return OC_STACK_INVALID_PARAM;
663     }
664
665     // Reset the CBOR length if we need to
666     if (*size > 0)
667     {
668         cborLen = *size;
669     }
670
671     *payload = NULL;
672     *size = 0;
673
674     cborPayload = (uint8_t*)OICCalloc(1, cborLen);
675     if (NULL != cborPayload)
676     {
677         cbor_encoder_init(&encoder, cborPayload, cborLen, 0);
678
679         // Create the Device Properties encoder map
680         cborResult = cbor_encoder_create_map(&encoder, &dpMap, CborIndefiniteLength);
681         if (CborNoError != cborResult)
682         {
683             OIC_LOG(ERROR, TAG, "Failed to create encoder map!");
684             result = OC_STACK_ERROR;
685         }
686     }
687     else
688     {
689         result = OC_STACK_NO_MEMORY;
690     }
691
692     // Protocol Independent ID - Mandatory
693     if (OC_STACK_OK == result)
694     {
695         cborResult = cbor_encode_text_string(&dpMap, OC_RSRVD_PROTOCOL_INDEPENDENT_ID, strlen(OC_RSRVD_PROTOCOL_INDEPENDENT_ID));
696         if (CborNoError == cborResult)
697         {
698             cborResult = cbor_encode_text_string(&dpMap,
699                                                  deviceProperties->protocolIndependentId,
700                                                  strlen(deviceProperties->protocolIndependentId));
701             if (CborNoError != cborResult)
702             {
703                 OIC_LOG(ERROR, TAG, "Failed to encode protocolIndependentId!");
704                 result = OC_STACK_ERROR;
705             }
706         }
707         else
708         {
709             OIC_LOG(ERROR, TAG, "Failed to encode OC_RSRVD_PROTOCOL_INDEPENDENT_ID!");
710             result = OC_STACK_ERROR;
711         }
712     }
713
714     // Encoding is finished
715     if (OC_STACK_OK == result)
716     {
717         cborResult = cbor_encoder_close_container(&encoder, &dpMap);
718         if (CborNoError != cborResult)
719         {
720             OIC_LOG(ERROR, TAG, "Failed to close dpMap container!");
721             result = OC_STACK_ERROR;
722         }
723     }
724
725     if (OC_STACK_OK == result)
726     {
727         *size = cbor_encoder_get_buffer_size(&encoder, cborPayload);
728         *payload = cborPayload;
729         cborPayload = NULL;
730     }
731     else if ((CborErrorOutOfMemory == cborResult) && (cborLen < CBOR_MAX_SIZE))
732     {
733         OICFreeAndSetToNull((void**)&cborPayload);
734
735         // Realloc and try again
736         cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
737         result = DevicePropertiesToCBORPayload(deviceProperties, payload, &cborLen);
738         if (OC_STACK_OK == result)
739         {
740             *size = cborLen;
741         }
742     }
743     else
744     {
745         OICFreeAndSetToNull((void**)&cborPayload);
746     }
747
748     return result;
749 }
750
751 static OCStackResult UpdateDeviceInfoResourceWithDeviceProperties(const OCDeviceProperties *deviceProperties, bool updateDatabase)
752 {
753     OCStackResult result = OC_STACK_OK;
754     OCResource *resource = NULL;
755
756     if (!deviceProperties)
757     {
758         return OC_STACK_INVALID_PARAM;
759     }
760
761     resource = FindResourceByUri(OC_RSRVD_DEVICE_URI);
762     if (resource)
763     {
764         result = SetAttributeInternal(resource, OC_RSRVD_PROTOCOL_INDEPENDENT_ID, deviceProperties->protocolIndependentId, updateDatabase);
765         if (OC_STACK_OK != result)
766         {
767             OIC_LOG(ERROR, TAG, "OCSetPropertyValue failed to set Protocol Independent ID");
768         }
769     }
770     else
771     {
772         OIC_LOG(ERROR, TAG, "Resource does not exist.");
773         result = OC_STACK_NO_RESOURCE;
774     }
775
776     return result;
777 }
778
779 static OCStackResult ReadDevicePropertiesFromDatabase(OCDeviceProperties **deviceProperties)
780 {
781     uint8_t *data = NULL;
782     size_t size = 0;
783
784     OCStackResult result = ReadDatabaseFromPS(OC_DEVICE_PROPS_FILE_NAME, OC_JSON_DEVICE_PROPS_NAME, &data, &size);
785     if (OC_STACK_OK == result)
786     {
787         // Read device properties from PS
788         result = CBORPayloadToDeviceProperties(data, size, deviceProperties);
789         if (OC_STACK_OK != result)
790         {
791             OIC_LOG(WARNING, TAG, "CBORPayloadToDeviceProperties failed");
792         }
793     }
794     else
795     {
796         OIC_LOG(ERROR, TAG, "ReadDatabaseFromPS failed");
797     }
798
799     // Clean Up
800     OICFreeAndSetToNull((void**)&data);
801
802     return result;
803 }
804
805 static OCStackResult UpdateDevicePropertiesDatabase(const OCDeviceProperties *deviceProperties)
806 {
807     OCStackResult result = OC_STACK_OK;
808     uint8_t *payload = NULL;
809     size_t size = 0;
810
811     if (!deviceProperties)
812     {
813         return OC_STACK_INVALID_PARAM;
814     }
815
816     // Check to see if persistent storage exists. If it doesn't then
817     // we just allow the device properties to exist in memory and
818     // it is the application's job to manage them.
819     if (!OCGetPersistentStorageHandler())
820     {
821         OIC_LOG(DEBUG, TAG, "Persistent Storage handler is NULL.");
822         return OC_STACK_OK;
823     }
824
825     // Convert OCDeviceProperties into CBOR to use for updating Persistent Storage
826     result = DevicePropertiesToCBORPayload(deviceProperties, &payload, &size);
827     if ((OC_STACK_OK == result) && payload)
828     {
829         result = UpdateResourceInPS(OC_DEVICE_PROPS_FILE_NAME, OC_JSON_DEVICE_PROPS_NAME, payload, size);
830         if (OC_STACK_OK != result)
831         {
832             OIC_LOG_V(ERROR, TAG, "UpdateResourceInPS failed with %d!", result);
833         }
834     }
835     else
836     {
837         OIC_LOG_V(ERROR, TAG, "DevicePropertiesToCBORPayload failed with %d!", result);
838     }
839
840     // Clean Up
841     OICFreeAndSetToNull((void**)&payload);
842
843     return result;
844 }
845
846 OCStackResult InitializeDeviceProperties()
847 {
848     OIC_LOG(DEBUG, TAG, "InitializeDeviceProperties IN");
849
850     OCStackResult result = OC_STACK_OK;
851     OCDeviceProperties *deviceProperties = NULL;
852     bool updateDatabase = false;
853
854     // Populate OCDeviceProperties from persistent storage
855     result = ReadDevicePropertiesFromDatabase(&deviceProperties);
856     if (OC_STACK_OK != result)
857     {
858         OIC_LOG(ERROR, TAG, "ReadDevicePropertiesFromDatabase failed");
859     }
860
861     // If the device properties in persistent storage are corrupted or
862     // not available for some reason, a default OCDeviceProperties is created.
863     if ((OC_STACK_OK != result) || !deviceProperties)
864     {
865         result = GenerateDeviceProperties(&deviceProperties);
866         if (OC_STACK_OK == result)
867         {
868             updateDatabase = true;
869         }
870         else
871         {
872             OIC_LOG(ERROR, TAG, "GenerateDeviceProperties failed");
873         }
874     }
875
876     // Set the device properties information on the device info resource. This will
877     // also persist OCDeviceProperties so they can be used in the future if they are
878     // not already in the database.
879     if (OC_STACK_OK == result)
880     {
881         result = UpdateDeviceInfoResourceWithDeviceProperties(deviceProperties, updateDatabase);
882         if (OC_STACK_OK != result)
883         {
884             OIC_LOG(ERROR, TAG, "UpdateDeviceInfoResourceWithDeviceProperties failed");
885         }
886     }
887
888     // Clean Up
889     CleanUpDeviceProperties(&deviceProperties);
890
891     OIC_LOG(DEBUG, TAG, "InitializeDeviceProperties OUT");
892
893     return result;
894 }
895
896 static size_t GetIntrospectionDataSize(const OCPersistentStorage *ps)
897 {
898     size_t size = 0;
899     char buffer[INTROSPECTION_FILE_SIZE_BLOCK];
900     FILE *fp;
901
902     if (!ps)
903     {
904         return 0;
905     }
906
907     fp = ps->open(OC_INTROSPECTION_FILE_NAME, "rb");
908     if (fp)
909     {
910         size_t bytesRead = 0;
911         do
912         {
913             bytesRead = ps->read(buffer, 1, INTROSPECTION_FILE_SIZE_BLOCK, fp);
914             size += bytesRead;
915         } while (bytesRead);
916         ps->close(fp);
917     }
918     return size;
919 }
920
921 OCStackResult GetIntrospectionDataFromPS(char **data, size_t *size)
922 {
923     OIC_LOG(DEBUG, TAG, "GetIntrospectionDataFromPS IN");
924
925     FILE *fp = NULL;
926     uint8_t *fsData = NULL;
927     size_t fileSize = 0;
928     OCStackResult ret = OC_STACK_ERROR;
929     OCPersistentStorage *ps = NULL;
930
931     if (!data || *data || !size)
932     {
933         return OC_STACK_INVALID_PARAM;
934     }
935
936     ps = OCGetPersistentStorageHandler();
937     if (!ps)
938     {
939         OIC_LOG(ERROR, TAG, "Persistent Storage handler is NULL");
940         goto exit;
941     }
942
943     fileSize = GetIntrospectionDataSize(ps);
944     OIC_LOG_V(DEBUG, TAG, "File Read Size: %zu", fileSize);
945     if (fileSize)
946     {
947         // allocate one more byte to accomodate null terminator for string we are reading.
948         fsData = (uint8_t *)OICCalloc(1, fileSize + 1);
949         if (!fsData)
950         {
951             OIC_LOG(ERROR, TAG, "Could not allocate memory for introspection data");
952             goto exit;
953         }
954
955         fp = ps->open(OC_INTROSPECTION_FILE_NAME, "rb");
956         if (!fp)
957         {
958             OIC_LOG(ERROR, TAG, "Could not open persistent storage file for introspection data");
959             goto exit;
960         }
961         if (ps->read(fsData, 1, fileSize, fp) == fileSize)
962         {
963             *size = fileSize;
964             fsData[fileSize] = '\0';
965             *data = (char *)fsData;
966             fsData = NULL;
967             ret = OC_STACK_OK;
968         }
969     }
970     OIC_LOG(DEBUG, TAG, "GetIntrospectionDataFromPS OUT");
971
972 exit:
973     if (fp)
974     {
975         ps->close(fp);
976     }
977     if (fsData)
978     {
979         OICFree(fsData);
980     }
981     return ret;
982 }
983
984 OCStackResult BuildIntrospectionPayloadResponse(const OCResource *resourcePtr,
985     OCRepPayload** payload, OCDevAddr *devAddr)
986 {
987     OCRepPayload *tempPayload = NULL;
988     OCStackResult ret;
989     char *introspectionData = NULL;
990     size_t size = 0;
991     ret = GetIntrospectionDataFromPS(&introspectionData, &size);
992     if (OC_STACK_OK == ret)
993     {
994         OCRepPayload *tempPayload = OCRepPayloadCreate();
995         if (tempPayload)
996         {
997             if (OCRepPayloadSetPropStringAsOwner(tempPayload, OC_RSRVD_INTROSPECTION_DATA_NAME, introspectionData))
998             {
999                 *payload = tempPayload;
1000             }
1001         }
1002         else
1003         {
1004             ret = OC_STACK_NO_MEMORY;
1005         }
1006     }
1007     if (ret != OC_STACK_OK)
1008     {
1009         OICFree(introspectionData);
1010         OCRepPayloadDestroy(tempPayload);
1011     }
1012
1013     return ret;
1014 }
1015
1016 OCRepPayload *BuildUrlInfoWithProtocol(const char *protocol)
1017 {
1018     OCStackResult result = OC_STACK_OK;
1019     OCRepPayload *urlInfoPayload = OCRepPayloadCreate();
1020     if (!urlInfoPayload)
1021     {
1022         OIC_LOG(ERROR, TAG, "Failed to create a new RepPayload");
1023         result = OC_STACK_NO_MEMORY;
1024         goto exit;
1025     }
1026
1027     if (!OCRepPayloadSetPropString(urlInfoPayload, OC_RSRVD_INTROSPECTION_URL, OC_RSRVD_INTROSPECTION_PAYLOAD_URI))
1028     {
1029         OIC_LOG(ERROR, TAG, "Failed to add url");
1030         result = OC_STACK_ERROR;
1031         goto exit;
1032     }
1033     if (!OCRepPayloadSetPropString(urlInfoPayload, OC_RSRVD_INTROSPECTION_PROTOCOL, protocol))
1034     {
1035         OIC_LOG(ERROR, TAG, "Failed to add protocol");
1036         result = OC_STACK_ERROR;
1037         goto exit;
1038     }
1039     if (!OCRepPayloadSetPropString(urlInfoPayload, OC_RSRVD_INTROSPECTION_CONTENT_TYPE, OC_RSRVD_INTROSPECTION_CONTENT_TYPE_VALUE))
1040     {
1041         OIC_LOG(ERROR, TAG, "Failed to add content type");
1042         result = OC_STACK_ERROR;
1043         goto exit;
1044     }
1045     if (!OCRepPayloadSetPropInt(urlInfoPayload, OC_RSRVD_INTROSPECTION_VERSION, OC_RSRVD_INTROSPECTION_VERSION_VALUE))
1046     {
1047         OIC_LOG(ERROR, TAG, "Failed to add version");
1048         result = OC_STACK_ERROR;
1049         goto exit;
1050     }
1051
1052 exit:
1053     if (result != OC_STACK_OK)
1054     {
1055         OCRepPayloadDestroy(urlInfoPayload);
1056         urlInfoPayload = NULL;
1057     }
1058     return urlInfoPayload;
1059 }
1060
1061 OCStackResult AddProtocolToLL(OCStringLL **protoLL, const char *protocol)
1062 {
1063     OCStringLL* cur = *protoLL;
1064     // Check if protocol is already in list
1065     while (cur)
1066     {
1067         if (strcmp(cur->value, protocol) == 0)
1068         {
1069             break;
1070         }
1071         cur = cur->next;
1072     }
1073     if (cur)
1074     {
1075         // The intent of the protocol list is to collect all unique protocols available on this
1076         // endpoint. Set an error that can be used to skip processing this protocol further as
1077         // it already exists in the list.
1078         return OC_STACK_INVALID_PARAM;
1079     }
1080     else
1081     {
1082         cur = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1083         if (!cur)
1084         {
1085             return OC_STACK_NO_MEMORY;
1086         }
1087     }
1088
1089     cur->value = OICStrdup(protocol);
1090     if (!cur->value)
1091     {
1092         OICFree(cur);
1093         return OC_STACK_NO_MEMORY;
1094     }
1095
1096     cur->next = *protoLL;
1097     *protoLL = cur;
1098     return OC_STACK_OK;
1099 }
1100
1101 void FreeProtocolLL(OCStringLL *protoLL)
1102 {
1103     OCStringLL* cur = protoLL;
1104     while (cur)
1105     {
1106         OCStringLL *temp = cur;
1107         cur = cur->next;
1108         OICFree(temp->value);
1109         OICFree(temp);
1110     }
1111 }
1112
1113 OCStackResult BuildIntrospectionResponseRepresentation(const OCResource *resourcePtr,
1114     OCRepPayload** payload, OCDevAddr *devAddr)
1115 {
1116     size_t dimensions[3] = { 0, 0, 0 };
1117     OCRepPayload *tempPayload = NULL;
1118     OCRepPayload **urlInfoPayload = NULL;
1119     OCStringLL *protoLL = NULL;
1120     OCStackResult ret = OC_STACK_OK;
1121     OCResourceType *resType = NULL;
1122     OCResourceInterface *resInterface = NULL;
1123
1124     if (!resourcePtr)
1125     {
1126         ret = OC_STACK_INVALID_PARAM;
1127         goto exit;
1128     }
1129
1130     tempPayload = OCRepPayloadCreate();
1131     if (!tempPayload)
1132     {
1133         ret = OC_STACK_NO_MEMORY;
1134         goto exit;
1135     }
1136
1137     if (!OCRepPayloadSetUri(tempPayload, resourcePtr->uri))
1138     {
1139         OIC_LOG(ERROR, TAG, "Failed to set payload URI");
1140         ret = OC_STACK_ERROR;
1141         goto exit;
1142     }
1143
1144     resType = resourcePtr->rsrcType;
1145     while (resType)
1146     {
1147         if (!OCRepPayloadAddResourceType(tempPayload, resType->resourcetypename))
1148         {
1149             OIC_LOG(ERROR, TAG, "Failed at add resource type");
1150             ret = OC_STACK_ERROR;
1151             goto exit;
1152         }
1153         resType = resType->next;
1154     }
1155
1156     resInterface = resourcePtr->rsrcInterface;
1157     while (resInterface)
1158     {
1159         if (!OCRepPayloadAddInterface(tempPayload, resInterface->name))
1160         {
1161             OIC_LOG(ERROR, TAG, "Failed to add interface");
1162             ret = OC_STACK_ERROR;
1163             goto exit;
1164         }
1165         resInterface = resInterface->next;
1166     }
1167     if (!OCRepPayloadSetPropString(tempPayload, OC_RSRVD_INTROSPECTION_NAME, OC_RSRVD_INTROSPECTION_NAME_VALUE))
1168     {
1169         OIC_LOG(ERROR, TAG, "Failed to set Name property.");
1170         ret = OC_STACK_ERROR;
1171         goto exit;
1172     }
1173
1174     // Figure out which protocols this endpoint supports
1175     if (resourcePtr->endpointType & OC_COAP)
1176     {
1177         if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAP_STR))
1178         {
1179             dimensions[0]++;
1180         }
1181     }
1182     if (resourcePtr->endpointType & OC_COAPS)
1183     {
1184         if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAPS_STR))
1185         {
1186             dimensions[0]++;
1187         }
1188     }
1189 #ifdef TCP_ADAPTER
1190     if (resourcePtr->endpointType & OC_COAP_TCP)
1191     {
1192         if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAP_STR))
1193         {
1194             dimensions[0]++;
1195         }
1196     }
1197     if (resourcePtr->endpointType & OC_COAPS_TCP)
1198     {
1199         if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAPS_STR))
1200         {
1201             dimensions[0]++;
1202         }
1203     }
1204 #endif
1205 #ifdef HTTP_ADAPTER
1206     if (resourcePtr->endpointType & OC_HTTP)
1207     {
1208         if (OC_STACK_OK == AddProtocolToLL(&protoLL, HTTP_STR))
1209         {
1210             dimensions[0]++;
1211         }
1212     }
1213     if (resourcePtr->endpointType & OC_HTTPS)
1214     {
1215         if (OC_STACK_OK == AddProtocolToLL(&protoLL, HTTPS_STR))
1216         {
1217             dimensions[0]++;
1218         }
1219     }
1220 #endif
1221 #ifdef EDR_ADAPTER
1222     if (resourcePtr->endpointType & OC_COAP_RFCOMM)
1223     {
1224         if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAP_STR))
1225         {
1226             dimensions[0]++;
1227         }
1228     }
1229 #endif
1230     // Add a urlInfo object for each protocol supported
1231     if (dimensions[0] >= 0)
1232     {
1233         urlInfoPayload = (OCRepPayload **)OICMalloc(dimensions[0] * sizeof(OCRepPayload));
1234         if (urlInfoPayload)
1235         {
1236             OCStringLL *proto = protoLL;
1237             size_t i = 0;
1238             while (proto)
1239             {
1240                 urlInfoPayload[i] = BuildUrlInfoWithProtocol(proto->value);
1241                 if (!urlInfoPayload[i])
1242                 {
1243                     OIC_LOG(ERROR, TAG, "Unable to build urlInfo object for protocol");
1244                     ret = OC_STACK_ERROR;
1245                     goto exit;
1246                 }
1247                 proto = proto->next;
1248                 i++;
1249             }
1250             if (!OCRepPayloadSetPropObjectArrayAsOwner(tempPayload,
1251                                                        OC_RSRVD_INTROSPECTION_URL_INFO,
1252                                                        urlInfoPayload,
1253                                                        dimensions))
1254             {
1255                 OIC_LOG(ERROR, TAG, "Unable to add urlInfo object to introspection payload ");
1256                 ret = OC_STACK_ERROR;
1257                 goto exit;
1258             }
1259         }
1260         else
1261         {
1262             OIC_LOG(ERROR, TAG, "Unable to allocate memory for urlInfo ");
1263             ret = OC_STACK_NO_MEMORY;
1264             goto exit;
1265         }
1266     }
1267
1268     if (!*payload)
1269     {
1270         *payload = tempPayload;
1271     }
1272     else
1273     {
1274         OCRepPayloadAppend(*payload, tempPayload);
1275     }
1276 exit:
1277     if (ret != OC_STACK_OK)
1278     {
1279         OCRepPayloadDestroy(tempPayload);
1280         if (urlInfoPayload)
1281         {
1282             OICFree(urlInfoPayload);
1283         }
1284     }
1285     FreeProtocolLL(protoLL);
1286
1287     return OC_STACK_OK;
1288 }
1289
1290 OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
1291                                            OCDiscoveryPayload *payload,
1292                                            OCDevAddr *devAddr,
1293                                            CAEndpoint_t *networkInfo,
1294                                            size_t infoSize)
1295 {
1296     if (!resourcePtr || !payload)
1297     {
1298         return OC_STACK_INVALID_PARAM;
1299     }
1300     uint16_t securePort = 0;
1301     if (resourcePtr->resourceProperties & OC_SECURE)
1302     {
1303        if (GetSecurePortInfo(devAddr, &securePort) != OC_STACK_OK)
1304        {
1305            securePort = 0;
1306        }
1307     }
1308
1309     bool isVirtual = false;
1310     if (GetTypeOfVirtualURI(resourcePtr->uri) != OC_UNKNOWN_URI)
1311     {
1312         isVirtual = true;
1313     }
1314 #ifdef TCP_ADAPTER
1315     uint16_t tcpPort = 0;
1316     GetTCPPortInfo(devAddr, &tcpPort, (resourcePtr->resourceProperties & OC_SECURE));
1317
1318     OCDiscoveryPayloadAddResourceWithEps(payload, resourcePtr, securePort,
1319                                          isVirtual, networkInfo, infoSize, devAddr, tcpPort);
1320 #else
1321     OCDiscoveryPayloadAddResourceWithEps(payload, resourcePtr, securePort,
1322                                          isVirtual, networkInfo, infoSize, devAddr);
1323 #endif
1324
1325     return OC_STACK_OK;
1326 }
1327
1328 OCResource *FindResourceByUri(const char* resourceUri)
1329 {
1330     if(!resourceUri)
1331     {
1332         return NULL;
1333     }
1334
1335     OCResource * pointer = headResource;
1336     while (pointer)
1337     {
1338         if (strcmp(resourceUri, pointer->uri) == 0)
1339         {
1340             return pointer;
1341         }
1342         pointer = pointer->next;
1343     }
1344     OIC_LOG_V(INFO, TAG, "Resource %s not found", resourceUri);
1345     return NULL;
1346 }
1347
1348 OCStackResult CheckRequestsEndpoint(const OCDevAddr *reqDevAddr,
1349                                     OCTpsSchemeFlags resTpsFlags)
1350 {
1351     if (!reqDevAddr)
1352     {
1353         OIC_LOG(ERROR, TAG, "OCDevAddr* is NULL!!!");
1354         return OC_STACK_INVALID_PARAM;
1355     }
1356
1357     OCTpsSchemeFlags reqTpsFlags = OC_NO_TPS;
1358     OCStackResult result = OCGetMatchedTpsFlags((CATransportAdapter_t)reqDevAddr->adapter,
1359                                   (CATransportFlags_t)reqDevAddr->flags, &reqTpsFlags);
1360
1361     if (result != OC_STACK_OK)
1362     {
1363         OIC_LOG_V(ERROR, TAG, "Failed at get TPS flags. errcode is %d", result);
1364         return result;
1365     }
1366
1367     // bit compare between request tps flags and resource tps flags
1368     if (reqTpsFlags & resTpsFlags)
1369     {
1370         OIC_LOG(INFO, TAG, "Request come from registered TPS");
1371         return OC_STACK_OK;
1372     }
1373     else
1374     {
1375         OIC_LOG(ERROR, TAG, "Request come from unregistered TPS!!!");
1376         return OC_STACK_BAD_ENDPOINT;
1377     }
1378 }
1379
1380 OCStackResult DetermineResourceHandling (const OCServerRequest *request,
1381                                          ResourceHandling *handling,
1382                                          OCResource **resource)
1383 {
1384     if(!request || !handling || !resource)
1385     {
1386         return OC_STACK_INVALID_PARAM;
1387     }
1388
1389     OIC_LOG_V(INFO, TAG, "DetermineResourceHandling for %s", request->resourceUrl);
1390
1391     // Check if virtual resource
1392     if (GetTypeOfVirtualURI(request->resourceUrl) != OC_UNKNOWN_URI)
1393     {
1394         OIC_LOG_V (INFO, TAG, "%s is virtual", request->resourceUrl);
1395         *handling = OC_RESOURCE_VIRTUAL;
1396         *resource = headResource;
1397         return OC_STACK_OK;
1398     }
1399     if (strlen((const char*)(request->resourceUrl)) == 0)
1400     {
1401         // Resource URL not specified
1402         *handling = OC_RESOURCE_NOT_SPECIFIED;
1403         return OC_STACK_NO_RESOURCE;
1404     }
1405     else
1406     {
1407         OCResource *resourcePtr = FindResourceByUri((const char*)request->resourceUrl);
1408         *resource = resourcePtr;
1409
1410         // Checking resource TPS flags if resource exist in stack.
1411         if (resourcePtr)
1412         {
1413             OCStackResult result = CheckRequestsEndpoint(&(request->devAddr), resourcePtr->endpointType);
1414
1415             if (result != OC_STACK_OK)
1416             {
1417                 if (result == OC_STACK_BAD_ENDPOINT)
1418                 {
1419                     OIC_LOG(ERROR, TAG, "Request come from bad endpoint. ignore request!!!");
1420                     return OC_STACK_BAD_ENDPOINT;
1421                 }
1422                 else
1423                 {
1424                     OIC_LOG_V(ERROR, TAG, "Failed at get tps flag errcode: %d", result);
1425                     return result;
1426                 }
1427             }
1428         }
1429
1430         if (!resourcePtr)
1431         {
1432             if(defaultDeviceHandler)
1433             {
1434                 *handling = OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER;
1435                 return OC_STACK_OK;
1436             }
1437
1438             // Resource does not exist
1439             // and default device handler does not exist
1440             *handling = OC_RESOURCE_NOT_SPECIFIED;
1441             return OC_STACK_NO_RESOURCE;
1442         }
1443
1444         if (resourcePtr && resourcePtr->rsrcChildResourcesHead != NULL)
1445         {
1446             // Collection resource
1447             if (resourcePtr->entityHandler != defaultResourceEHandler)
1448             {
1449                 *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER;
1450                 return OC_STACK_OK;
1451             }
1452             else
1453             {
1454                 *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER;
1455                 return OC_STACK_OK;
1456             }
1457         }
1458         else
1459         {
1460             // Resource not a collection
1461             if (resourcePtr->entityHandler != defaultResourceEHandler)
1462             {
1463                 *handling = OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER;
1464                 return OC_STACK_OK;
1465             }
1466             else
1467             {
1468                 *handling = OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER;
1469                 return OC_STACK_OK;
1470             }
1471         }
1472     }
1473 }
1474
1475 OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
1476 {
1477     OCStackResult result;
1478
1479     switch (ehResult)
1480     {
1481         case OC_EH_OK:
1482         case OC_EH_CONTENT:
1483         case OC_EH_VALID:
1484             result = OC_STACK_OK;
1485             break;
1486         case OC_EH_SLOW:
1487             result = OC_STACK_SLOW_RESOURCE;
1488             break;
1489         case OC_EH_ERROR:
1490             result = OC_STACK_ERROR;
1491             break;
1492         case OC_EH_FORBIDDEN:
1493             result = OC_STACK_FORBIDDEN_REQ;
1494             break;
1495         case OC_EH_INTERNAL_SERVER_ERROR:
1496             result = OC_STACK_INTERNAL_SERVER_ERROR;
1497             break;
1498         case OC_EH_RESOURCE_CREATED:
1499             result = OC_STACK_RESOURCE_CREATED;
1500             break;
1501         case OC_EH_RESOURCE_DELETED:
1502             result = OC_STACK_RESOURCE_DELETED;
1503             break;
1504         case OC_EH_CHANGED:
1505             result = OC_STACK_RESOURCE_CHANGED;
1506             break;
1507         case OC_EH_RESOURCE_NOT_FOUND:
1508             result = OC_STACK_NO_RESOURCE;
1509             break;
1510         default:
1511             result = OC_STACK_ERROR;
1512     }
1513
1514     return result;
1515 }
1516
1517 static bool resourceMatchesRTFilter(OCResource *resource, char *resourceTypeFilter)
1518 {
1519     if (!resource)
1520     {
1521         return false;
1522     }
1523
1524     // Null is analogous to no filter.i.e. query is of form /oic/res?if=oic.if.baseline or /oic/res,
1525     // without rt query.
1526     if (NULL == resourceTypeFilter)
1527     {
1528         return true;
1529     }
1530
1531     // Empty resourceType filter is analogous to error query
1532     // It is an error as query is of form /oic/res?rt=
1533     if (0 == strlen(resourceTypeFilter))
1534     {
1535         return false;
1536     }
1537
1538     for (OCResourceType *rtPtr = resource->rsrcType; rtPtr; rtPtr = rtPtr->next)
1539     {
1540         if (0 == strcmp(rtPtr->resourcetypename, resourceTypeFilter))
1541         {
1542             return true;
1543         }
1544     }
1545
1546     OIC_LOG_V(INFO, TAG, "%s does not contain rt=%s.", resource->uri, resourceTypeFilter);
1547     return false;
1548 }
1549
1550 static bool resourceMatchesIFFilter(OCResource *resource, char *interfaceFilter)
1551 {
1552     if (!resource)
1553     {
1554         return false;
1555     }
1556
1557     // Null is analogous to no filter i.e. query is of form /oic/res?rt=core.light or /oic/res,
1558     // without if query.
1559     if (NULL == interfaceFilter)
1560     {
1561         return true;
1562     }
1563
1564     // Empty interface filter is analogous to error query
1565     // It is an error as query is of form /oic/res?if=
1566     if (0 == strlen(interfaceFilter))
1567     {
1568         return false;
1569     }
1570
1571     for (OCResourceInterface *ifPtr = resource->rsrcInterface; ifPtr; ifPtr = ifPtr->next)
1572     {
1573         if (0 == strcmp(ifPtr->name, interfaceFilter) ||
1574             0 == strcmp(OC_RSRVD_INTERFACE_LL, interfaceFilter) ||
1575             0 == strcmp(OC_RSRVD_INTERFACE_DEFAULT, interfaceFilter))
1576         {
1577             return true;
1578         }
1579     }
1580
1581     OIC_LOG_V(INFO, TAG, "%s does not contain if=%s.", resource->uri, interfaceFilter);
1582     return false;
1583 }
1584
1585 /*
1586  * If the filters are null, they will be assumed to NOT be present
1587  * and the resource will not be matched against them.
1588  * Function will return true if all non null AND non empty filters passed in find a match.
1589  */
1590 static bool includeThisResourceInResponse(OCResource *resource,
1591                                           char *interfaceFilter,
1592                                           char *resourceTypeFilter)
1593 {
1594     if (!resource)
1595     {
1596         OIC_LOG(ERROR, TAG, "Invalid resource");
1597         return false;
1598     }
1599
1600     if (resource->resourceProperties & OC_EXPLICIT_DISCOVERABLE)
1601     {
1602         /*
1603          * At least one valid filter should be available to
1604          * include the resource in discovery response
1605          */
1606         if (!(resourceTypeFilter && *resourceTypeFilter))
1607         {
1608             OIC_LOG_V(INFO, TAG, "%s no query string for EXPLICIT_DISCOVERABLE\
1609                 resource", resource->uri);
1610             return false;
1611         }
1612     }
1613     else if (!(resource->resourceProperties & OC_ACTIVE) ||
1614          !(resource->resourceProperties & OC_DISCOVERABLE))
1615     {
1616         OIC_LOG_V(INFO, TAG, "%s not ACTIVE or DISCOVERABLE", resource->uri);
1617         return false;
1618     }
1619
1620     return resourceMatchesIFFilter(resource, interfaceFilter) &&
1621            resourceMatchesRTFilter(resource, resourceTypeFilter);
1622 }
1623
1624 OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCResource *resource,
1625                                 OCPayload *discoveryPayload, OCEntityHandlerResult ehResult)
1626 {
1627     OCEntityHandlerResponse *response = NULL;
1628     OCStackResult result = OC_STACK_ERROR;
1629
1630     response = (OCEntityHandlerResponse *)OICCalloc(1, sizeof(*response));
1631     VERIFY_PARAM_NON_NULL(TAG, response, "Failed allocating OCEntityHandlerResponse");
1632
1633     response->ehResult = ehResult;
1634     response->payload = discoveryPayload;
1635     response->persistentBufferFlag = 0;
1636     response->requestHandle = (OCRequestHandle) request;
1637     response->resourceHandle = (OCResourceHandle) resource;
1638
1639     result = OCDoResponse(response);
1640
1641     OICFree(response);
1642     return result;
1643
1644 exit:
1645     return OC_STACK_NO_MEMORY;
1646 }
1647
1648 static OCStackResult EHRequest(OCEntityHandlerRequest *ehRequest, OCPayloadType type,
1649     OCServerRequest *request, OCResource *resource)
1650 {
1651     return FormOCEntityHandlerRequest(ehRequest,
1652                                      (OCRequestHandle)request,
1653                                      request->method,
1654                                      &request->devAddr,
1655                                      (OCResourceHandle)resource,
1656                                      request->query,
1657                                      type,
1658                                      request->payload,
1659                                      request->payloadSize,
1660                                      request->numRcvdVendorSpecificHeaderOptions,
1661                                      request->rcvdVendorSpecificHeaderOptions,
1662                                      (OCObserveAction)(request->notificationFlag ? OC_OBSERVE_NO_OPTION :
1663                                                        request->observationOption),
1664                                      (OCObservationId)0,
1665                                      request->coapID);
1666 }
1667
1668 #ifdef RD_SERVER
1669 /**
1670  * Find resources at the resource directory server. These resources are not local resources but
1671  * remote resources.
1672  *
1673  * @param interfaceQuery The interface query parameter.
1674  * @param resourceTypeQuery The resourceType query parameter.
1675  * @param discPayload The payload that will be added with the resource information if found at RD.
1676  *
1677  * @return ::OC_STACK_OK if any resources are found else ::OC_STACK_NO_RESOURCE.
1678  * In case if RD server is not started, it returns ::OC_STACK_NO_RESOURCE.
1679  */
1680 static OCStackResult findResourcesAtRD(const char *interfaceQuery,
1681                                        const char *resourceTypeQuery, OCDiscoveryPayload **discPayload)
1682 {
1683     OCStackResult result = OC_STACK_NO_RESOURCE;
1684     if (OCGetResourceHandleAtUri(OC_RSRVD_RD_URI) != NULL)
1685     {
1686         result = OCRDDatabaseDiscoveryPayloadCreate(interfaceQuery, resourceTypeQuery,
1687             (*discPayload) ? &(*discPayload)->next : discPayload);
1688     }
1689     if ((*discPayload) && (*discPayload)->resources)
1690     {
1691         result = OC_STACK_OK;
1692     }
1693     return result;
1694 }
1695 #endif
1696
1697 /**
1698  * Creates a discovery payload and add device id information. This information is included in all
1699  * /oic/res response.
1700  *
1701  * @param payload  payload that will have memory alllocated and device id information added.
1702  *
1703  * @return ::OC_STACK_OK if successful in allocating memory and adding ID information.
1704  * ::OC_STACK_NO_MEMORY if failed allocating the memory.
1705  */
1706 static OCStackResult discoveryPayloadCreateAndAddDeviceId(OCPayload **payload)
1707 {
1708     if (*payload)
1709     {
1710         OIC_LOG(DEBUG, TAG, "Payload is already allocated");
1711         return OC_STACK_OK;
1712     }
1713
1714     *payload = (OCPayload *) OCDiscoveryPayloadCreate();
1715     VERIFY_PARAM_NON_NULL(TAG, *payload, "Failed adding device id to discovery payload.");
1716
1717     {
1718         OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)*payload;
1719         discPayload->sid = (char *)OICCalloc(1, UUID_STRING_SIZE);
1720         VERIFY_PARAM_NON_NULL(TAG, discPayload->sid, "Failed adding device id to discovery payload.");
1721
1722         const char* uid = OCGetServerInstanceIDString();
1723         if (uid)
1724         {
1725             memcpy(discPayload->sid, uid, UUID_STRING_SIZE);
1726         }
1727
1728     }
1729     return OC_STACK_OK;
1730 exit:
1731     OCPayloadDestroy(*payload);
1732     return OC_STACK_NO_MEMORY;
1733 }
1734
1735 /**
1736  * Add the common properties to the payload, they are only included in case of oic.if.baseline response.
1737  *
1738  * @param discPayload payload that will have the baseline information included.
1739  *
1740  * @return ::OC_STACK_OK if successful in adding all the information. ::OC_STACK_NO_MEMORY if failed
1741  * allocating the memory for the baseline information.
1742  */
1743 static OCStackResult addDiscoveryBaselineCommonProperties(OCDiscoveryPayload *discPayload)
1744 {
1745     if (!discPayload)
1746     {
1747         OIC_LOG(ERROR, TAG, "Payload is not allocated");
1748         return OC_STACK_INVALID_PARAM;
1749     }
1750
1751     OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, (void **)&discPayload->name);
1752
1753     discPayload->type = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1754     VERIFY_PARAM_NON_NULL(TAG, discPayload->type, "Failed adding rt to discovery payload.");
1755     discPayload->type->value = OICStrdup(OC_RSRVD_RESOURCE_TYPE_RES);
1756     VERIFY_PARAM_NON_NULL(TAG, discPayload->type, "Failed adding rt value to discovery payload.");
1757
1758     OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_LL);
1759     OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_DEFAULT);
1760     VERIFY_PARAM_NON_NULL(TAG, discPayload->iface, "Failed adding if to discovery payload.");
1761
1762     return OC_STACK_OK;
1763
1764 exit:
1765     return OC_STACK_NO_MEMORY;
1766 }
1767
1768 static bool isUnicast(OCServerRequest *request)
1769 {
1770     bool isMulticast = request->devAddr.flags & OC_MULTICAST;
1771     return (isMulticast == false &&
1772            (request->devAddr.adapter != OC_ADAPTER_RFCOMM_BTEDR) &&
1773            (request->devAddr.adapter != OC_ADAPTER_GATT_BTLE));
1774 }
1775
1776 static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource)
1777 {
1778     if (!request || !resource)
1779     {
1780         return OC_STACK_INVALID_PARAM;
1781     }
1782
1783     OCPayload* payload = NULL;
1784     char *interfaceQuery = NULL;
1785     char *resourceTypeQuery = NULL;
1786
1787     OIC_LOG(INFO, TAG, "Entering HandleVirtualResource");
1788
1789     OCVirtualResources virtualUriInRequest = GetTypeOfVirtualURI (request->resourceUrl);
1790
1791 #ifdef TCP_ADAPTER
1792     if (OC_KEEPALIVE_RESOURCE_URI == virtualUriInRequest)
1793     {
1794         // Received request for a keepalive
1795         OIC_LOG(INFO, TAG, "Request is for KeepAlive Request");
1796         return HandleKeepAliveRequest(request, resource);
1797     }
1798 #endif
1799
1800     OCStackResult discoveryResult = OC_STACK_ERROR;
1801     if (request->method == OC_REST_PUT || request->method == OC_REST_POST ||
1802         request->method == OC_REST_DELETE)
1803     {
1804         OIC_LOG_V(ERROR, TAG, "Resource : %s not permitted for method: %d",
1805             request->resourceUrl, request->method);
1806         return OC_STACK_UNAUTHORIZED_REQ;
1807     }
1808
1809     discoveryResult = HandleVirtualObserveRequest(request);
1810     if (discoveryResult == OC_STACK_DUPLICATE_REQUEST)
1811     {
1812         // server requests are usually free'd when the response is sent out
1813         // for the request in ocserverrequest.c : HandleSingleResponse()
1814         // Since we are making an early return and not responding, the server request
1815         // needs to be deleted.
1816         FindAndDeleteServerRequest (request);
1817         discoveryResult = OC_STACK_OK;
1818         goto exit;
1819     }
1820     else if (discoveryResult != OC_STACK_OK)
1821     {
1822         goto exit;
1823     }
1824
1825     // Step 1: Generate the response to discovery request
1826     if (virtualUriInRequest == OC_WELL_KNOWN_URI
1827 #ifdef MQ_BROKER
1828             || virtualUriInRequest == OC_MQ_BROKER_URI
1829 #endif
1830             )
1831     {
1832         char *interfaceQuery = NULL;
1833         char *resourceTypeQuery = NULL;
1834
1835         CAEndpoint_t *networkInfo = NULL;
1836         size_t infoSize = 0;
1837
1838         CAResult_t caResult = CAGetNetworkInformation(&networkInfo, &infoSize);
1839         if (CA_STATUS_FAILED == caResult)
1840         {
1841             OIC_LOG(ERROR, TAG, "CAGetNetworkInformation has error on parsing network infomation");
1842             return OC_STACK_ERROR;
1843         }
1844
1845         discoveryResult = getQueryParamsForFiltering (virtualUriInRequest, request->query,
1846                 &interfaceQuery, &resourceTypeQuery);
1847         VERIFY_SUCCESS(discoveryResult);
1848
1849         if (!interfaceQuery && !resourceTypeQuery)
1850         {
1851             // If no query is sent, default interface is used i.e. oic.if.ll.
1852             interfaceQuery = OICStrdup(OC_RSRVD_INTERFACE_LL);
1853         }
1854
1855         discoveryResult = discoveryPayloadCreateAndAddDeviceId(&payload);
1856         VERIFY_PARAM_NON_NULL(TAG, payload, "Failed creating Discovery Payload.");
1857         VERIFY_SUCCESS(discoveryResult);
1858
1859         OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)payload;
1860         if (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_DEFAULT))
1861         {
1862             discoveryResult = addDiscoveryBaselineCommonProperties(discPayload);
1863             VERIFY_SUCCESS(discoveryResult);
1864         }
1865         OCResourceProperty prop = OC_DISCOVERABLE;
1866 #ifdef MQ_BROKER
1867         prop = (OC_MQ_BROKER_URI == virtualUriInRequest) ? OC_MQ_BROKER : prop;
1868 #endif
1869         for (; resource && discoveryResult == OC_STACK_OK; resource = resource->next)
1870         {
1871             // This case will handle when no resource type and it is oic.if.ll.
1872             // Do not assume check if the query is ll
1873             if (!resourceTypeQuery &&
1874                 (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_LL)))
1875             {
1876                 // Only include discoverable type
1877                 if (resource->resourceProperties & prop)
1878                 {
1879                     discoveryResult = BuildVirtualResourceResponse(resource,
1880                                                                    discPayload,
1881                                                                    &request->devAddr,
1882                                                                    networkInfo,
1883                                                                    infoSize);
1884                 }
1885             }
1886             else if (includeThisResourceInResponse(resource, interfaceQuery, resourceTypeQuery))
1887             {
1888                 discoveryResult = BuildVirtualResourceResponse(resource,
1889                                                                discPayload,
1890                                                                &request->devAddr,
1891                                                                networkInfo,
1892                                                                infoSize);
1893             }
1894             else
1895             {
1896                 discoveryResult = OC_STACK_OK;
1897             }
1898         }
1899         if (discPayload->resources == NULL)
1900         {
1901             discoveryResult = OC_STACK_NO_RESOURCE;
1902             OCPayloadDestroy(payload);
1903             payload = NULL;
1904         }
1905
1906         if (networkInfo)
1907         {
1908             OICFree(networkInfo);
1909         }
1910 #ifdef RD_SERVER
1911         discoveryResult = findResourcesAtRD(interfaceQuery, resourceTypeQuery, (OCDiscoveryPayload **)&payload);
1912 #endif
1913     }
1914     else if (virtualUriInRequest == OC_DEVICE_URI)
1915     {
1916         OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_DEVICE_URI);
1917         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Device URI not found.");
1918         discoveryResult = BuildDevicePlatformPayload(resourcePtr, (OCRepPayload **)&payload, true);
1919     }
1920     else if (virtualUriInRequest == OC_PLATFORM_URI)
1921     {
1922         OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_PLATFORM_URI);
1923         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Platform URI not found.");
1924         discoveryResult = BuildDevicePlatformPayload(resourcePtr, (OCRepPayload **)&payload, false);
1925     }
1926 #ifdef ROUTING_GATEWAY
1927     else if (OC_GATEWAY_URI == virtualUriInRequest)
1928     {
1929         // Received request for a gateway
1930         OIC_LOG(INFO, TAG, "Request is for Gateway Virtual Request");
1931         discoveryResult = RMHandleGatewayRequest(request, resource);
1932     }
1933 #endif
1934     else if (OC_INTROSPECTION_URI == virtualUriInRequest)
1935     {
1936         // Received request for introspection
1937         OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_INTROSPECTION_URI);
1938         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Introspection URI not found.");
1939         discoveryResult = BuildIntrospectionResponseRepresentation(resourcePtr, (OCRepPayload **)&payload, &request->devAddr);
1940         OIC_LOG(INFO, TAG, "Request is for Introspection");
1941     }
1942     else if (OC_INTROSPECTION_PAYLOAD_URI == virtualUriInRequest)
1943     {
1944         // Received request for introspection payload
1945         OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_INTROSPECTION_PAYLOAD_URI);
1946         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Introspection Payload URI not found.");
1947         discoveryResult = BuildIntrospectionPayloadResponse(resourcePtr, (OCRepPayload **)&payload, &request->devAddr);
1948         OIC_LOG(INFO, TAG, "Request is for Introspection Payload");
1949     }
1950     /**
1951      * Step 2: Send the discovery response
1952      *
1953      * Iotivity should respond to discovery requests in below manner:
1954      * 1)If query filter matching fails and discovery request is multicast,
1955      *   it should NOT send any response.
1956      * 2)If query filter matching fails and discovery request is unicast,
1957      *   it should send an error(RESOURCE_NOT_FOUND - 404) response.
1958      * 3)If Server does not have any 'DISCOVERABLE' resources and discovery
1959      *   request is multicast, it should NOT send any response.
1960      * 4)If Server does not have any 'DISCOVERABLE' resources and discovery
1961      *   request is unicast, it should send an error(RESOURCE_NOT_FOUND - 404) response.
1962      */
1963
1964 #ifdef WITH_PRESENCE
1965     if ((virtualUriInRequest == OC_PRESENCE) &&
1966         (resource->resourceProperties & OC_ACTIVE))
1967     {
1968         // Need to send ACK when the request is CON.
1969         if (request->qos == OC_HIGH_QOS)
1970         {
1971             CAEndpoint_t endpoint = { .adapter = CA_DEFAULT_ADAPTER };
1972             CopyDevAddrToEndpoint(&request->devAddr, &endpoint);
1973             SendDirectStackResponse(&endpoint, request->coapID, CA_EMPTY, CA_MSG_ACKNOWLEDGE,
1974                                     0, NULL, NULL, 0, NULL, CA_RESPONSE_FOR_RES);
1975         }
1976         FindAndDeleteServerRequest(request);
1977
1978         // Presence uses observer notification api to respond via SendPresenceNotification.
1979         SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
1980     }
1981     else
1982 #endif
1983 #if ROUTING_GATEWAY
1984     // Gateway uses the RMHandleGatewayRequest to respond to the request.
1985     if (OC_GATEWAY_URI != virtualUriInRequest)
1986 #endif
1987     {
1988         OIC_LOG_PAYLOAD(DEBUG, payload);
1989         if(discoveryResult == OC_STACK_OK)
1990         {
1991
1992             SendNonPersistantDiscoveryResponse(request, resource, payload, OC_EH_OK);
1993         }
1994         else // Error handling
1995         {
1996             if (isUnicast(request))
1997             {
1998                 OIC_LOG_V(ERROR, TAG, "Sending a (%d) error to (%d) discovery request",
1999                     discoveryResult, virtualUriInRequest);
2000                 SendNonPersistantDiscoveryResponse(request, resource, NULL,
2001                     (discoveryResult == OC_STACK_NO_RESOURCE) ?
2002                         OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR);
2003             }
2004             else // Multicast
2005             {
2006                 // Ignoring the discovery request as per RFC 7252, Section #8.2
2007                 OIC_LOG(INFO, TAG, "Silently ignoring the request since no useful data to send.");
2008                 // the request should be removed.
2009                 // since it never remove and causes a big memory waste.
2010                 FindAndDeleteServerRequest(request);
2011             }
2012             discoveryResult = OC_STACK_CONTINUE;
2013         }
2014     }
2015
2016 exit:
2017     if (interfaceQuery)
2018     {
2019         OICFree(interfaceQuery);
2020     }
2021
2022     if (resourceTypeQuery)
2023     {
2024         OICFree(resourceTypeQuery);
2025     }
2026     OCPayloadDestroy(payload);
2027
2028     // To ignore the message, OC_STACK_CONTINUE is sent
2029     return discoveryResult;
2030 }
2031
2032 static OCStackResult
2033 HandleDefaultDeviceEntityHandler(OCServerRequest *request)
2034 {
2035     if (!request)
2036     {
2037         return OC_STACK_INVALID_PARAM;
2038     }
2039
2040     OCEntityHandlerResult ehResult = OC_EH_ERROR;
2041     OCEntityHandlerRequest ehRequest = {0};
2042     OIC_LOG(INFO, TAG, "Entering HandleResourceWithDefaultDeviceEntityHandler");
2043     OCStackResult result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, NULL);
2044     VERIFY_SUCCESS(result);
2045
2046     // At this point we know for sure that defaultDeviceHandler exists
2047     ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
2048                                   (char*) request->resourceUrl, defaultDeviceHandlerCallbackParameter);
2049     if(ehResult == OC_EH_SLOW)
2050     {
2051         OIC_LOG(INFO, TAG, "This is a slow resource");
2052         request->slowFlag = 1;
2053     }
2054     else if(ehResult == OC_EH_ERROR)
2055     {
2056         FindAndDeleteServerRequest(request);
2057     }
2058     result = EntityHandlerCodeToOCStackCode(ehResult);
2059 exit:
2060     OCPayloadDestroy(ehRequest.payload);
2061     return result;
2062 }
2063
2064 static OCStackResult
2065 HandleResourceWithEntityHandler(OCServerRequest *request,
2066                                 OCResource *resource)
2067 {
2068     if(!request || ! resource)
2069     {
2070         return OC_STACK_INVALID_PARAM;
2071     }
2072
2073     OCStackResult result = OC_STACK_ERROR;
2074     OCEntityHandlerResult ehResult = OC_EH_ERROR;
2075     OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
2076     ResourceObserver *resObs = NULL;
2077
2078     OCEntityHandlerRequest ehRequest = {0};
2079
2080     OIC_LOG(INFO, TAG, "Entering HandleResourceWithEntityHandler");
2081     OCPayloadType type = PAYLOAD_TYPE_REPRESENTATION;
2082     // check the security resource
2083     if (request && request->resourceUrl && SRMIsSecurityResourceURI(request->resourceUrl))
2084     {
2085         type = PAYLOAD_TYPE_SECURITY;
2086
2087     }
2088
2089     result = EHRequest(&ehRequest, type, request, resource);
2090     VERIFY_SUCCESS(result);
2091
2092     if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
2093     {
2094         OIC_LOG(INFO, TAG, "No observation requested");
2095         ehFlag = OC_REQUEST_FLAG;
2096     }
2097     else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER)
2098     {
2099         OIC_LOG(INFO, TAG, "Observation registration requested");
2100
2101         ResourceObserver *obs = GetObserverUsingToken (request->requestToken,
2102                                     request->tokenLength);
2103
2104         if (obs)
2105         {
2106             OIC_LOG (INFO, TAG, "Observer with this token already present");
2107             OIC_LOG (INFO, TAG, "Possibly re-transmitted CON OBS request");
2108             OIC_LOG (INFO, TAG, "Not adding observer. Not responding to client");
2109             OIC_LOG (INFO, TAG, "The first request for this token is already ACKED.");
2110
2111             // server requests are usually free'd when the response is sent out
2112             // for the request in ocserverrequest.c : HandleSingleResponse()
2113             // Since we are making an early return and not responding, the server request
2114             // needs to be deleted.
2115             FindAndDeleteServerRequest (request);
2116             return OC_STACK_OK;
2117         }
2118
2119         result = GenerateObserverId(&ehRequest.obsInfo.obsId);
2120         VERIFY_SUCCESS(result);
2121
2122         result = AddObserver ((const char*)(request->resourceUrl),
2123                 (const char *)(request->query),
2124                 ehRequest.obsInfo.obsId, request->requestToken, request->tokenLength,
2125                 resource, request->qos, request->acceptFormat,
2126                 request->acceptVersion, &request->devAddr);
2127
2128         if(result == OC_STACK_OK)
2129         {
2130             OIC_LOG(INFO, TAG, "Added observer successfully");
2131             request->observeResult = OC_STACK_OK;
2132             ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
2133         }
2134         else if (result == OC_STACK_RESOURCE_ERROR)
2135         {
2136             OIC_LOG(INFO, TAG, "The Resource is not active, discoverable or observable");
2137             request->observeResult = OC_STACK_ERROR;
2138             ehFlag = OC_REQUEST_FLAG;
2139         }
2140         else
2141         {
2142             // The error in observeResult for the request will be used when responding to this
2143             // request by omitting the observation option/sequence number.
2144             request->observeResult = OC_STACK_ERROR;
2145             OIC_LOG(ERROR, TAG, "Observer Addition failed");
2146             ehFlag = OC_REQUEST_FLAG;
2147             FindAndDeleteServerRequest(request);
2148             goto exit;
2149         }
2150
2151     }
2152     else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER)
2153     {
2154         OIC_LOG(INFO, TAG, "Deregistering observation requested");
2155
2156         resObs = GetObserverUsingToken (request->requestToken, request->tokenLength);
2157
2158         if (NULL == resObs)
2159         {
2160             // Stack does not contain this observation request
2161             // Either token is incorrect or observation list is corrupted
2162             result = OC_STACK_ERROR;
2163             goto exit;
2164         }
2165         ehRequest.obsInfo.obsId = resObs->observeId;
2166         ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
2167
2168         result = DeleteObserverUsingToken (request->requestToken, request->tokenLength);
2169
2170         if(result == OC_STACK_OK)
2171         {
2172             OIC_LOG(INFO, TAG, "Removed observer successfully");
2173             request->observeResult = OC_STACK_OK;
2174             // There should be no observe option header for de-registration response.
2175             // Set as an invalid value here so we can detect it later and remove the field in response.
2176             request->observationOption = MAX_SEQUENCE_NUMBER + 1;
2177         }
2178         else
2179         {
2180             request->observeResult = OC_STACK_ERROR;
2181             OIC_LOG(ERROR, TAG, "Observer Removal failed");
2182             FindAndDeleteServerRequest(request);
2183             goto exit;
2184         }
2185     }
2186     else
2187     {
2188         result = OC_STACK_ERROR;
2189         goto exit;
2190     }
2191
2192     ehResult = resource->entityHandler(ehFlag, &ehRequest, resource->entityHandlerCallbackParam);
2193     if(ehResult == OC_EH_SLOW)
2194     {
2195         OIC_LOG(INFO, TAG, "This is a slow resource");
2196         request->slowFlag = 1;
2197     }
2198     else if(ehResult == OC_EH_ERROR)
2199     {
2200         FindAndDeleteServerRequest(request);
2201     }
2202     result = EntityHandlerCodeToOCStackCode(ehResult);
2203 exit:
2204     OCPayloadDestroy(ehRequest.payload);
2205     return result;
2206 }
2207
2208 static OCStackResult HandleCollectionResourceDefaultEntityHandler(OCServerRequest *request,
2209                                                                   OCResource *resource)
2210 {
2211     if (!request || !resource)
2212     {
2213         return OC_STACK_INVALID_PARAM;
2214     }
2215
2216     OCEntityHandlerRequest ehRequest = {0};
2217     OCStackResult result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, resource);
2218     if(result == OC_STACK_OK)
2219     {
2220         result = DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest);
2221     }
2222
2223     OCPayloadDestroy(ehRequest.payload);
2224     return result;
2225 }
2226
2227 OCStackResult
2228 ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request)
2229 {
2230     OCStackResult ret = OC_STACK_OK;
2231
2232     switch (resHandling)
2233     {
2234         case OC_RESOURCE_VIRTUAL:
2235         {
2236             ret = HandleVirtualResource (request, resource);
2237             break;
2238         }
2239         case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER:
2240         {
2241             ret = HandleDefaultDeviceEntityHandler(request);
2242             break;
2243         }
2244         case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
2245         {
2246             OIC_LOG(INFO, TAG, "OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER");
2247             return OC_STACK_ERROR;
2248         }
2249         case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
2250         {
2251             ret = HandleResourceWithEntityHandler (request, resource);
2252             break;
2253         }
2254         case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
2255         {
2256             ret = HandleResourceWithEntityHandler (request, resource);
2257             break;
2258         }
2259         case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
2260         {
2261             ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
2262             break;
2263         }
2264         case OC_RESOURCE_NOT_SPECIFIED:
2265         {
2266             ret = OC_STACK_NO_RESOURCE;
2267             break;
2268         }
2269         default:
2270         {
2271             OIC_LOG(INFO, TAG, "Invalid Resource Determination");
2272             return OC_STACK_ERROR;
2273         }
2274     }
2275     return ret;
2276 }
2277
2278 OCStackResult OCSetPlatformInfo(OCPlatformInfo info)
2279 {
2280     OCResource *resource = NULL;
2281     if (!info.platformID || !info.manufacturerName)
2282     {
2283         OIC_LOG(ERROR, TAG, "No value specified.");
2284         goto exit;
2285     }
2286     if (0 == strlen(info.platformID) || 0 == strlen(info.manufacturerName))
2287     {
2288         OIC_LOG(ERROR, TAG, "The passed value cannot be empty");
2289         goto exit;
2290     }
2291     if ((info.manufacturerName && strlen(info.manufacturerName) > MAX_PLATFORM_NAME_LENGTH) ||
2292         (info.manufacturerUrl && strlen(info.manufacturerUrl) > MAX_PLATFORM_URL_LENGTH) ||
2293         (info.modelNumber && strlen(info.modelNumber) > MAX_PLATFORM_NAME_LENGTH) ||
2294         (info.platformVersion && strlen(info.platformVersion) > MAX_PLATFORM_NAME_LENGTH) ||
2295         (info.operatingSystemVersion && strlen(info.operatingSystemVersion) > MAX_PLATFORM_NAME_LENGTH) ||
2296         (info.hardwareVersion && strlen(info.hardwareVersion) > MAX_PLATFORM_NAME_LENGTH) ||
2297         (info.firmwareVersion && strlen(info.firmwareVersion) > MAX_PLATFORM_NAME_LENGTH) ||
2298         (info.supportUrl && strlen(info.supportUrl) > MAX_PLATFORM_URL_LENGTH))
2299     {
2300         OIC_LOG(ERROR, TAG, "The passed value is bigger than permitted.");
2301         goto exit;
2302     }
2303
2304     /*
2305      * @todo (IOT-1541) There are several versions of a UUID structure and conversion
2306      * methods scattered around the IoTivity code base.  They need to be combined
2307      * into one PAL API.
2308      */
2309     uint8_t uuid[UUID_SIZE];
2310     if (!OCConvertStringToUuid(info.platformID, uuid))
2311     {
2312         OIC_LOG(ERROR, TAG, "Platform ID is not a UUID.");
2313         goto exit;
2314     }
2315
2316     resource = FindResourceByUri(OC_RSRVD_PLATFORM_URI);
2317     if (!resource)
2318     {
2319         OIC_LOG(ERROR, TAG, "Platform Resource does not exist.");
2320         goto exit;
2321     }
2322     OIC_LOG(INFO, TAG, "Entering OCSetPlatformInfo");
2323     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_PLATFORM_ID, info.platformID));
2324     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_NAME, info.manufacturerName));
2325     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_URL, info.manufacturerUrl);
2326     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MODEL_NUM, info.modelNumber);
2327     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_DATE, info.dateOfManufacture);
2328     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_PLATFORM_VERSION, info.platformVersion);
2329     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_OS_VERSION, info.operatingSystemVersion);
2330     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_HARDWARE_VERSION, info.hardwareVersion);
2331     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_FIRMWARE_VERSION, info.firmwareVersion);
2332     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_SUPPORT_URL, info.supportUrl);
2333     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_SYSTEM_TIME, info.systemTime);
2334     OIC_LOG(INFO, TAG, "Platform parameter initialized successfully.");
2335     return OC_STACK_OK;
2336
2337 exit:
2338     return OC_STACK_INVALID_PARAM;
2339 }
2340
2341 OCStackResult OCSetDeviceInfo(OCDeviceInfo info)
2342 {
2343     OCResource *resource = FindResourceByUri(OC_RSRVD_DEVICE_URI);
2344     if (!resource)
2345     {
2346         OIC_LOG(ERROR, TAG, "Device Resource does not exist.");
2347         goto exit;
2348     }
2349     if (!info.deviceName || info.deviceName[0] == '\0')
2350     {
2351         OIC_LOG(ERROR, TAG, "Null or empty device name.");
2352        return OC_STACK_INVALID_PARAM;
2353     }
2354
2355     if (OCGetServerInstanceIDString() == NULL)
2356     {
2357         OIC_LOG(INFO, TAG, "Device ID generation failed");
2358         goto exit;
2359     }
2360
2361     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, info.deviceName));
2362     for (OCStringLL *temp = info.types; temp; temp = temp->next)
2363     {
2364         if (temp->value)
2365         {
2366             VERIFY_SUCCESS(OCBindResourceTypeToResource(resource, temp->value));
2367         }
2368     }
2369     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_SPEC_VERSION, info.specVersion ?
2370         info.specVersion: OC_SPEC_VERSION));
2371
2372     if (info.dataModelVersions)
2373     {
2374         char *dmv = OCCreateString(info.dataModelVersions);
2375         VERIFY_PARAM_NON_NULL(TAG, dmv, "Failed allocating dataModelVersions");
2376         OCStackResult r = OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION, dmv);
2377         OICFree(dmv);
2378         VERIFY_SUCCESS(r);
2379     }
2380     else
2381     {
2382         VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION,
2383             OC_DATA_MODEL_VERSION));
2384     }
2385     OIC_LOG(INFO, TAG, "Device parameter initialized successfully.");
2386     return OC_STACK_OK;
2387
2388 exit:
2389     return OC_STACK_ERROR;
2390 }
2391
2392 OCStackResult OCGetAttribute(const OCResource *resource, const char *attribute, void **value)
2393 {
2394     if (!resource || !attribute)
2395     {
2396         return OC_STACK_INVALID_PARAM;
2397     }
2398     if (0 == strlen(attribute))
2399     {
2400         return OC_STACK_INVALID_PARAM;
2401     }
2402     for (OCAttribute *temp = resource->rsrcAttributes; temp; temp = temp->next)
2403     {
2404         if (0 == strcmp(attribute, temp->attrName))
2405         {
2406             // A special case as this type return OCStringLL
2407             if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, attribute))
2408             {
2409                 *value = CloneOCStringLL((OCStringLL *)temp->attrValue);
2410                 return OC_STACK_OK;
2411             }
2412             else
2413             {
2414                 *value = OICStrdup((char *)temp->attrValue);
2415                 return OC_STACK_OK;
2416             }
2417         }
2418     }
2419     return OC_STACK_NO_RESOURCE;
2420 }
2421
2422 OCStackResult OCGetPropertyValue(OCPayloadType type, const char *prop, void **value)
2423 {
2424     if (!prop)
2425     {
2426         return OC_STACK_INVALID_PARAM;
2427     }
2428     if (strlen(prop) == 0)
2429     {
2430         return OC_STACK_INVALID_PARAM;
2431     }
2432     if (*value)
2433     {
2434         *value = NULL;
2435     }
2436     OCStackResult res =  OC_STACK_NO_RESOURCE;
2437     if (PAYLOAD_TYPE_DEVICE == type || PAYLOAD_TYPE_PLATFORM == type)
2438     {
2439         const char *pathType = (type == PAYLOAD_TYPE_DEVICE) ? OC_RSRVD_DEVICE_URI : OC_RSRVD_PLATFORM_URI;
2440         OCResource *resource = FindResourceByUri(pathType);
2441         if (!resource)
2442         {
2443             return OC_STACK_NO_RESOURCE;
2444         }
2445
2446         res = OCGetAttribute(resource, prop, value);
2447     }
2448     return res;
2449 }
2450
2451 static OCStackResult SetAttributeInternal(OCResource *resource,
2452                                           const char *attribute,
2453                                           const void *value,
2454                                           bool updateDatabase)
2455 {
2456     OCAttribute *resAttrib = NULL;
2457
2458     // See if the attribute already exists in the list.
2459     for (resAttrib = resource->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
2460     {
2461         if (0 == strcmp(attribute, resAttrib->attrName))
2462         {
2463             // Found, free the old value.
2464             if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName))
2465             {
2466                 OCFreeOCStringLL((OCStringLL *)resAttrib->attrValue);
2467             }
2468             else
2469             {
2470                 OICFree((char *)resAttrib->attrValue);
2471             }
2472             break;
2473         }
2474     }
2475
2476     // If not already in the list, add it.
2477     if (NULL == resAttrib)
2478     {
2479         resAttrib = (OCAttribute *)OICCalloc(1, sizeof(OCAttribute));
2480         VERIFY_PARAM_NON_NULL(TAG, resAttrib, "Failed allocating OCAttribute");
2481         resAttrib->attrName = OICStrdup(attribute);
2482         VERIFY_PARAM_NON_NULL(TAG, resAttrib->attrName, "Failed allocating attribute name");
2483         resAttrib->next = resource->rsrcAttributes;
2484         resource->rsrcAttributes = resAttrib;
2485     }
2486
2487     // Fill in the new value.
2488     if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, attribute))
2489     {
2490         resAttrib->attrValue = OCCreateOCStringLL((char *)value);
2491     }
2492     else
2493     {
2494         resAttrib->attrValue = OICStrdup((char *)value);
2495     }
2496     VERIFY_PARAM_NON_NULL(TAG, resAttrib->attrValue, "Failed allocating attribute value");
2497
2498     // The resource has changed from what is stored in the database. Update the database to
2499     // reflect the new value.
2500     if (updateDatabase)
2501     {
2502         OCDeviceProperties *deviceProperties = NULL;
2503
2504         OCStackResult result = CreateDeviceProperties((const char*)value, &deviceProperties);
2505         if (OC_STACK_OK == result)
2506         {
2507             result = UpdateDevicePropertiesDatabase(deviceProperties);
2508             if (OC_STACK_OK != result)
2509             {
2510                 OIC_LOG(ERROR, TAG, "UpdateDevicePropertiesDatabase failed!");
2511             }
2512
2513             CleanUpDeviceProperties(&deviceProperties);
2514         }
2515         else
2516         {
2517             OIC_LOG(ERROR, TAG, "CreateDeviceProperties failed!");
2518         }
2519     }
2520
2521     return OC_STACK_OK;
2522
2523 exit:
2524     OCDeleteResourceAttributes(resAttrib);
2525     return OC_STACK_NO_MEMORY;
2526 }
2527
2528 static OCStackResult IsDatabaseUpdateNeeded(const char *attribute, const void *value, bool *update)
2529 {
2530     OCStackResult result = OC_STACK_OK;
2531     void *currentPIID = NULL;
2532
2533     if (!attribute || !value || !update)
2534     {
2535         return OC_STACK_INVALID_PARAM;
2536     }
2537
2538     *update = false;
2539
2540     // Protocol Independent ID
2541     if (0 == strcmp(OC_RSRVD_PROTOCOL_INDEPENDENT_ID, attribute))
2542     {
2543         result = OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_PROTOCOL_INDEPENDENT_ID, &currentPIID);
2544         if (OC_STACK_OK == result)
2545         {
2546             // PIID has already been set on the resource and stored in the database. Check to see
2547             // if the value is changing so the database can be updated accordingly.
2548             if (0 != strcmp((char *)currentPIID, (char*)value))
2549             {
2550                 *update = true;
2551             }
2552         }
2553         else if (OC_STACK_NO_RESOURCE == result)
2554         {
2555             // PIID has not been set yet so we should always update the database.
2556             *update = true;
2557             result = OC_STACK_OK;
2558         }
2559         else
2560         {
2561             OIC_LOG_V(ERROR, TAG, 
2562                 "Call to OCGetPropertyValue for the current PIID failed with error: %d", result);
2563         }
2564     }
2565
2566     // Clean Up
2567     OICFreeAndSetToNull(&currentPIID);
2568
2569     return result;
2570 }
2571
2572 OCStackResult OCSetAttribute(OCResource *resource, const char *attribute, const void *value)
2573 {
2574     bool updateDatabase = false;
2575
2576     // Check to see if we also need to update the database for this attribute. If the current
2577     // value matches what is stored in the database we can skip the update and an unnecessary
2578     // write.
2579     if (OC_STACK_OK != IsDatabaseUpdateNeeded(attribute, value, &updateDatabase))
2580     {
2581         OIC_LOG_V(WARNING, TAG, 
2582             "Could not determine if a database update was needed for %s. Proceeding without updating the database.",
2583             attribute);
2584         updateDatabase = false;
2585     }
2586
2587     return SetAttributeInternal(resource, attribute, value, updateDatabase);
2588 }
2589
2590 OCStackResult OCSetPropertyValue(OCPayloadType type, const char *prop, const void *value)
2591 {
2592     if (!prop || !value)
2593     {
2594         return OC_STACK_INVALID_PARAM;
2595     }
2596     if (strlen(prop) == 0)
2597     {
2598         return OC_STACK_INVALID_PARAM;
2599     }
2600
2601     OCStackResult res = OC_STACK_ERROR;
2602     if (PAYLOAD_TYPE_DEVICE == type || PAYLOAD_TYPE_PLATFORM == type)
2603     {
2604         const char *pathType = (type == PAYLOAD_TYPE_DEVICE) ? OC_RSRVD_DEVICE_URI : OC_RSRVD_PLATFORM_URI;
2605         OCResource *resource = FindResourceByUri(pathType);
2606         if (!resource)
2607         {
2608             OIC_LOG(ERROR, TAG, "Resource does not exist.");
2609         }
2610         else
2611         {
2612             res = OCSetAttribute(resource, prop, value);
2613         }
2614     }
2615
2616     return res;
2617 }