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