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