ae86922134487e6d8f6b204eee4d09495f57ea63
[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         result = 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     OCRepPayload *tempPayload = NULL;
991     OCStackResult ret;
992     char *introspectionData = NULL;
993     size_t size = 0;
994     ret = GetIntrospectionDataFromPS(&introspectionData, &size);
995     if (OC_STACK_OK == ret)
996     {
997         OCRepPayload *tempPayload = OCRepPayloadCreate();
998         if (tempPayload)
999         {
1000             if (OCRepPayloadSetPropStringAsOwner(tempPayload, OC_RSRVD_INTROSPECTION_DATA_NAME, introspectionData))
1001             {
1002                 *payload = tempPayload;
1003             }
1004         }
1005         else
1006         {
1007             ret = OC_STACK_NO_MEMORY;
1008         }
1009     }
1010     if (ret != OC_STACK_OK)
1011     {
1012         OICFree(introspectionData);
1013         OCRepPayloadDestroy(tempPayload);
1014     }
1015
1016     return ret;
1017 }
1018
1019 OCRepPayload *BuildUrlInfoWithProtocol(const char *protocol)
1020 {
1021     OCStackResult result = OC_STACK_OK;
1022     OCRepPayload *urlInfoPayload = OCRepPayloadCreate();
1023     if (!urlInfoPayload)
1024     {
1025         OIC_LOG(ERROR, TAG, "Failed to create a new RepPayload");
1026         result = OC_STACK_NO_MEMORY;
1027         goto exit;
1028     }
1029
1030     if (!OCRepPayloadSetPropString(urlInfoPayload, OC_RSRVD_INTROSPECTION_URL, OC_RSRVD_INTROSPECTION_PAYLOAD_URI))
1031     {
1032         OIC_LOG(ERROR, TAG, "Failed to add url");
1033         result = OC_STACK_ERROR;
1034         goto exit;
1035     }
1036     if (!OCRepPayloadSetPropString(urlInfoPayload, OC_RSRVD_INTROSPECTION_PROTOCOL, protocol))
1037     {
1038         OIC_LOG(ERROR, TAG, "Failed to add protocol");
1039         result = OC_STACK_ERROR;
1040         goto exit;
1041     }
1042     if (!OCRepPayloadSetPropString(urlInfoPayload, OC_RSRVD_INTROSPECTION_CONTENT_TYPE, OC_RSRVD_INTROSPECTION_CONTENT_TYPE_VALUE))
1043     {
1044         OIC_LOG(ERROR, TAG, "Failed to add content type");
1045         result = OC_STACK_ERROR;
1046         goto exit;
1047     }
1048     if (!OCRepPayloadSetPropInt(urlInfoPayload, OC_RSRVD_INTROSPECTION_VERSION, OC_RSRVD_INTROSPECTION_VERSION_VALUE))
1049     {
1050         OIC_LOG(ERROR, TAG, "Failed to add version");
1051         result = OC_STACK_ERROR;
1052         goto exit;
1053     }
1054
1055 exit:
1056     if (result != OC_STACK_OK)
1057     {
1058         OCRepPayloadDestroy(urlInfoPayload);
1059         urlInfoPayload = NULL;
1060     }
1061     return urlInfoPayload;
1062 }
1063
1064 OCStackResult AddProtocolToLL(OCStringLL **protoLL, const char *protocol)
1065 {
1066     OCStringLL* cur = *protoLL;
1067     // Check if protocol is already in list
1068     while (cur)
1069     {
1070         if (strcmp(cur->value, protocol) == 0)
1071         {
1072             break;
1073         }
1074         cur = cur->next;
1075     }
1076     if (cur)
1077     {
1078         // The intent of the protocol list is to collect all unique protocols available on this
1079         // endpoint. Set an error that can be used to skip processing this protocol further as
1080         // it already exists in the list.
1081         return OC_STACK_INVALID_PARAM;
1082     }
1083     else
1084     {
1085         cur = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1086         if (!cur)
1087         {
1088             return OC_STACK_NO_MEMORY;
1089         }
1090     }
1091
1092     cur->value = OICStrdup(protocol);
1093     if (!cur->value)
1094     {
1095         OICFree(cur);
1096         return OC_STACK_NO_MEMORY;
1097     }
1098
1099     cur->next = *protoLL;
1100     *protoLL = cur;
1101     return OC_STACK_OK;
1102 }
1103
1104 void FreeProtocolLL(OCStringLL *protoLL)
1105 {
1106     OCStringLL* cur = protoLL;
1107     while (cur)
1108     {
1109         OCStringLL *temp = cur;
1110         cur = cur->next;
1111         OICFree(temp->value);
1112         OICFree(temp);
1113     }
1114 }
1115
1116 OCStackResult BuildIntrospectionResponseRepresentation(const OCResource *resourcePtr,
1117     OCRepPayload** payload, OCDevAddr *devAddr)
1118 {
1119     OC_UNUSED(devAddr);
1120     size_t dimensions[3] = { 0, 0, 0 };
1121     OCRepPayload *tempPayload = NULL;
1122     OCRepPayload **urlInfoPayload = NULL;
1123     OCStringLL *protoLL = NULL;
1124     OCStackResult ret = OC_STACK_OK;
1125     OCResourceType *resType = NULL;
1126     OCResourceInterface *resInterface = NULL;
1127
1128     if (!resourcePtr)
1129     {
1130         ret = OC_STACK_INVALID_PARAM;
1131         goto exit;
1132     }
1133
1134     tempPayload = OCRepPayloadCreate();
1135     if (!tempPayload)
1136     {
1137         ret = OC_STACK_NO_MEMORY;
1138         goto exit;
1139     }
1140
1141     if (!OCRepPayloadSetUri(tempPayload, resourcePtr->uri))
1142     {
1143         OIC_LOG(ERROR, TAG, "Failed to set payload URI");
1144         ret = OC_STACK_ERROR;
1145         goto exit;
1146     }
1147
1148     resType = resourcePtr->rsrcType;
1149     while (resType)
1150     {
1151         if (!OCRepPayloadAddResourceType(tempPayload, resType->resourcetypename))
1152         {
1153             OIC_LOG(ERROR, TAG, "Failed at add resource type");
1154             ret = OC_STACK_ERROR;
1155             goto exit;
1156         }
1157         resType = resType->next;
1158     }
1159
1160     resInterface = resourcePtr->rsrcInterface;
1161     while (resInterface)
1162     {
1163         if (!OCRepPayloadAddInterface(tempPayload, resInterface->name))
1164         {
1165             OIC_LOG(ERROR, TAG, "Failed to add interface");
1166             ret = OC_STACK_ERROR;
1167             goto exit;
1168         }
1169         resInterface = resInterface->next;
1170     }
1171     if (!OCRepPayloadSetPropString(tempPayload, OC_RSRVD_INTROSPECTION_NAME, OC_RSRVD_INTROSPECTION_NAME_VALUE))
1172     {
1173         OIC_LOG(ERROR, TAG, "Failed to set Name property.");
1174         ret = OC_STACK_ERROR;
1175         goto exit;
1176     }
1177
1178     // Figure out which protocols this endpoint supports
1179     if (resourcePtr->endpointType & OC_COAP)
1180     {
1181         if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAP_STR))
1182         {
1183             dimensions[0]++;
1184         }
1185     }
1186     if (resourcePtr->endpointType & OC_COAPS)
1187     {
1188         if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAPS_STR))
1189         {
1190             dimensions[0]++;
1191         }
1192     }
1193 #ifdef TCP_ADAPTER
1194     if (resourcePtr->endpointType & OC_COAP_TCP)
1195     {
1196         if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAP_STR))
1197         {
1198             dimensions[0]++;
1199         }
1200     }
1201     if (resourcePtr->endpointType & OC_COAPS_TCP)
1202     {
1203         if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAPS_STR))
1204         {
1205             dimensions[0]++;
1206         }
1207     }
1208 #endif
1209 #ifdef HTTP_ADAPTER
1210     if (resourcePtr->endpointType & OC_HTTP)
1211     {
1212         if (OC_STACK_OK == AddProtocolToLL(&protoLL, HTTP_STR))
1213         {
1214             dimensions[0]++;
1215         }
1216     }
1217     if (resourcePtr->endpointType & OC_HTTPS)
1218     {
1219         if (OC_STACK_OK == AddProtocolToLL(&protoLL, HTTPS_STR))
1220         {
1221             dimensions[0]++;
1222         }
1223     }
1224 #endif
1225 #ifdef EDR_ADAPTER
1226     if (resourcePtr->endpointType & OC_COAP_RFCOMM)
1227     {
1228         if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAP_STR))
1229         {
1230             dimensions[0]++;
1231         }
1232     }
1233 #endif
1234     // Add a urlInfo object for each protocol supported
1235     urlInfoPayload = (OCRepPayload **)OICMalloc(dimensions[0] * sizeof(OCRepPayload));
1236     if (urlInfoPayload)
1237     {
1238         OCStringLL *proto = protoLL;
1239         size_t i = 0;
1240         while (proto)
1241         {
1242             urlInfoPayload[i] = BuildUrlInfoWithProtocol(proto->value);
1243             if (!urlInfoPayload[i])
1244             {
1245                 OIC_LOG(ERROR, TAG, "Unable to build urlInfo object for protocol");
1246                 ret = OC_STACK_ERROR;
1247                 goto exit;
1248             }
1249             proto = proto->next;
1250             i++;
1251         }
1252         if (!OCRepPayloadSetPropObjectArrayAsOwner(tempPayload,
1253                                                    OC_RSRVD_INTROSPECTION_URL_INFO,
1254                                                    urlInfoPayload,
1255                                                    dimensions))
1256         {
1257             OIC_LOG(ERROR, TAG, "Unable to add urlInfo object to introspection payload ");
1258             ret = OC_STACK_ERROR;
1259             goto exit;
1260         }
1261     }
1262     else
1263     {
1264         OIC_LOG(ERROR, TAG, "Unable to allocate memory for urlInfo ");
1265         ret = OC_STACK_NO_MEMORY;
1266         goto exit;
1267     }
1268
1269     if (!*payload)
1270     {
1271         *payload = tempPayload;
1272     }
1273     else
1274     {
1275         OCRepPayloadAppend(*payload, tempPayload);
1276     }
1277 exit:
1278     if (ret != OC_STACK_OK)
1279     {
1280         OCRepPayloadDestroy(tempPayload);
1281         if (urlInfoPayload)
1282         {
1283             OICFree(urlInfoPayload);
1284         }
1285     }
1286     FreeProtocolLL(protoLL);
1287
1288     return OC_STACK_OK;
1289 }
1290
1291 OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
1292                                            OCDiscoveryPayload *payload,
1293                                            OCDevAddr *devAddr,
1294                                            CAEndpoint_t *networkInfo,
1295                                            size_t infoSize)
1296 {
1297     if (!resourcePtr || !payload)
1298     {
1299         return OC_STACK_INVALID_PARAM;
1300     }
1301     uint16_t securePort = 0;
1302     if (resourcePtr->resourceProperties & OC_SECURE)
1303     {
1304        if (GetSecurePortInfo(devAddr, &securePort) != OC_STACK_OK)
1305        {
1306            securePort = 0;
1307        }
1308     }
1309
1310     bool isVirtual = false;
1311     if (GetTypeOfVirtualURI(resourcePtr->uri) != OC_UNKNOWN_URI)
1312     {
1313         isVirtual = true;
1314     }
1315 #ifdef TCP_ADAPTER
1316     uint16_t tcpPort = 0;
1317     GetTCPPortInfo(devAddr, &tcpPort, (resourcePtr->resourceProperties & OC_SECURE));
1318
1319     OCDiscoveryPayloadAddResourceWithEps(payload, resourcePtr, securePort,
1320                                          isVirtual, networkInfo, infoSize, devAddr, tcpPort);
1321 #else
1322     OCDiscoveryPayloadAddResourceWithEps(payload, resourcePtr, securePort,
1323                                          isVirtual, networkInfo, infoSize, devAddr);
1324 #endif
1325
1326     return OC_STACK_OK;
1327 }
1328
1329 OCResource *FindResourceByUri(const char* resourceUri)
1330 {
1331     if(!resourceUri)
1332     {
1333         return NULL;
1334     }
1335
1336     OCResource * pointer = headResource;
1337     while (pointer)
1338     {
1339         if (strcmp(resourceUri, pointer->uri) == 0)
1340         {
1341             return pointer;
1342         }
1343         pointer = pointer->next;
1344     }
1345     OIC_LOG_V(INFO, TAG, "Resource %s not found", resourceUri);
1346     return NULL;
1347 }
1348
1349 OCStackResult CheckRequestsEndpoint(const OCDevAddr *reqDevAddr,
1350                                     OCTpsSchemeFlags resTpsFlags)
1351 {
1352     if (!reqDevAddr)
1353     {
1354         OIC_LOG(ERROR, TAG, "OCDevAddr* is NULL!!!");
1355         return OC_STACK_INVALID_PARAM;
1356     }
1357
1358     OCTpsSchemeFlags reqTpsFlags = OC_NO_TPS;
1359     OCStackResult result = OCGetMatchedTpsFlags((CATransportAdapter_t)reqDevAddr->adapter,
1360                                   (CATransportFlags_t)reqDevAddr->flags, &reqTpsFlags);
1361
1362     if (result != OC_STACK_OK)
1363     {
1364         OIC_LOG_V(ERROR, TAG, "Failed at get TPS flags. errcode is %d", result);
1365         return result;
1366     }
1367
1368     // bit compare between request tps flags and resource tps flags
1369     if (reqTpsFlags & resTpsFlags)
1370     {
1371         OIC_LOG(INFO, TAG, "Request come from registered TPS");
1372         return OC_STACK_OK;
1373     }
1374     else
1375     {
1376         OIC_LOG(ERROR, TAG, "Request come from unregistered TPS!!!");
1377         return OC_STACK_BAD_ENDPOINT;
1378     }
1379 }
1380
1381 OCStackResult DetermineResourceHandling (const OCServerRequest *request,
1382                                          ResourceHandling *handling,
1383                                          OCResource **resource)
1384 {
1385     if(!request || !handling || !resource)
1386     {
1387         return OC_STACK_INVALID_PARAM;
1388     }
1389
1390     OIC_LOG_V(INFO, TAG, "DetermineResourceHandling for %s", request->resourceUrl);
1391
1392     // Check if virtual resource
1393     if (GetTypeOfVirtualURI(request->resourceUrl) != OC_UNKNOWN_URI)
1394     {
1395         OIC_LOG_V (INFO, TAG, "%s is virtual", request->resourceUrl);
1396         *handling = OC_RESOURCE_VIRTUAL;
1397         *resource = headResource;
1398         return OC_STACK_OK;
1399     }
1400     if (strlen((const char*)(request->resourceUrl)) == 0)
1401     {
1402         // Resource URL not specified
1403         *handling = OC_RESOURCE_NOT_SPECIFIED;
1404         return OC_STACK_NO_RESOURCE;
1405     }
1406     else
1407     {
1408         OCResource *resourcePtr = FindResourceByUri((const char*)request->resourceUrl);
1409         *resource = resourcePtr;
1410
1411         // Checking resource TPS flags if resource exist in stack.
1412         if (resourcePtr)
1413         {
1414             OCStackResult result = CheckRequestsEndpoint(&(request->devAddr), resourcePtr->endpointType);
1415
1416             if (result != OC_STACK_OK)
1417             {
1418                 if (result == OC_STACK_BAD_ENDPOINT)
1419                 {
1420                     OIC_LOG(ERROR, TAG, "Request come from bad endpoint. ignore request!!!");
1421                     return OC_STACK_BAD_ENDPOINT;
1422                 }
1423                 else
1424                 {
1425                     OIC_LOG_V(ERROR, TAG, "Failed at get tps flag errcode: %d", result);
1426                     return result;
1427                 }
1428             }
1429         }
1430
1431         if (!resourcePtr)
1432         {
1433             if(defaultDeviceHandler)
1434             {
1435                 *handling = OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER;
1436                 return OC_STACK_OK;
1437             }
1438
1439             // Resource does not exist
1440             // and default device handler does not exist
1441             *handling = OC_RESOURCE_NOT_SPECIFIED;
1442             return OC_STACK_NO_RESOURCE;
1443         }
1444
1445         if (resourcePtr && resourcePtr->rsrcChildResourcesHead != NULL)
1446         {
1447             // Collection resource
1448             if (resourcePtr->entityHandler != defaultResourceEHandler)
1449             {
1450                 *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER;
1451                 return OC_STACK_OK;
1452             }
1453             else
1454             {
1455                 *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER;
1456                 return OC_STACK_OK;
1457             }
1458         }
1459         else
1460         {
1461             // Resource not a collection
1462             if (resourcePtr->entityHandler != defaultResourceEHandler)
1463             {
1464                 *handling = OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER;
1465                 return OC_STACK_OK;
1466             }
1467             else
1468             {
1469                 *handling = OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER;
1470                 return OC_STACK_OK;
1471             }
1472         }
1473     }
1474 }
1475
1476 OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
1477 {
1478     OCStackResult result;
1479
1480     switch (ehResult)
1481     {
1482         case OC_EH_OK:
1483         case OC_EH_CONTENT:
1484         case OC_EH_VALID:
1485             result = OC_STACK_OK;
1486             break;
1487         case OC_EH_SLOW:
1488             result = OC_STACK_SLOW_RESOURCE;
1489             break;
1490         case OC_EH_ERROR:
1491             result = OC_STACK_ERROR;
1492             break;
1493         case OC_EH_FORBIDDEN:
1494             result = OC_STACK_FORBIDDEN_REQ;
1495             break;
1496         case OC_EH_INTERNAL_SERVER_ERROR:
1497             result = OC_STACK_INTERNAL_SERVER_ERROR;
1498             break;
1499         case OC_EH_RESOURCE_CREATED:
1500             result = OC_STACK_RESOURCE_CREATED;
1501             break;
1502         case OC_EH_RESOURCE_DELETED:
1503             result = OC_STACK_RESOURCE_DELETED;
1504             break;
1505         case OC_EH_CHANGED:
1506             result = OC_STACK_RESOURCE_CHANGED;
1507             break;
1508         case OC_EH_RESOURCE_NOT_FOUND:
1509             result = OC_STACK_NO_RESOURCE;
1510             break;
1511         default:
1512             result = OC_STACK_ERROR;
1513     }
1514
1515     return result;
1516 }
1517
1518 static bool resourceMatchesRTFilter(OCResource *resource, char *resourceTypeFilter)
1519 {
1520     if (!resource)
1521     {
1522         return false;
1523     }
1524
1525     // Null is analogous to no filter.i.e. query is of form /oic/res?if=oic.if.baseline or /oic/res,
1526     // without rt query.
1527     if (NULL == resourceTypeFilter)
1528     {
1529         return true;
1530     }
1531
1532     // Empty resourceType filter is analogous to error query
1533     // It is an error as query is of form /oic/res?rt=
1534     if (0 == strlen(resourceTypeFilter))
1535     {
1536         return false;
1537     }
1538
1539     for (OCResourceType *rtPtr = resource->rsrcType; rtPtr; rtPtr = rtPtr->next)
1540     {
1541         if (0 == strcmp(rtPtr->resourcetypename, resourceTypeFilter))
1542         {
1543             return true;
1544         }
1545     }
1546
1547     OIC_LOG_V(INFO, TAG, "%s does not contain rt=%s.", resource->uri, resourceTypeFilter);
1548     return false;
1549 }
1550
1551 static bool resourceMatchesIFFilter(OCResource *resource, char *interfaceFilter)
1552 {
1553     if (!resource)
1554     {
1555         return false;
1556     }
1557
1558     // Null is analogous to no filter i.e. query is of form /oic/res?rt=core.light or /oic/res,
1559     // without if query.
1560     if (NULL == interfaceFilter)
1561     {
1562         return true;
1563     }
1564
1565     // Empty interface filter is analogous to error query
1566     // It is an error as query is of form /oic/res?if=
1567     if (0 == strlen(interfaceFilter))
1568     {
1569         return false;
1570     }
1571
1572     for (OCResourceInterface *ifPtr = resource->rsrcInterface; ifPtr; ifPtr = ifPtr->next)
1573     {
1574         if (0 == strcmp(ifPtr->name, interfaceFilter) ||
1575             0 == strcmp(OC_RSRVD_INTERFACE_LL, interfaceFilter) ||
1576             0 == strcmp(OC_RSRVD_INTERFACE_DEFAULT, interfaceFilter))
1577         {
1578             return true;
1579         }
1580     }
1581
1582     OIC_LOG_V(INFO, TAG, "%s does not contain if=%s.", resource->uri, interfaceFilter);
1583     return false;
1584 }
1585
1586 /*
1587  * If the filters are null, they will be assumed to NOT be present
1588  * and the resource will not be matched against them.
1589  * Function will return true if all non null AND non empty filters passed in find a match.
1590  */
1591 static bool includeThisResourceInResponse(OCResource *resource,
1592                                           char *interfaceFilter,
1593                                           char *resourceTypeFilter)
1594 {
1595     if (!resource)
1596     {
1597         OIC_LOG(ERROR, TAG, "Invalid resource");
1598         return false;
1599     }
1600
1601     if (resource->resourceProperties & OC_EXPLICIT_DISCOVERABLE)
1602     {
1603         /*
1604          * At least one valid filter should be available to
1605          * include the resource in discovery response
1606          */
1607         if (!(resourceTypeFilter && *resourceTypeFilter))
1608         {
1609             OIC_LOG_V(INFO, TAG, "%s no query string for EXPLICIT_DISCOVERABLE\
1610                 resource", resource->uri);
1611             return false;
1612         }
1613     }
1614     else if (!(resource->resourceProperties & OC_ACTIVE) ||
1615          !(resource->resourceProperties & OC_DISCOVERABLE))
1616     {
1617         OIC_LOG_V(INFO, TAG, "%s not ACTIVE or DISCOVERABLE", resource->uri);
1618         return false;
1619     }
1620
1621     return resourceMatchesIFFilter(resource, interfaceFilter) &&
1622            resourceMatchesRTFilter(resource, resourceTypeFilter);
1623 }
1624
1625 OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCResource *resource,
1626                                 OCPayload *discoveryPayload, OCEntityHandlerResult ehResult)
1627 {
1628     OCEntityHandlerResponse *response = NULL;
1629     OCStackResult result = OC_STACK_ERROR;
1630
1631     response = (OCEntityHandlerResponse *)OICCalloc(1, sizeof(*response));
1632     VERIFY_PARAM_NON_NULL(TAG, response, "Failed allocating OCEntityHandlerResponse");
1633
1634     response->ehResult = ehResult;
1635     response->payload = discoveryPayload;
1636     response->persistentBufferFlag = 0;
1637     response->requestHandle = (OCRequestHandle) request;
1638     response->resourceHandle = (OCResourceHandle) resource;
1639
1640     result = OCDoResponse(response);
1641
1642     OICFree(response);
1643     return result;
1644
1645 exit:
1646     return OC_STACK_NO_MEMORY;
1647 }
1648
1649 static OCStackResult EHRequest(OCEntityHandlerRequest *ehRequest, OCPayloadType type,
1650     OCServerRequest *request, OCResource *resource)
1651 {
1652     return FormOCEntityHandlerRequest(ehRequest,
1653                                      (OCRequestHandle)request,
1654                                      request->method,
1655                                      &request->devAddr,
1656                                      (OCResourceHandle)resource,
1657                                      request->query,
1658                                      type,
1659                                      request->payload,
1660                                      request->payloadSize,
1661                                      request->numRcvdVendorSpecificHeaderOptions,
1662                                      request->rcvdVendorSpecificHeaderOptions,
1663                                      (OCObserveAction)(request->notificationFlag ? OC_OBSERVE_NO_OPTION :
1664                                                        request->observationOption),
1665                                      (OCObservationId)0,
1666                                      request->coapID);
1667 }
1668
1669 #ifdef RD_SERVER
1670 /**
1671  * Find resources at the resource directory server. These resources are not local resources but
1672  * remote resources.
1673  *
1674  * @param interfaceQuery The interface query parameter.
1675  * @param resourceTypeQuery The resourceType query parameter.
1676  * @param discPayload The payload that will be added with the resource information if found at RD.
1677  *
1678  * @return ::OC_STACK_OK if any resources are found else ::OC_STACK_NO_RESOURCE.
1679  * In case if RD server is not started, it returns ::OC_STACK_NO_RESOURCE.
1680  */
1681 static OCStackResult findResourcesAtRD(const char *interfaceQuery,
1682                                        const char *resourceTypeQuery, OCDiscoveryPayload **discPayload)
1683 {
1684     OCStackResult result = OC_STACK_NO_RESOURCE;
1685     if (OCGetResourceHandleAtUri(OC_RSRVD_RD_URI) != NULL)
1686     {
1687         result = OCRDDatabaseDiscoveryPayloadCreate(interfaceQuery, resourceTypeQuery,
1688             (*discPayload) ? &(*discPayload)->next : discPayload);
1689     }
1690     if ((*discPayload) && (*discPayload)->resources)
1691     {
1692         result = OC_STACK_OK;
1693     }
1694     return result;
1695 }
1696 #endif
1697
1698 /**
1699  * Creates a discovery payload and add device id information. This information is included in all
1700  * /oic/res response.
1701  *
1702  * @param payload  payload that will have memory alllocated and device id information added.
1703  *
1704  * @return ::OC_STACK_OK if successful in allocating memory and adding ID information.
1705  * ::OC_STACK_NO_MEMORY if failed allocating the memory.
1706  */
1707 static OCStackResult discoveryPayloadCreateAndAddDeviceId(OCPayload **payload)
1708 {
1709     if (*payload)
1710     {
1711         OIC_LOG(DEBUG, TAG, "Payload is already allocated");
1712         return OC_STACK_OK;
1713     }
1714
1715     *payload = (OCPayload *) OCDiscoveryPayloadCreate();
1716     VERIFY_PARAM_NON_NULL(TAG, *payload, "Failed adding device id to discovery payload.");
1717
1718     {
1719         OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)*payload;
1720         discPayload->sid = (char *)OICCalloc(1, UUID_STRING_SIZE);
1721         VERIFY_PARAM_NON_NULL(TAG, discPayload->sid, "Failed adding device id to discovery payload.");
1722
1723         const char* uid = OCGetServerInstanceIDString();
1724         if (uid)
1725         {
1726             memcpy(discPayload->sid, uid, UUID_STRING_SIZE);
1727         }
1728
1729     }
1730     return OC_STACK_OK;
1731 exit:
1732     OCPayloadDestroy(*payload);
1733     return OC_STACK_NO_MEMORY;
1734 }
1735
1736 /**
1737  * Add the common properties to the payload, they are only included in case of oic.if.baseline response.
1738  *
1739  * @param discPayload payload that will have the baseline information included.
1740  *
1741  * @return ::OC_STACK_OK if successful in adding all the information. ::OC_STACK_NO_MEMORY if failed
1742  * allocating the memory for the baseline information.
1743  */
1744 static OCStackResult addDiscoveryBaselineCommonProperties(OCDiscoveryPayload *discPayload)
1745 {
1746     if (!discPayload)
1747     {
1748         OIC_LOG(ERROR, TAG, "Payload is not allocated");
1749         return OC_STACK_INVALID_PARAM;
1750     }
1751
1752     OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, (void **)&discPayload->name);
1753
1754     discPayload->type = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1755     VERIFY_PARAM_NON_NULL(TAG, discPayload->type, "Failed adding rt to discovery payload.");
1756     discPayload->type->value = OICStrdup(OC_RSRVD_RESOURCE_TYPE_RES);
1757     VERIFY_PARAM_NON_NULL(TAG, discPayload->type, "Failed adding rt value to discovery payload.");
1758
1759     OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_LL);
1760     OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_DEFAULT);
1761     VERIFY_PARAM_NON_NULL(TAG, discPayload->iface, "Failed adding if to discovery payload.");
1762
1763     return OC_STACK_OK;
1764
1765 exit:
1766     return OC_STACK_NO_MEMORY;
1767 }
1768
1769 static bool isUnicast(OCServerRequest *request)
1770 {
1771     bool isMulticast = request->devAddr.flags & OC_MULTICAST;
1772     return (isMulticast == false &&
1773            (request->devAddr.adapter != OC_ADAPTER_RFCOMM_BTEDR) &&
1774            (request->devAddr.adapter != OC_ADAPTER_GATT_BTLE));
1775 }
1776
1777 static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource)
1778 {
1779     if (!request || !resource)
1780     {
1781         return OC_STACK_INVALID_PARAM;
1782     }
1783
1784     OCPayload* payload = NULL;
1785     char *interfaceQuery = NULL;
1786     char *resourceTypeQuery = NULL;
1787
1788     OIC_LOG(INFO, TAG, "Entering HandleVirtualResource");
1789
1790     OCVirtualResources virtualUriInRequest = GetTypeOfVirtualURI (request->resourceUrl);
1791
1792 #ifdef TCP_ADAPTER
1793     if (OC_KEEPALIVE_RESOURCE_URI == virtualUriInRequest)
1794     {
1795         // Received request for a keepalive
1796         OIC_LOG(INFO, TAG, "Request is for KeepAlive Request");
1797         return HandleKeepAliveRequest(request, resource);
1798     }
1799 #endif
1800
1801     OCStackResult discoveryResult = OC_STACK_ERROR;
1802     if (request->method == OC_REST_PUT || request->method == OC_REST_POST ||
1803         request->method == OC_REST_DELETE)
1804     {
1805         OIC_LOG_V(ERROR, TAG, "Resource : %s not permitted for method: %d",
1806             request->resourceUrl, request->method);
1807         return OC_STACK_UNAUTHORIZED_REQ;
1808     }
1809
1810     discoveryResult = HandleVirtualObserveRequest(request);
1811     if (discoveryResult == OC_STACK_DUPLICATE_REQUEST)
1812     {
1813         // server requests are usually free'd when the response is sent out
1814         // for the request in ocserverrequest.c : HandleSingleResponse()
1815         // Since we are making an early return and not responding, the server request
1816         // needs to be deleted.
1817         FindAndDeleteServerRequest (request);
1818         discoveryResult = OC_STACK_OK;
1819         goto exit;
1820     }
1821     else if (discoveryResult != OC_STACK_OK)
1822     {
1823         goto exit;
1824     }
1825
1826     // Step 1: Generate the response to discovery request
1827     if (virtualUriInRequest == OC_WELL_KNOWN_URI
1828 #ifdef MQ_BROKER
1829             || virtualUriInRequest == OC_MQ_BROKER_URI
1830 #endif
1831             )
1832     {
1833         if (g_multicastServerStopped && !isUnicast(request))
1834         {
1835             // Ignore the discovery request
1836             FindAndDeleteServerRequest(request);
1837             discoveryResult = OC_STACK_CONTINUE;
1838             goto exit;
1839         }
1840
1841         char *interfaceQuery = NULL;
1842         char *resourceTypeQuery = NULL;
1843
1844         CAEndpoint_t *networkInfo = NULL;
1845         size_t infoSize = 0;
1846
1847         CAResult_t caResult = CAGetNetworkInformation(&networkInfo, &infoSize);
1848         if (CA_STATUS_FAILED == caResult)
1849         {
1850             OIC_LOG(ERROR, TAG, "CAGetNetworkInformation has error on parsing network infomation");
1851             return OC_STACK_ERROR;
1852         }
1853
1854         discoveryResult = getQueryParamsForFiltering (virtualUriInRequest, request->query,
1855                 &interfaceQuery, &resourceTypeQuery);
1856         VERIFY_SUCCESS(discoveryResult);
1857
1858         if (!interfaceQuery && !resourceTypeQuery)
1859         {
1860             // If no query is sent, default interface is used i.e. oic.if.ll.
1861             interfaceQuery = OICStrdup(OC_RSRVD_INTERFACE_LL);
1862         }
1863
1864         discoveryResult = discoveryPayloadCreateAndAddDeviceId(&payload);
1865         VERIFY_PARAM_NON_NULL(TAG, payload, "Failed creating Discovery Payload.");
1866         VERIFY_SUCCESS(discoveryResult);
1867
1868         OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)payload;
1869         if (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_DEFAULT))
1870         {
1871             discoveryResult = addDiscoveryBaselineCommonProperties(discPayload);
1872             VERIFY_SUCCESS(discoveryResult);
1873         }
1874         OCResourceProperty prop = OC_DISCOVERABLE;
1875 #ifdef MQ_BROKER
1876         prop = (OC_MQ_BROKER_URI == virtualUriInRequest) ? OC_MQ_BROKER : prop;
1877 #endif
1878         for (; resource && discoveryResult == OC_STACK_OK; resource = resource->next)
1879         {
1880             // This case will handle when no resource type and it is oic.if.ll.
1881             // Do not assume check if the query is ll
1882             if (!resourceTypeQuery &&
1883                 (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_LL)))
1884             {
1885                 // Only include discoverable type
1886                 if (resource->resourceProperties & prop)
1887                 {
1888                     discoveryResult = BuildVirtualResourceResponse(resource,
1889                                                                    discPayload,
1890                                                                    &request->devAddr,
1891                                                                    networkInfo,
1892                                                                    infoSize);
1893                 }
1894             }
1895             else if (includeThisResourceInResponse(resource, interfaceQuery, resourceTypeQuery))
1896             {
1897                 discoveryResult = BuildVirtualResourceResponse(resource,
1898                                                                discPayload,
1899                                                                &request->devAddr,
1900                                                                networkInfo,
1901                                                                infoSize);
1902             }
1903             else
1904             {
1905                 discoveryResult = OC_STACK_OK;
1906             }
1907         }
1908         if (discPayload->resources == NULL)
1909         {
1910             discoveryResult = OC_STACK_NO_RESOURCE;
1911             OCPayloadDestroy(payload);
1912             payload = NULL;
1913         }
1914
1915         if (networkInfo)
1916         {
1917             OICFree(networkInfo);
1918         }
1919 #ifdef RD_SERVER
1920         discoveryResult = findResourcesAtRD(interfaceQuery, resourceTypeQuery, (OCDiscoveryPayload **)&payload);
1921 #endif
1922     }
1923     else if (virtualUriInRequest == OC_DEVICE_URI)
1924     {
1925         OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_DEVICE_URI);
1926         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Device URI not found.");
1927         discoveryResult = BuildDevicePlatformPayload(resourcePtr, (OCRepPayload **)&payload, true);
1928     }
1929     else if (virtualUriInRequest == OC_PLATFORM_URI)
1930     {
1931         OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_PLATFORM_URI);
1932         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Platform URI not found.");
1933         discoveryResult = BuildDevicePlatformPayload(resourcePtr, (OCRepPayload **)&payload, false);
1934     }
1935 #ifdef ROUTING_GATEWAY
1936     else if (OC_GATEWAY_URI == virtualUriInRequest)
1937     {
1938         // Received request for a gateway
1939         OIC_LOG(INFO, TAG, "Request is for Gateway Virtual Request");
1940         discoveryResult = RMHandleGatewayRequest(request, resource);
1941     }
1942 #endif
1943     else if (OC_INTROSPECTION_URI == virtualUriInRequest)
1944     {
1945         // Received request for introspection
1946         OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_INTROSPECTION_URI);
1947         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Introspection URI not found.");
1948         discoveryResult = BuildIntrospectionResponseRepresentation(resourcePtr, (OCRepPayload **)&payload, &request->devAddr);
1949         OIC_LOG(INFO, TAG, "Request is for Introspection");
1950     }
1951     else if (OC_INTROSPECTION_PAYLOAD_URI == virtualUriInRequest)
1952     {
1953         // Received request for introspection payload
1954         OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_INTROSPECTION_PAYLOAD_URI);
1955         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Introspection Payload URI not found.");
1956         discoveryResult = BuildIntrospectionPayloadResponse(resourcePtr, (OCRepPayload **)&payload, &request->devAddr);
1957         OIC_LOG(INFO, TAG, "Request is for Introspection Payload");
1958     }
1959     /**
1960      * Step 2: Send the discovery response
1961      *
1962      * Iotivity should respond to discovery requests in below manner:
1963      * 1)If query filter matching fails and discovery request is multicast,
1964      *   it should NOT send any response.
1965      * 2)If query filter matching fails and discovery request is unicast,
1966      *   it should send an error(RESOURCE_NOT_FOUND - 404) response.
1967      * 3)If Server does not have any 'DISCOVERABLE' resources and discovery
1968      *   request is multicast, it should NOT send any response.
1969      * 4)If Server does not have any 'DISCOVERABLE' resources and discovery
1970      *   request is unicast, it should send an error(RESOURCE_NOT_FOUND - 404) response.
1971      */
1972
1973 #ifdef WITH_PRESENCE
1974     if ((virtualUriInRequest == OC_PRESENCE) &&
1975         (resource->resourceProperties & OC_ACTIVE))
1976     {
1977         // Need to send ACK when the request is CON.
1978         if (request->qos == OC_HIGH_QOS)
1979         {
1980             CAEndpoint_t endpoint = { .adapter = CA_DEFAULT_ADAPTER };
1981             CopyDevAddrToEndpoint(&request->devAddr, &endpoint);
1982             SendDirectStackResponse(&endpoint, request->coapID, CA_EMPTY, CA_MSG_ACKNOWLEDGE,
1983                                     0, NULL, NULL, 0, NULL, CA_RESPONSE_FOR_RES);
1984         }
1985         FindAndDeleteServerRequest(request);
1986
1987         // Presence uses observer notification api to respond via SendPresenceNotification.
1988         SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
1989     }
1990     else
1991 #endif
1992 #if ROUTING_GATEWAY
1993     // Gateway uses the RMHandleGatewayRequest to respond to the request.
1994     if (OC_GATEWAY_URI != virtualUriInRequest)
1995 #endif
1996     {
1997         OIC_LOG_PAYLOAD(DEBUG, payload);
1998         if(discoveryResult == OC_STACK_OK)
1999         {
2000             SendNonPersistantDiscoveryResponse(request, resource, payload, OC_EH_OK);
2001         }
2002         else // Error handling
2003         {
2004             if (isUnicast(request))
2005             {
2006                 OIC_LOG_V(ERROR, TAG, "Sending a (%d) error to (%d) discovery request",
2007                     discoveryResult, virtualUriInRequest);
2008                 SendNonPersistantDiscoveryResponse(request, resource, NULL,
2009                     (discoveryResult == OC_STACK_NO_RESOURCE) ?
2010                         OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR);
2011             }
2012             else // Multicast
2013             {
2014                 // Ignoring the discovery request as per RFC 7252, Section #8.2
2015                 OIC_LOG(INFO, TAG, "Silently ignoring the request since no useful data to send.");
2016                 // the request should be removed.
2017                 // since it never remove and causes a big memory waste.
2018                 FindAndDeleteServerRequest(request);
2019             }
2020             discoveryResult = OC_STACK_CONTINUE;
2021         }
2022     }
2023
2024 exit:
2025     if (interfaceQuery)
2026     {
2027         OICFree(interfaceQuery);
2028     }
2029
2030     if (resourceTypeQuery)
2031     {
2032         OICFree(resourceTypeQuery);
2033     }
2034     OCPayloadDestroy(payload);
2035
2036     // To ignore the message, OC_STACK_CONTINUE is sent
2037     return discoveryResult;
2038 }
2039
2040 static OCStackResult
2041 HandleDefaultDeviceEntityHandler(OCServerRequest *request)
2042 {
2043     if (!request)
2044     {
2045         return OC_STACK_INVALID_PARAM;
2046     }
2047
2048     OCEntityHandlerResult ehResult = OC_EH_ERROR;
2049     OCEntityHandlerRequest ehRequest = {0};
2050     OIC_LOG(INFO, TAG, "Entering HandleResourceWithDefaultDeviceEntityHandler");
2051     OCStackResult result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, NULL);
2052     VERIFY_SUCCESS(result);
2053
2054     // At this point we know for sure that defaultDeviceHandler exists
2055     ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
2056                                   (char*) request->resourceUrl, defaultDeviceHandlerCallbackParameter);
2057     if(ehResult == OC_EH_SLOW)
2058     {
2059         OIC_LOG(INFO, TAG, "This is a slow resource");
2060         request->slowFlag = 1;
2061     }
2062     else if(ehResult == OC_EH_ERROR)
2063     {
2064         FindAndDeleteServerRequest(request);
2065     }
2066     result = EntityHandlerCodeToOCStackCode(ehResult);
2067 exit:
2068     OCPayloadDestroy(ehRequest.payload);
2069     return result;
2070 }
2071
2072 static OCStackResult
2073 HandleResourceWithEntityHandler(OCServerRequest *request,
2074                                 OCResource *resource)
2075 {
2076     if(!request || ! resource)
2077     {
2078         return OC_STACK_INVALID_PARAM;
2079     }
2080
2081     OCStackResult result = OC_STACK_ERROR;
2082     OCEntityHandlerResult ehResult = OC_EH_ERROR;
2083     OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
2084     ResourceObserver *resObs = NULL;
2085
2086     OCEntityHandlerRequest ehRequest = {0};
2087
2088     OIC_LOG(INFO, TAG, "Entering HandleResourceWithEntityHandler");
2089     OCPayloadType type = PAYLOAD_TYPE_REPRESENTATION;
2090     // check the security resource
2091     if (request && request->resourceUrl && SRMIsSecurityResourceURI(request->resourceUrl))
2092     {
2093         type = PAYLOAD_TYPE_SECURITY;
2094     }
2095
2096     result = EHRequest(&ehRequest, type, request, resource);
2097     VERIFY_SUCCESS(result);
2098
2099     if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
2100     {
2101         OIC_LOG(INFO, TAG, "No observation requested");
2102         ehFlag = OC_REQUEST_FLAG;
2103     }
2104     else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER)
2105     {
2106         OIC_LOG(INFO, TAG, "Observation registration requested");
2107
2108         ResourceObserver *obs = GetObserverUsingToken (request->requestToken,
2109                                     request->tokenLength);
2110
2111         if (obs)
2112         {
2113             OIC_LOG (INFO, TAG, "Observer with this token already present");
2114             OIC_LOG (INFO, TAG, "Possibly re-transmitted CON OBS request");
2115             OIC_LOG (INFO, TAG, "Not adding observer. Not responding to client");
2116             OIC_LOG (INFO, TAG, "The first request for this token is already ACKED.");
2117
2118             // server requests are usually free'd when the response is sent out
2119             // for the request in ocserverrequest.c : HandleSingleResponse()
2120             // Since we are making an early return and not responding, the server request
2121             // needs to be deleted.
2122             FindAndDeleteServerRequest (request);
2123             return OC_STACK_OK;
2124         }
2125
2126         result = GenerateObserverId(&ehRequest.obsInfo.obsId);
2127         VERIFY_SUCCESS(result);
2128
2129         result = AddObserver ((const char*)(request->resourceUrl),
2130                 (const char *)(request->query),
2131                 ehRequest.obsInfo.obsId, request->requestToken, request->tokenLength,
2132                 resource, request->qos, request->acceptFormat,
2133                 request->acceptVersion, &request->devAddr);
2134
2135         if(result == OC_STACK_OK)
2136         {
2137             OIC_LOG(INFO, TAG, "Added observer successfully");
2138             request->observeResult = OC_STACK_OK;
2139             ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
2140         }
2141         else if (result == OC_STACK_RESOURCE_ERROR)
2142         {
2143             OIC_LOG(INFO, TAG, "The Resource is not active, discoverable or observable");
2144             request->observeResult = OC_STACK_ERROR;
2145             ehFlag = OC_REQUEST_FLAG;
2146         }
2147         else
2148         {
2149             // The error in observeResult for the request will be used when responding to this
2150             // request by omitting the observation option/sequence number.
2151             request->observeResult = OC_STACK_ERROR;
2152             OIC_LOG(ERROR, TAG, "Observer Addition failed");
2153             ehFlag = OC_REQUEST_FLAG;
2154             FindAndDeleteServerRequest(request);
2155             goto exit;
2156         }
2157
2158     }
2159     else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER)
2160     {
2161         OIC_LOG(INFO, TAG, "Deregistering observation requested");
2162
2163         resObs = GetObserverUsingToken (request->requestToken, request->tokenLength);
2164
2165         if (NULL == resObs)
2166         {
2167             // Stack does not contain this observation request
2168             // Either token is incorrect or observation list is corrupted
2169             result = OC_STACK_ERROR;
2170             goto exit;
2171         }
2172         ehRequest.obsInfo.obsId = resObs->observeId;
2173         ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
2174
2175         result = DeleteObserverUsingToken (request->requestToken, request->tokenLength);
2176
2177         if(result == OC_STACK_OK)
2178         {
2179             OIC_LOG(INFO, TAG, "Removed observer successfully");
2180             request->observeResult = OC_STACK_OK;
2181             // There should be no observe option header for de-registration response.
2182             // Set as an invalid value here so we can detect it later and remove the field in response.
2183             request->observationOption = MAX_SEQUENCE_NUMBER + 1;
2184         }
2185         else
2186         {
2187             request->observeResult = OC_STACK_ERROR;
2188             OIC_LOG(ERROR, TAG, "Observer Removal failed");
2189             FindAndDeleteServerRequest(request);
2190             goto exit;
2191         }
2192     }
2193     else
2194     {
2195         result = OC_STACK_ERROR;
2196         goto exit;
2197     }
2198
2199     ehResult = resource->entityHandler(ehFlag, &ehRequest, resource->entityHandlerCallbackParam);
2200     if(ehResult == OC_EH_SLOW)
2201     {
2202         OIC_LOG(INFO, TAG, "This is a slow resource");
2203         request->slowFlag = 1;
2204     }
2205     else if(ehResult == OC_EH_ERROR)
2206     {
2207         FindAndDeleteServerRequest(request);
2208     }
2209     result = EntityHandlerCodeToOCStackCode(ehResult);
2210 exit:
2211     OCPayloadDestroy(ehRequest.payload);
2212     return result;
2213 }
2214
2215 static OCStackResult HandleCollectionResourceDefaultEntityHandler(OCServerRequest *request,
2216                                                                   OCResource *resource)
2217 {
2218     if (!request || !resource)
2219     {
2220         return OC_STACK_INVALID_PARAM;
2221     }
2222
2223     OCEntityHandlerRequest ehRequest = {0};
2224     OCStackResult result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, resource);
2225     if(result == OC_STACK_OK)
2226     {
2227         result = DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest);
2228     }
2229
2230     OCPayloadDestroy(ehRequest.payload);
2231     return result;
2232 }
2233
2234 OCStackResult
2235 ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request)
2236 {
2237     OCStackResult ret = OC_STACK_OK;
2238
2239     switch (resHandling)
2240     {
2241         case OC_RESOURCE_VIRTUAL:
2242         {
2243             ret = HandleVirtualResource (request, resource);
2244             break;
2245         }
2246         case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER:
2247         {
2248             ret = HandleDefaultDeviceEntityHandler(request);
2249             break;
2250         }
2251         case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
2252         {
2253             OIC_LOG(INFO, TAG, "OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER");
2254             return OC_STACK_ERROR;
2255         }
2256         case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
2257         {
2258             ret = HandleResourceWithEntityHandler (request, resource);
2259             break;
2260         }
2261         case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
2262         {
2263             ret = HandleResourceWithEntityHandler (request, resource);
2264             break;
2265         }
2266         case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
2267         {
2268             ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
2269             break;
2270         }
2271         case OC_RESOURCE_NOT_SPECIFIED:
2272         {
2273             ret = OC_STACK_NO_RESOURCE;
2274             break;
2275         }
2276         default:
2277         {
2278             OIC_LOG(INFO, TAG, "Invalid Resource Determination");
2279             return OC_STACK_ERROR;
2280         }
2281     }
2282     return ret;
2283 }
2284
2285 OCStackResult OCSetPlatformInfo(OCPlatformInfo info)
2286 {
2287     OCResource *resource = NULL;
2288     if (!info.platformID || !info.manufacturerName)
2289     {
2290         OIC_LOG(ERROR, TAG, "No value specified.");
2291         goto exit;
2292     }
2293     if (0 == strlen(info.platformID) || 0 == strlen(info.manufacturerName))
2294     {
2295         OIC_LOG(ERROR, TAG, "The passed value cannot be empty");
2296         goto exit;
2297     }
2298     if ((info.manufacturerName && strlen(info.manufacturerName) > MAX_PLATFORM_NAME_LENGTH) ||
2299         (info.manufacturerUrl && strlen(info.manufacturerUrl) > MAX_PLATFORM_URL_LENGTH) ||
2300         (info.modelNumber && strlen(info.modelNumber) > MAX_PLATFORM_NAME_LENGTH) ||
2301         (info.platformVersion && strlen(info.platformVersion) > MAX_PLATFORM_NAME_LENGTH) ||
2302         (info.operatingSystemVersion && strlen(info.operatingSystemVersion) > MAX_PLATFORM_NAME_LENGTH) ||
2303         (info.hardwareVersion && strlen(info.hardwareVersion) > MAX_PLATFORM_NAME_LENGTH) ||
2304         (info.firmwareVersion && strlen(info.firmwareVersion) > MAX_PLATFORM_NAME_LENGTH) ||
2305         (info.supportUrl && strlen(info.supportUrl) > MAX_PLATFORM_URL_LENGTH))
2306     {
2307         OIC_LOG(ERROR, TAG, "The passed value is bigger than permitted.");
2308         goto exit;
2309     }
2310
2311     /*
2312      * @todo (IOT-1541) There are several versions of a UUID structure and conversion
2313      * methods scattered around the IoTivity code base.  They need to be combined
2314      * into one PAL API.
2315      */
2316     uint8_t uuid[UUID_SIZE];
2317     if (!OCConvertStringToUuid(info.platformID, uuid))
2318     {
2319         OIC_LOG(ERROR, TAG, "Platform ID is not a UUID.");
2320         goto exit;
2321     }
2322
2323     resource = FindResourceByUri(OC_RSRVD_PLATFORM_URI);
2324     if (!resource)
2325     {
2326         OIC_LOG(ERROR, TAG, "Platform Resource does not exist.");
2327         goto exit;
2328     }
2329     OIC_LOG(INFO, TAG, "Entering OCSetPlatformInfo");
2330     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_PLATFORM_ID, info.platformID));
2331     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_NAME, info.manufacturerName));
2332     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_URL, info.manufacturerUrl);
2333     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MODEL_NUM, info.modelNumber);
2334     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_DATE, info.dateOfManufacture);
2335     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_PLATFORM_VERSION, info.platformVersion);
2336     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_OS_VERSION, info.operatingSystemVersion);
2337     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_HARDWARE_VERSION, info.hardwareVersion);
2338     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_FIRMWARE_VERSION, info.firmwareVersion);
2339     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_SUPPORT_URL, info.supportUrl);
2340     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_SYSTEM_TIME, info.systemTime);
2341     OIC_LOG(INFO, TAG, "Platform parameter initialized successfully.");
2342     return OC_STACK_OK;
2343
2344 exit:
2345     return OC_STACK_INVALID_PARAM;
2346 }
2347
2348 OCStackResult OCSetDeviceInfo(OCDeviceInfo info)
2349 {
2350     OCResource *resource = FindResourceByUri(OC_RSRVD_DEVICE_URI);
2351     if (!resource)
2352     {
2353         OIC_LOG(ERROR, TAG, "Device Resource does not exist.");
2354         goto exit;
2355     }
2356     if (!info.deviceName || info.deviceName[0] == '\0')
2357     {
2358         OIC_LOG(ERROR, TAG, "Null or empty device name.");
2359        return OC_STACK_INVALID_PARAM;
2360     }
2361
2362     if (OCGetServerInstanceIDString() == NULL)
2363     {
2364         OIC_LOG(INFO, TAG, "Device ID generation failed");
2365         goto exit;
2366     }
2367
2368     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, info.deviceName));
2369     for (OCStringLL *temp = info.types; temp; temp = temp->next)
2370     {
2371         if (temp->value)
2372         {
2373             VERIFY_SUCCESS(OCBindResourceTypeToResource(resource, temp->value));
2374         }
2375     }
2376     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_SPEC_VERSION, info.specVersion ?
2377         info.specVersion: OC_SPEC_VERSION));
2378
2379     if (info.dataModelVersions)
2380     {
2381         char *dmv = OCCreateString(info.dataModelVersions);
2382         VERIFY_PARAM_NON_NULL(TAG, dmv, "Failed allocating dataModelVersions");
2383         OCStackResult r = OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION, dmv);
2384         OICFree(dmv);
2385         VERIFY_SUCCESS(r);
2386     }
2387     else
2388     {
2389         VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION,
2390             OC_DATA_MODEL_VERSION));
2391     }
2392     OIC_LOG(INFO, TAG, "Device parameter initialized successfully.");
2393     return OC_STACK_OK;
2394
2395 exit:
2396     return OC_STACK_ERROR;
2397 }
2398
2399 OCStackResult OCGetAttribute(const OCResource *resource, const char *attribute, void **value)
2400 {
2401     if (!resource || !attribute)
2402     {
2403         return OC_STACK_INVALID_PARAM;
2404     }
2405     if (0 == strlen(attribute))
2406     {
2407         return OC_STACK_INVALID_PARAM;
2408     }
2409     for (OCAttribute *temp = resource->rsrcAttributes; temp; temp = temp->next)
2410     {
2411         if (0 == strcmp(attribute, temp->attrName))
2412         {
2413             // A special case as this type return OCStringLL
2414             if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, attribute))
2415             {
2416                 *value = CloneOCStringLL((OCStringLL *)temp->attrValue);
2417                 return OC_STACK_OK;
2418             }
2419             else
2420             {
2421                 *value = OICStrdup((char *)temp->attrValue);
2422                 return OC_STACK_OK;
2423             }
2424         }
2425     }
2426     return OC_STACK_NO_RESOURCE;
2427 }
2428
2429 OCStackResult OCGetPropertyValue(OCPayloadType type, const char *prop, void **value)
2430 {
2431     if (!prop)
2432     {
2433         return OC_STACK_INVALID_PARAM;
2434     }
2435     if (strlen(prop) == 0)
2436     {
2437         return OC_STACK_INVALID_PARAM;
2438     }
2439     if (*value)
2440     {
2441         *value = NULL;
2442     }
2443     OCStackResult res =  OC_STACK_NO_RESOURCE;
2444     if (PAYLOAD_TYPE_DEVICE == type || PAYLOAD_TYPE_PLATFORM == type)
2445     {
2446         const char *pathType = (type == PAYLOAD_TYPE_DEVICE) ? OC_RSRVD_DEVICE_URI : OC_RSRVD_PLATFORM_URI;
2447         OCResource *resource = FindResourceByUri(pathType);
2448         if (!resource)
2449         {
2450             return OC_STACK_NO_RESOURCE;
2451         }
2452
2453         res = OCGetAttribute(resource, prop, value);
2454     }
2455     return res;
2456 }
2457
2458 static OCStackResult SetAttributeInternal(OCResource *resource,
2459                                           const char *attribute,
2460                                           const void *value,
2461                                           bool updateDatabase)
2462 {
2463     OCAttribute *resAttrib = NULL;
2464
2465     // See if the attribute already exists in the list.
2466     for (resAttrib = resource->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
2467     {
2468         if (0 == strcmp(attribute, resAttrib->attrName))
2469         {
2470             // Found, free the old value.
2471             if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName))
2472             {
2473                 OCFreeOCStringLL((OCStringLL *)resAttrib->attrValue);
2474             }
2475             else
2476             {
2477                 OICFree((char *)resAttrib->attrValue);
2478             }
2479             break;
2480         }
2481     }
2482
2483     // If not already in the list, add it.
2484     if (NULL == resAttrib)
2485     {
2486         resAttrib = (OCAttribute *)OICCalloc(1, sizeof(OCAttribute));
2487         VERIFY_PARAM_NON_NULL(TAG, resAttrib, "Failed allocating OCAttribute");
2488         resAttrib->attrName = OICStrdup(attribute);
2489         VERIFY_PARAM_NON_NULL(TAG, resAttrib->attrName, "Failed allocating attribute name");
2490         resAttrib->next = resource->rsrcAttributes;
2491         resource->rsrcAttributes = resAttrib;
2492     }
2493
2494     // Fill in the new value.
2495     if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, attribute))
2496     {
2497         resAttrib->attrValue = OCCreateOCStringLL((char *)value);
2498     }
2499     else
2500     {
2501         resAttrib->attrValue = OICStrdup((char *)value);
2502     }
2503     VERIFY_PARAM_NON_NULL(TAG, resAttrib->attrValue, "Failed allocating attribute value");
2504
2505     // The resource has changed from what is stored in the database. Update the database to
2506     // reflect the new value.
2507     if (updateDatabase)
2508     {
2509         OCDeviceProperties *deviceProperties = NULL;
2510
2511         OCStackResult result = CreateDeviceProperties((const char*)value, &deviceProperties);
2512         if (OC_STACK_OK == result)
2513         {
2514             result = UpdateDevicePropertiesDatabase(deviceProperties);
2515             if (OC_STACK_OK != result)
2516             {
2517                 OIC_LOG(ERROR, TAG, "UpdateDevicePropertiesDatabase failed!");
2518             }
2519
2520             CleanUpDeviceProperties(&deviceProperties);
2521         }
2522         else
2523         {
2524             OIC_LOG(ERROR, TAG, "CreateDeviceProperties failed!");
2525         }
2526     }
2527
2528     return OC_STACK_OK;
2529
2530 exit:
2531     OCDeleteResourceAttributes(resAttrib);
2532     return OC_STACK_NO_MEMORY;
2533 }
2534
2535 static OCStackResult IsDatabaseUpdateNeeded(const char *attribute, const void *value, bool *update)
2536 {
2537     OCStackResult result = OC_STACK_OK;
2538     void *currentPIID = NULL;
2539
2540     if (!attribute || !value || !update)
2541     {
2542         return OC_STACK_INVALID_PARAM;
2543     }
2544
2545     *update = false;
2546
2547     // Protocol Independent ID
2548     if (0 == strcmp(OC_RSRVD_PROTOCOL_INDEPENDENT_ID, attribute))
2549     {
2550         result = OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_PROTOCOL_INDEPENDENT_ID, &currentPIID);
2551         if (OC_STACK_OK == result)
2552         {
2553             // PIID has already been set on the resource and stored in the database. Check to see
2554             // if the value is changing so the database can be updated accordingly.
2555             if (0 != strcmp((char *)currentPIID, (char*)value))
2556             {
2557                 *update = true;
2558             }
2559         }
2560         else if (OC_STACK_NO_RESOURCE == result)
2561         {
2562             // PIID has not been set yet so we should always update the database.
2563             *update = true;
2564             result = OC_STACK_OK;
2565         }
2566         else
2567         {
2568             OIC_LOG_V(ERROR, TAG, 
2569                 "Call to OCGetPropertyValue for the current PIID failed with error: %d", result);
2570         }
2571     }
2572
2573     // Clean Up
2574     OICFreeAndSetToNull(&currentPIID);
2575
2576     return result;
2577 }
2578
2579 OCStackResult OCSetAttribute(OCResource *resource, const char *attribute, const void *value)
2580 {
2581     bool updateDatabase = false;
2582
2583     // Check to see if we also need to update the database for this attribute. If the current
2584     // value matches what is stored in the database we can skip the update and an unnecessary
2585     // write.
2586     if (OC_STACK_OK != IsDatabaseUpdateNeeded(attribute, value, &updateDatabase))
2587     {
2588         OIC_LOG_V(WARNING, TAG, 
2589             "Could not determine if a database update was needed for %s. Proceeding without updating the database.",
2590             attribute);
2591         updateDatabase = false;
2592     }
2593
2594     return SetAttributeInternal(resource, attribute, value, updateDatabase);
2595 }
2596
2597 OCStackResult OCSetPropertyValue(OCPayloadType type, const char *prop, const void *value)
2598 {
2599     if (!prop || !value)
2600     {
2601         return OC_STACK_INVALID_PARAM;
2602     }
2603     if (strlen(prop) == 0)
2604     {
2605         return OC_STACK_INVALID_PARAM;
2606     }
2607
2608     OCStackResult res = OC_STACK_ERROR;
2609     if (PAYLOAD_TYPE_DEVICE == type || PAYLOAD_TYPE_PLATFORM == type)
2610     {
2611         const char *pathType = (type == PAYLOAD_TYPE_DEVICE) ? OC_RSRVD_DEVICE_URI : OC_RSRVD_PLATFORM_URI;
2612         OCResource *resource = FindResourceByUri(pathType);
2613         if (!resource)
2614         {
2615             OIC_LOG(ERROR, TAG, "Resource does not exist.");
2616         }
2617         else
2618         {
2619             res = OCSetAttribute(resource, prop, value);
2620         }
2621     }
2622
2623     return res;
2624 }