Update snapshot(2018-01-04)
[platform/upstream/iotivity.git] / resource / csdk / stack / src / ocresource.c
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 // Defining _POSIX_C_SOURCE macro with 200112L (or greater) as value
22 // causes header files to expose definitions
23 // corresponding to the POSIX.1-2001 base
24 // specification (excluding the XSI extension).
25 // For POSIX.1-2001 base specification,
26 // Refer http://pubs.opengroup.org/onlinepubs/009695399/
27 #define _POSIX_C_SOURCE 200112L
28 #ifndef _GNU_SOURCE
29 #define _GNU_SOURCE
30 #endif
31
32 #include "iotivity_config.h"
33 #ifdef HAVE_STRING_H
34 #include <string.h>
35 #endif
36 #ifdef HAVE_STRINGS_H
37 #include <strings.h>
38 #endif
39
40 #include "ocresource.h"
41 #include "ocresourcehandler.h"
42 #include "ocobserve.h"
43 #include "occollection.h"
44 #include "oic_malloc.h"
45 #include "oic_string.h"
46 #include "logger.h"
47 #include "ocpayload.h"
48 #include "secureresourcemanager.h"
49 #include "cacommon.h"
50 #include "cainterface.h"
51 #include "ocpayload.h"
52 #include "oickeepaliveinternal.h"
53 #include "platform_features.h"
54 #include "payload_logging.h"
55 #ifdef ROUTING_GATEWAY
56 #include "routingmanager.h"
57 #endif
58
59 /// Module Name
60 #define TAG "OIC_RI_RESOURCE"
61
62 #define VERIFY_SUCCESS(op) { if (op != (OC_STACK_OK)) \
63             {OIC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
64
65 extern OCResource *headResource;
66
67 /**
68  * Prepares a Payload for response.
69  */
70 static OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
71                                                   OCDiscoveryPayload* payload,
72                                                   OCDevAddr *endpoint);
73
74 //-----------------------------------------------------------------------------
75 // Default resource entity handler function
76 //-----------------------------------------------------------------------------
77 OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag,
78         OCEntityHandlerRequest * request, void* callbackParam)
79 {
80     //TODO ("Implement me!!!!");
81     // TODO:  remove silence unused param warnings
82     (void) flag;
83     (void) request;
84     (void) callbackParam;
85     return  OC_EH_OK; // Making sure that the Default EH and the Vendor EH have matching signatures
86 }
87
88 /* This method will retrieve the port at which the secure resource is hosted */
89 static OCStackResult GetSecurePortInfo(OCDevAddr *endpoint, uint16_t *port)
90 {
91     uint16_t p = 0;
92
93     if (endpoint->adapter == OC_ADAPTER_IP)
94     {
95         if (endpoint->flags & OC_IP_USE_V6)
96         {
97             p = caglobals.ip.u6s.port;
98         }
99         else if (endpoint->flags & OC_IP_USE_V4)
100         {
101             p = caglobals.ip.u4s.port;
102         }
103     }
104
105     *port = p;
106     return OC_STACK_OK;
107 }
108
109 #ifdef TCP_ADAPTER
110 /* This method will retrieve the tcp port */
111 static OCStackResult GetTCPPortInfo(OCDevAddr *endpoint, uint16_t *port, bool secured)
112 {
113     uint16_t p = 0;
114
115     if (endpoint->adapter == OC_ADAPTER_IP)
116     {
117         if (endpoint->flags & OC_IP_USE_V4)
118         {
119             p = secured ? caglobals.tcp.ipv4s.port : caglobals.tcp.ipv4.port;
120         }
121         else if (endpoint->flags & OC_IP_USE_V6)
122         {
123             p = secured ? caglobals.tcp.ipv6s.port : caglobals.tcp.ipv6.port;
124         }
125     }
126
127     *port = p;
128     return OC_STACK_OK;
129 }
130 #endif
131
132 /*
133  * Function will extract 0, 1 or 2 filters from query.
134  * More than 2 filters or unsupported filters will result in error.
135  * If both filters are of the same supported type, the 2nd one will be picked.
136  * Resource and device filters in the SAME query are NOT validated
137  * and resources will likely not clear filters.
138  */
139 OCStackResult ExtractFiltersFromQuery(const char *query, char **filterOne, char **filterTwo)
140 {
141     if (!query)
142     {
143         OIC_LOG_V(ERROR, TAG, "Query is empty!");
144         return OC_STACK_INVALID_QUERY;
145     }
146     char *key = NULL;
147     char *value = NULL;
148     char *queryDup = NULL;
149     char *restOfQuery = NULL;
150     char *keyValuePair = NULL;
151     int numKeyValuePairsParsed = 0;
152
153     *filterOne = NULL;
154     *filterTwo = NULL;
155
156     queryDup = OICStrdup(query);
157     if (NULL == queryDup)
158     {
159         OIC_LOG_V(ERROR, TAG, "Creating duplicate string failed!");
160         return OC_STACK_NO_MEMORY;
161     }
162
163     OIC_LOG_V(INFO, TAG, "Extracting params from %s", queryDup);
164
165     OCStackResult eCode = OC_STACK_INVALID_QUERY;
166     if (strnlen(queryDup, MAX_QUERY_LENGTH) >= MAX_QUERY_LENGTH)
167     {
168         OIC_LOG(ERROR, TAG, "Query exceeds maximum length.");
169         goto exit;
170     }
171
172     keyValuePair = strtok_r (queryDup, OC_QUERY_SEPARATOR, &restOfQuery);
173
174     while(keyValuePair)
175     {
176         if (numKeyValuePairsParsed >= 2)
177         {
178             OIC_LOG(ERROR, TAG, "More than 2 queries params in URI.");
179             goto exit;
180         }
181
182         key = strtok_r(keyValuePair, OC_KEY_VALUE_DELIMITER, &value);
183
184         if (!key || !value)
185         {
186             goto exit;
187         }
188         else if (strncasecmp(key, OC_RSRVD_INTERFACE, sizeof(OC_RSRVD_INTERFACE) - 1) == 0)
189         {
190             *filterOne = value;     // if
191         }
192         else if (strncasecmp(key, OC_RSRVD_RESOURCE_TYPE, sizeof(OC_RSRVD_INTERFACE) - 1) == 0)
193         {
194             *filterTwo = value;     // rt
195         }
196         else
197         {
198             OIC_LOG_V(ERROR, TAG, "Unsupported query key: %s", key);
199             goto exit;
200         }
201         ++numKeyValuePairsParsed;
202
203         keyValuePair = strtok_r(NULL, OC_QUERY_SEPARATOR, &restOfQuery);
204     }
205
206     if (*filterOne)
207     {
208         *filterOne = OICStrdup(*filterOne);
209         if (NULL == *filterOne)
210         {
211             OIC_LOG_V(ERROR, TAG, "Creating duplicate string failed!");
212             eCode = OC_STACK_NO_MEMORY;
213             goto exit;
214         }
215     }
216
217     if (*filterTwo)
218     {
219         *filterTwo = OICStrdup(*filterTwo);
220         if (NULL == *filterTwo)
221         {
222             OIC_LOG_V(ERROR, TAG, "Creating duplicate string failed!");
223             OICFree(*filterOne);
224             eCode = OC_STACK_NO_MEMORY;
225             goto exit;
226         }
227     }
228
229     OICFree(queryDup);
230     OIC_LOG_V(INFO, TAG, "Extracted params if: %s and rt: %s.", *filterOne, *filterTwo);
231     return OC_STACK_OK;
232
233 exit:
234     *filterOne = NULL;
235     *filterTwo = NULL;
236     OICFree(queryDup);
237     return eCode;
238 }
239
240 static OCVirtualResources GetTypeOfVirtualURI(const char *uriInRequest)
241 {
242     if (strcmp(uriInRequest, OC_RSRVD_WELL_KNOWN_URI) == 0)
243     {
244         return OC_WELL_KNOWN_URI;
245     }
246     else if (strcmp(uriInRequest, OC_RSRVD_DEVICE_URI) == 0)
247     {
248         return OC_DEVICE_URI;
249     }
250     else if (strcmp(uriInRequest, OC_RSRVD_PLATFORM_URI) == 0)
251     {
252         return OC_PLATFORM_URI;
253     }
254     else if (strcmp(uriInRequest, OC_RSRVD_RESOURCE_TYPES_URI) == 0)
255     {
256         return OC_RESOURCE_TYPES_URI;
257     }
258 #ifdef ROUTING_GATEWAY
259     else if (0 == strcmp(uriInRequest, OC_RSRVD_GATEWAY_URI))
260     {
261         return OC_GATEWAY_URI;
262     }
263 #endif
264 #ifdef WITH_PRESENCE
265     else if (strcmp(uriInRequest, OC_RSRVD_PRESENCE_URI) == 0)
266     {
267         return OC_PRESENCE;
268     }
269 #endif //WITH_PRESENCE
270
271 #ifdef MQ_BROKER
272     else if (0 == strcmp(uriInRequest, OC_RSRVD_WELL_KNOWN_MQ_URI))
273     {
274         return OC_MQ_BROKER_URI;
275     }
276 #endif //MQ_BROKER
277
278 #ifdef TCP_ADAPTER
279     else if (strcmp(uriInRequest, OC_RSRVD_KEEPALIVE_URI) == 0)
280     {
281         return OC_KEEPALIVE_RESOURCE_URI;
282     }
283 #endif
284
285     return OC_UNKNOWN_URI;
286 }
287
288 static OCStackResult getQueryParamsForFiltering (OCVirtualResources uri, char *query,
289                                             char **filterOne, char **filterTwo)
290 {
291     if(!filterOne || !filterTwo)
292     {
293         return OC_STACK_INVALID_PARAM;
294     }
295
296     *filterOne = NULL;
297     *filterTwo = NULL;
298
299 #ifdef WITH_PRESENCE
300     if (uri == OC_PRESENCE)
301     {
302         //Nothing needs to be done, except for pass a OC_PRESENCE query through as OC_STACK_OK.
303         OIC_LOG(INFO, TAG, "OC_PRESENCE Request for virtual resource.");
304         return OC_STACK_OK;
305     }
306 #endif
307
308     OCStackResult result = OC_STACK_OK;
309
310     if (query && *query)
311     {
312         result = ExtractFiltersFromQuery(query, filterOne, filterTwo);
313     }
314
315     return result;
316 }
317
318 bool appendOCStringLL(OCRepPayload *device, OCStringLL *dmv)
319 {
320     int size = 0;
321     for (OCStringLL *ll = dmv; ll; ll = ll->next, size++);
322     size_t dim[MAX_REP_ARRAY_DEPTH] = {size, 0, 0};
323     char **dt = (char **)OICMalloc(sizeof(char *) * size);
324     int i = 0;
325     VERIFY_PARAM_NON_NULL(TAG, dt, "Data Model Version allocation failed.");
326     for (OCStringLL *ll = dmv; ll; ll = ll->next, i++)
327     {
328         dt[i] = OICStrdup(ll->value);
329         VERIFY_PARAM_NON_NULL(TAG, dt[i], "Data Model Version adding failed.");
330     }
331     if (!OCRepPayloadSetStringArrayAsOwner(device, OC_RSRVD_DATA_MODEL_VERSION, dt, dim))
332     {
333         goto exit;
334     }
335     return true;
336
337 exit:
338     for (int i = 0; i < size; i++)
339     {
340         OICFree(dt[i]);
341     }
342     OICFree(dt);
343     return false;
344 }
345
346 static OCStackResult BuildDevicePlatformPayload(const OCResource *resourcePtr, OCRepPayload** payload, bool addDeviceId)
347 {
348     if (!resourcePtr)
349     {
350         return OC_STACK_INVALID_PARAM;
351     }
352
353     OCRepPayload *tempPayload = OCRepPayloadCreate();
354     if (!tempPayload)
355     {
356         return OC_STACK_NO_MEMORY;
357     }
358
359     if (addDeviceId)
360     {
361         const char *deviceId = OCGetServerInstanceIDString();
362         if (!deviceId)
363         {
364             OIC_LOG(ERROR, TAG, "Failed retrieving device id.");
365             return OC_STACK_ERROR;
366         }
367         OCRepPayloadSetPropString(tempPayload, OC_RSRVD_DEVICE_ID, deviceId);
368     }
369
370     OCResourceType *resType = resourcePtr->rsrcType;
371     while(resType)
372     {
373         OCRepPayloadAddResourceType(tempPayload, resType->resourcetypename);
374         resType = resType->next;
375     }
376
377     OCResourceInterface *resInterface = resourcePtr->rsrcInterface;
378     while(resInterface)
379     {
380         OCRepPayloadAddInterface(tempPayload, resInterface->name);
381         resInterface = resInterface->next;
382     }
383
384     OCAttribute *resAttrib = resourcePtr->rsrcAttributes;
385     while(resAttrib)
386     {
387         if (resAttrib->attrName && resAttrib->attrValue)
388         {
389             if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName))
390             {
391                 char *dmv = OCCreateString((OCStringLL *)resAttrib->attrValue);
392                 if (dmv)
393                 {
394                     OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, dmv);
395                     OICFree(dmv);
396                 }
397             }
398             else
399             {
400                 OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, (char *)resAttrib->attrValue);
401             }
402         }
403         resAttrib = resAttrib->next;
404     }
405
406     if(!*payload)
407     {
408         *payload = tempPayload;
409     }
410     else
411     {
412         OCRepPayloadAppend(*payload, tempPayload);
413     }
414
415     return OC_STACK_OK;
416 }
417
418 OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr,
419                     OCRepPayload** payload, OCDevAddr *devAddr)
420 {
421     if (!resourcePtr)
422     {
423         return OC_STACK_INVALID_PARAM;
424     }
425
426     OCRepPayload *tempPayload = OCRepPayloadCreate();
427     if(!tempPayload)
428     {
429         return OC_STACK_NO_MEMORY;
430     }
431
432     OCRepPayloadSetPropString(tempPayload, OC_RSRVD_HREF, resourcePtr->uri);
433
434     uint8_t numElement = 0;
435     if (OC_STACK_OK == OCGetNumberOfResourceTypes((OCResource *)resourcePtr, &numElement))
436     {
437         size_t rtDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
438         char **rt = (char **)OICMalloc(sizeof(char *) * numElement);
439         if (!rt)
440         {
441             OIC_LOG(ERROR, TAG, "Resource type allocation failed.");
442             OCRepPayloadDestroy(tempPayload);
443             return OC_STACK_NO_MEMORY;
444         }
445         for (uint8_t i = 0; i < numElement; ++i)
446         {
447             const char *value = OCGetResourceTypeName((OCResource *)resourcePtr, i);
448             OIC_LOG_V(DEBUG, TAG, "value: %s", value);
449             rt[i] = OICStrdup(value);
450         }
451         OCRepPayloadSetStringArrayAsOwner(tempPayload, OC_RSRVD_RESOURCE_TYPE, rt, rtDim);
452     }
453
454     numElement = 0;
455     if (OC_STACK_OK == OCGetNumberOfResourceInterfaces((OCResource *)resourcePtr, &numElement))
456     {
457         size_t ifDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
458         char **itf = (char **)OICMalloc(sizeof(char *) * numElement);
459         if (!itf)
460         {
461             OIC_LOG(ERROR, TAG, "Resource interface allocation failed.");
462             OCRepPayloadDestroy(tempPayload);
463             return OC_STACK_NO_MEMORY;
464         }
465         for (uint8_t i = 0; i < numElement; ++i)
466         {
467             const char *value = OCGetResourceInterfaceName((OCResource *)resourcePtr, i);
468             OIC_LOG_V(DEBUG, TAG, "value: %s", value);
469             itf[i] = OICStrdup(value);
470         }
471         OCRepPayloadSetStringArrayAsOwner(tempPayload, OC_RSRVD_INTERFACE, itf, ifDim);
472     }
473
474     for (OCAttribute *resAttrib = resourcePtr->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
475     {
476         if (resAttrib->attrName && resAttrib->attrValue)
477         {
478             if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName))
479             {
480                 char *dmv = OCCreateString((OCStringLL *)resAttrib->attrValue);
481                 if (dmv)
482                 {
483                     OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, dmv);
484                     OICFree(dmv);
485                 }
486             }
487             else
488             {
489                 OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, (char *)resAttrib->attrValue);
490             }
491         }
492     }
493
494     if (devAddr)
495     {
496         OCResourceProperty p = OCGetResourceProperties((OCResourceHandle *)resourcePtr);
497         OCRepPayload *policy = OCRepPayloadCreate();
498         if (!policy)
499         {
500             OCPayloadDestroy((OCPayload *)tempPayload);
501             return OC_STACK_NO_MEMORY;
502         }
503         OCRepPayloadSetPropInt(policy, OC_RSRVD_BITMAP, ((p & OC_DISCOVERABLE) | (p & OC_OBSERVABLE)));
504         if (p & OC_SECURE)
505         {
506             OCRepPayloadSetPropBool(policy, OC_RSRVD_SECURE, p & OC_SECURE);
507             uint16_t securePort = 0;
508             if (GetSecurePortInfo(devAddr, &securePort) != OC_STACK_OK)
509             {
510                 securePort = 0;
511             }
512             OCRepPayloadSetPropInt(policy, OC_RSRVD_HOSTING_PORT, securePort);
513         }
514         OCRepPayloadSetPropObjectAsOwner(tempPayload, OC_RSRVD_POLICY, policy);
515     }
516
517     if (!*payload)
518     {
519         *payload = tempPayload;
520     }
521     else
522     {
523         OCRepPayloadAppend(*payload, tempPayload);
524     }
525
526     return OC_STACK_OK;
527 }
528
529 OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
530                         OCDiscoveryPayload *payload, OCDevAddr *devAddr)
531 {
532     if (!resourcePtr || !payload)
533     {
534         return OC_STACK_INVALID_PARAM;
535     }
536     uint16_t securePort = 0;
537     if (resourcePtr->resourceProperties & OC_SECURE)
538     {
539        if (GetSecurePortInfo(devAddr, &securePort) != OC_STACK_OK)
540        {
541            securePort = 0;
542        }
543     }
544
545 #ifdef TCP_ADAPTER
546     uint16_t tcpPort = 0;
547     GetTCPPortInfo(devAddr, &tcpPort, (resourcePtr->resourceProperties & OC_SECURE));
548
549     OCDiscoveryPayloadAddResource(payload, resourcePtr, securePort, tcpPort);
550 #else
551     OCDiscoveryPayloadAddResource(payload, resourcePtr, securePort);
552 #endif
553
554     return OC_STACK_OK;
555 }
556
557 OCResource *FindResourceByUri(const char* resourceUri)
558 {
559     if(!resourceUri)
560     {
561         return NULL;
562     }
563
564     OCResource * pointer = headResource;
565     while (pointer)
566     {
567         if (strcmp(resourceUri, pointer->uri) == 0)
568         {
569             return pointer;
570         }
571         pointer = pointer->next;
572     }
573     OIC_LOG_V(INFO, TAG, "Resource %s not found", resourceUri);
574     return NULL;
575 }
576
577 OCStackResult DetermineResourceHandling (const OCServerRequest *request,
578                                          ResourceHandling *handling,
579                                          OCResource **resource)
580 {
581     if(!request || !handling || !resource)
582     {
583         return OC_STACK_INVALID_PARAM;
584     }
585
586     OIC_LOG_V(INFO, TAG, "DetermineResourceHandling for %s", request->resourceUrl);
587
588     // Check if virtual resource
589     if (GetTypeOfVirtualURI(request->resourceUrl) != OC_UNKNOWN_URI)
590     {
591         OIC_LOG_V (INFO, TAG, "%s is virtual", request->resourceUrl);
592         *handling = OC_RESOURCE_VIRTUAL;
593         *resource = headResource;
594         return OC_STACK_OK;
595     }
596     if (strlen((const char*)(request->resourceUrl)) == 0)
597     {
598         // Resource URL not specified
599         *handling = OC_RESOURCE_NOT_SPECIFIED;
600         return OC_STACK_NO_RESOURCE;
601     }
602     else
603     {
604         OCResource *resourcePtr = FindResourceByUri((const char*)request->resourceUrl);
605         *resource = resourcePtr;
606         if (!resourcePtr)
607         {
608             if(defaultDeviceHandler)
609             {
610                 *handling = OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER;
611                 return OC_STACK_OK;
612             }
613
614             // Resource does not exist
615             // and default device handler does not exist
616             *handling = OC_RESOURCE_NOT_SPECIFIED;
617             return OC_STACK_NO_RESOURCE;
618         }
619
620         if (resourcePtr && resourcePtr->rsrcChildResourcesHead != NULL)
621         {
622             // Collection resource
623             if (resourcePtr->entityHandler != defaultResourceEHandler)
624             {
625                 *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER;
626                 return OC_STACK_OK;
627             }
628             else
629             {
630                 *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER;
631                 return OC_STACK_OK;
632             }
633         }
634         else
635         {
636             // Resource not a collection
637             if (resourcePtr->entityHandler != defaultResourceEHandler)
638             {
639                 *handling = OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER;
640                 return OC_STACK_OK;
641             }
642             else
643             {
644                 *handling = OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER;
645                 return OC_STACK_OK;
646             }
647         }
648     }
649 }
650
651 OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
652 {
653     OCStackResult result;
654
655     switch (ehResult)
656     {
657         case OC_EH_OK:
658         case OC_EH_CONTENT:
659         case OC_EH_VALID:
660             result = OC_STACK_OK;
661             break;
662         case OC_EH_SLOW:
663             result = OC_STACK_SLOW_RESOURCE;
664             break;
665         case OC_EH_ERROR:
666             result = OC_STACK_ERROR;
667             break;
668         case OC_EH_FORBIDDEN:
669             result = OC_STACK_FORBIDDEN_REQ;
670             break;
671         case OC_EH_RESOURCE_CREATED:
672             result = OC_STACK_RESOURCE_CREATED;
673             break;
674         case OC_EH_RESOURCE_DELETED:
675             result = OC_STACK_RESOURCE_DELETED;
676             break;
677         case OC_EH_CHANGED:
678             result = OC_STACK_RESOURCE_CHANGED;
679             break;
680         case OC_EH_RESOURCE_NOT_FOUND:
681             result = OC_STACK_NO_RESOURCE;
682             break;
683         case OC_EH_INTERNAL_SERVER_ERROR:
684             result = OC_STACK_INTERNAL_SERVER_ERROR;
685             break;
686         case OC_EH_NOT_IMPLEMENTED:
687             result = OC_STACK_NOT_IMPLEMENTED;
688             break;
689         case OC_EH_BAD_GATEWAY:
690             result = OC_STACK_BAD_GATEWAY;
691             break;
692         case OC_EH_SERVICE_UNAVAILABLE:
693             result = OC_STACK_SERVICE_UNAVAILABLE;
694             break;
695         case OC_EH_RETRANSMIT_TIMEOUT:
696             result = OC_STACK_GATEWAY_TIMEOUT;
697             break;
698         case OC_EH_PROXY_NOT_SUPPORTED:
699             result = OC_STACK_PROXY_NOT_SUPPORTED;
700             break;
701         default:
702             result = OC_STACK_ERROR;
703     }
704
705     return result;
706 }
707
708 static bool resourceMatchesRTFilter(OCResource *resource, char *resourceTypeFilter)
709 {
710     if (!resource)
711     {
712         return false;
713     }
714
715     // Null is analogous to no filter.
716     if (NULL == resourceTypeFilter)
717     {
718         return true;
719     }
720
721     // Empty resourceType filter is analogous to error query
722     if (0 == strlen(resourceTypeFilter))
723     {
724         return false;
725     }
726
727     for (OCResourceType *rtPtr = resource->rsrcType; rtPtr; rtPtr = rtPtr->next)
728     {
729         if (0 == strcmp(rtPtr->resourcetypename, resourceTypeFilter))
730         {
731             return true;
732         }
733     }
734
735     OIC_LOG_V(INFO, TAG, "%s does not contain rt=%s.", resource->uri, resourceTypeFilter);
736     return false;
737 }
738
739 static bool resourceMatchesIFFilter(OCResource *resource, char *interfaceFilter)
740 {
741     if (!resource)
742     {
743         return false;
744     }
745
746     // Null is analogous to no filter.
747     if (NULL == interfaceFilter)
748     {
749         return true;
750     }
751
752     // Empty interface filter is analogous to error query
753     if (0 == strlen(interfaceFilter))
754     {
755         return false;
756     }
757
758     for (OCResourceInterface *ifPtr = resource->rsrcInterface; ifPtr; ifPtr = ifPtr->next)
759     {
760         if (0 == strcmp(ifPtr->name, interfaceFilter) ||
761             0 == strcmp(OC_RSRVD_INTERFACE_LL, interfaceFilter) ||
762             0 == strcmp(OC_RSRVD_INTERFACE_DEFAULT, interfaceFilter))
763         {
764             return true;
765         }
766     }
767
768     OIC_LOG_V(INFO, TAG, "%s does not contain if=%s.", resource->uri, interfaceFilter);
769     return false;
770 }
771
772 /*
773  * If the filters are null, they will be assumed to NOT be present
774  * and the resource will not be matched against them.
775  * Function will return true if all non null AND non empty filters passed in find a match.
776  */
777 static bool includeThisResourceInResponse(OCResource *resource,
778                                           char *interfaceFilter,
779                                           char *resourceTypeFilter)
780 {
781     if (!resource)
782     {
783         OIC_LOG(ERROR, TAG, "Invalid resource");
784         return false;
785     }
786
787     if (resource->resourceProperties & OC_EXPLICIT_DISCOVERABLE)
788     {
789         /*
790          * At least one valid filter should be available to
791          * include the resource in discovery response
792          */
793         if (!(resourceTypeFilter && *resourceTypeFilter))
794         {
795             OIC_LOG_V(INFO, TAG, "%s no query string for EXPLICIT_DISCOVERABLE\
796                 resource", resource->uri);
797             return false;
798         }
799     }
800     else if (!(resource->resourceProperties & OC_ACTIVE) ||
801          !(resource->resourceProperties & OC_DISCOVERABLE))
802     {
803         OIC_LOG_V(INFO, TAG, "%s not ACTIVE or DISCOVERABLE", resource->uri);
804         return false;
805     }
806
807     return resourceMatchesIFFilter(resource, interfaceFilter) &&
808            resourceMatchesRTFilter(resource, resourceTypeFilter);
809 }
810
811 OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCResource *resource,
812                                 OCPayload *discoveryPayload, OCEntityHandlerResult ehResult)
813 {
814     OCEntityHandlerResponse response = {0};
815
816     response.ehResult = ehResult;
817     response.payload = discoveryPayload;
818     response.persistentBufferFlag = 0;
819     response.requestHandle = (OCRequestHandle) request->requestId;
820     response.resourceHandle = (OCResourceHandle) resource;
821
822     return OCDoResponse(&response);
823 }
824
825 static OCStackResult EHRequest(OCEntityHandlerRequest *ehRequest, OCPayloadType type,
826     OCServerRequest *request, OCResource *resource)
827 {
828     return FormOCEntityHandlerRequest(ehRequest,
829                                      (OCRequestHandle)request->requestId,
830                                      request->method,
831                                      &request->devAddr,
832                                      (OCResourceHandle)resource,
833                                      request->query,
834                                      type,
835                                      request->payload,
836                                      request->payloadSize,
837                                      request->numRcvdVendorSpecificHeaderOptions,
838                                      request->rcvdVendorSpecificHeaderOptions,
839                                      (OCObserveAction)request->observationOption,
840                                      (OCObservationId)0,
841                                      request->coapID);
842 }
843
844 #ifdef RD_SERVER
845 /**
846  * Find resource at the resource directory server. This resource is not local resource but a
847  * remote resource.
848  *
849  * @param resource The resource to check the matching resource URI.
850  * @param interfaceQuery The interface query parameter.
851  * @param resourceTypeQuery The resourceType query parameter.
852  * @param discPayload The payload that will be added with the resource information if found at RD.
853  *
854  * @return ::OC_STACK_OK if the resource is found else ::OC_STACK_NO_RESOURCE.
855  * In case if build is not with flag RD_SERVER, it returns ::OC_STACK_NO_RESOURCE.
856  */
857 static OCStackResult findResourceAtRD(const OCResource* resource, const char *interfaceQuery,
858     const char *resourceTypeQuery, OCDiscoveryPayload *discPayload)
859 {
860     if (strcmp(resource->uri, OC_RSRVD_RD_URI) == 0)
861     {
862         if (OC_STACK_OK == OCRDDatabaseCheckResources(interfaceQuery, resourceTypeQuery, discPayload))
863         {
864             return OC_STACK_OK;
865         }
866     }
867
868     return OC_STACK_NO_RESOURCE;
869 }
870 #endif
871
872 /**
873  * Creates a discovery payload and add device id information. This information is included in all
874  * /oic/res response.
875  *
876  * @param payload  payload that will have memory alllocated and device id information added.
877  *
878  * @return ::OC_STACK_OK if successful in allocating memory and adding ID information.
879  * ::OC_STACK_NO_MEMORY if failed allocating the memory.
880  */
881 static OCStackResult discoveryPayloadCreateAndAddDeviceId(OCPayload **payload)
882 {
883     if (*payload)
884     {
885         OIC_LOG(DEBUG, TAG, "Payload is already allocated");
886         return OC_STACK_OK;
887     }
888
889     *payload = (OCPayload *) OCDiscoveryPayloadCreate();
890     VERIFY_PARAM_NON_NULL(TAG, *payload, "Failed adding device id to discovery payload.");
891
892     {
893         OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)*payload;
894         discPayload->sid = (char *)OICCalloc(1, UUID_STRING_SIZE);
895         VERIFY_PARAM_NON_NULL(TAG, discPayload->sid, "Failed adding device id to discovery payload.");
896
897         const char* uid = OCGetServerInstanceIDString();
898         if (uid)
899         {
900             memcpy(discPayload->sid, uid, UUID_STRING_SIZE);
901         }
902
903     }
904     return OC_STACK_OK;
905 exit:
906     OCPayloadDestroy(*payload);
907     return OC_STACK_NO_MEMORY;
908 }
909
910 /**
911  * Add the common properties to the payload, they are only included in case of oic.if.baseline response.
912  *
913  * @param discPayload payload that will have the baseline information included.
914  *
915  * @return ::OC_STACK_OK if successful in adding all the information. ::OC_STACK_NO_MEMORY if failed
916  * allocating the memory for the baseline information.
917  */
918 static OCStackResult addDiscoveryBaselineCommonProperties(OCDiscoveryPayload *discPayload)
919 {
920     if (!discPayload)
921     {
922         OIC_LOG(ERROR, TAG, "Payload is not allocated");
923         return OC_STACK_ERROR;
924     }
925
926     OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, (void **)&discPayload->name);
927
928     discPayload->type = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
929     VERIFY_PARAM_NON_NULL(TAG, discPayload->type, "Failed adding rt to discovery payload.");
930     discPayload->type->value = OICStrdup(OC_RSRVD_RESOURCE_TYPE_RES);
931     VERIFY_PARAM_NON_NULL(TAG, discPayload->type, "Failed adding rt value to discovery payload.");
932
933     OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_LL);
934     OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_DEFAULT);
935     VERIFY_PARAM_NON_NULL(TAG, discPayload->iface, "Failed adding if to discovery payload.");
936
937     return OC_STACK_OK;
938
939 exit:
940     return OC_STACK_NO_MEMORY;
941 }
942
943 static bool isUnicast(OCServerRequest *request)
944 {
945     bool isMulticast = request->devAddr.flags &  OC_MULTICAST;
946     return (isMulticast == false &&
947            (request->devAddr.adapter != OC_ADAPTER_RFCOMM_BTEDR) &&
948            (request->devAddr.adapter != OC_ADAPTER_GATT_BTLE));
949 }
950
951 static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource)
952 {
953     if (!request || !resource)
954     {
955         return OC_STACK_INVALID_PARAM;
956     }
957
958     OCPayload* payload = NULL;
959     char *interfaceQuery = NULL;
960     char *resourceTypeQuery = NULL;
961
962     OIC_LOG(INFO, TAG, "Entering HandleVirtualResource");
963
964     OCVirtualResources virtualUriInRequest = GetTypeOfVirtualURI (request->resourceUrl);
965
966 #ifdef TCP_ADAPTER
967     if (OC_KEEPALIVE_RESOURCE_URI == virtualUriInRequest)
968     {
969         // Received request for a keepalive
970         OIC_LOG(INFO, TAG, "Request is for KeepAlive Request");
971         return OCHandleKeepAliveRequest(request, resource);
972     }
973 #endif
974
975     OCStackResult discoveryResult = OC_STACK_ERROR;
976     if (request->method == OC_REST_PUT || request->method == OC_REST_POST ||
977         request->method == OC_REST_DELETE)
978     {
979         OIC_LOG_V(ERROR, TAG, "Resource : %s not permitted for method: %d",
980             request->resourceUrl, request->method);
981         return OC_STACK_UNAUTHORIZED_REQ;
982     }
983
984     // Step 1: Generate the response to discovery request
985     if (virtualUriInRequest == OC_WELL_KNOWN_URI
986 #ifdef MQ_BROKER
987             || virtualUriInRequest == OC_MQ_BROKER_URI
988 #endif
989             )
990     {
991         discoveryResult = getQueryParamsForFiltering(virtualUriInRequest, request->query,
992                 &interfaceQuery, &resourceTypeQuery);
993         VERIFY_SUCCESS(discoveryResult);
994
995         if (!interfaceQuery && !resourceTypeQuery)
996         {
997             // If no query is sent, default interface is used i.e. oic.if.ll.
998             interfaceQuery = OICStrdup(OC_RSRVD_INTERFACE_LL);
999         }
1000
1001         discoveryResult = discoveryPayloadCreateAndAddDeviceId(&payload);
1002         VERIFY_PARAM_NON_NULL(TAG, payload, "Failed creating Discovery Payload.");
1003         VERIFY_SUCCESS(discoveryResult);
1004
1005         OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)payload;
1006         if (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_DEFAULT))
1007         {
1008             discoveryResult = addDiscoveryBaselineCommonProperties(discPayload);
1009             VERIFY_SUCCESS(discoveryResult);
1010         }
1011         OCResourceProperty prop = OC_DISCOVERABLE;
1012 #ifdef MQ_BROKER
1013         prop = (OC_MQ_BROKER_URI == virtualUriInRequest) ? OC_MQ_BROKER : prop;
1014 #endif
1015         for (; resource && discoveryResult == OC_STACK_OK; resource = resource->next)
1016         {
1017             // This case will handle when no resource type and it is oic.if.ll.
1018             // Do not assume check if the query is ll
1019             if (!resourceTypeQuery &&
1020                 (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_LL)))
1021             {
1022                 // Only include discoverable type
1023                 if (resource->resourceProperties & prop)
1024                 {
1025                     discoveryResult = BuildVirtualResourceResponse(resource, discPayload, &request->devAddr);
1026                 }
1027             }
1028             else if (includeThisResourceInResponse(resource, interfaceQuery, resourceTypeQuery))
1029             {
1030                 discoveryResult = BuildVirtualResourceResponse(resource, discPayload, &request->devAddr);
1031             }
1032             else
1033             {
1034                 discoveryResult = OC_STACK_OK;
1035             }
1036         }
1037         if (discPayload->resources == NULL)
1038         {
1039             discoveryResult = OC_STACK_NO_RESOURCE;
1040         }
1041     }
1042     else if (virtualUriInRequest == OC_DEVICE_URI)
1043     {
1044         OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_DEVICE_URI);
1045         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Device URI not found.");
1046         discoveryResult = BuildDevicePlatformPayload(resourcePtr, (OCRepPayload **)&payload, true);
1047     }
1048     else if (virtualUriInRequest == OC_PLATFORM_URI)
1049     {
1050         OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_PLATFORM_URI);
1051         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Platform URI not found.");
1052         discoveryResult = BuildDevicePlatformPayload(resourcePtr, (OCRepPayload **)&payload, false);
1053     }
1054 #ifdef ROUTING_GATEWAY
1055     else if (OC_GATEWAY_URI == virtualUriInRequest)
1056     {
1057         // Received request for a gateway
1058         OIC_LOG(INFO, TAG, "Request is for Gateway Virtual Request");
1059         discoveryResult = RMHandleGatewayRequest(request, resource);
1060     }
1061 #endif
1062
1063     /**
1064      * Step 2: Send the discovery response
1065      *
1066      * Iotivity should respond to discovery requests in below manner:
1067      * 1)If query filter matching fails and discovery request is multicast,
1068      *   it should NOT send any response.
1069      * 2)If query filter matching fails and discovery request is unicast,
1070      *   it should send an error(RESOURCE_NOT_FOUND - 404) response.
1071      * 3)If Server does not have any 'DISCOVERABLE' resources and discovery
1072      *   request is multicast, it should NOT send any response.
1073      * 4)If Server does not have any 'DISCOVERABLE' resources and discovery
1074      *   request is unicast, it should send an error(RESOURCE_NOT_FOUND - 404) response.
1075      */
1076
1077 #ifdef WITH_PRESENCE
1078     if ((virtualUriInRequest == OC_PRESENCE) &&
1079         (resource->resourceProperties & OC_ACTIVE))
1080     {
1081         // Need to send ACK when the request is CON.
1082         if (request->qos == OC_HIGH_QOS)
1083         {
1084             CAEndpoint_t endpoint = { .adapter = CA_DEFAULT_ADAPTER };
1085             CopyDevAddrToEndpoint(&request->devAddr, &endpoint);
1086             SendDirectStackResponse(&endpoint, request->coapID, CA_EMPTY, CA_MSG_ACKNOWLEDGE,
1087                                     0, NULL, NULL, 0, NULL, CA_RESPONSE_FOR_RES);
1088         }
1089         FindAndDeleteServerRequest(request);
1090
1091         // Presence uses observer notification api to respond via SendPresenceNotification.
1092         SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
1093     }
1094     else
1095 #endif
1096 #if ROUTING_GATEWAY
1097     // Gateway uses the RMHandleGatewayRequest to respond to the request.
1098     if (OC_GATEWAY_URI != virtualUriInRequest)
1099 #endif
1100     {
1101         OIC_LOG_PAYLOAD(DEBUG, payload);
1102         if(discoveryResult == OC_STACK_OK)
1103         {
1104
1105             SendNonPersistantDiscoveryResponse(request, resource, payload, OC_EH_OK);
1106         }
1107         else // Error handling
1108         {
1109             if (isUnicast(request))
1110             {
1111                 OIC_LOG_V(ERROR, TAG, "Sending a (%d) error to (%d) discovery request",
1112                     discoveryResult, virtualUriInRequest);
1113                 SendNonPersistantDiscoveryResponse(request, resource, NULL,
1114                     (discoveryResult == OC_STACK_NO_RESOURCE) ?
1115                         OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR);
1116             }
1117             else // Multicast
1118             {
1119                 // Ignoring the discovery request as per RFC 7252, Section #8.2
1120                 OIC_LOG(INFO, TAG, "Silently ignoring the request since no useful data to send.");
1121                 // the request should be removed.
1122                 // since it never remove and causes a big memory waste.
1123                 FindAndDeleteServerRequest(request);
1124             }
1125             discoveryResult = OC_STACK_CONTINUE;
1126         }
1127     }
1128
1129 exit:
1130     if (interfaceQuery)
1131     {
1132         OICFree(interfaceQuery);
1133     }
1134
1135     if (resourceTypeQuery)
1136     {
1137         OICFree(resourceTypeQuery);
1138     }
1139     OCPayloadDestroy(payload);
1140
1141     // To ignore the message, OC_STACK_CONTINUE is sent
1142     return discoveryResult;
1143 }
1144
1145 static OCStackResult
1146 HandleDefaultDeviceEntityHandler(OCServerRequest *request)
1147 {
1148     if (!request)
1149     {
1150         return OC_STACK_INVALID_PARAM;
1151     }
1152
1153     OCEntityHandlerResult ehResult = OC_EH_ERROR;
1154     OCEntityHandlerRequest ehRequest = {0};
1155     OIC_LOG(INFO, TAG, "Entering HandleResourceWithDefaultDeviceEntityHandler");
1156     OCStackResult result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, NULL);
1157     VERIFY_SUCCESS(result);
1158
1159     // At this point we know for sure that defaultDeviceHandler exists
1160     ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
1161                                   (char*) request->resourceUrl, defaultDeviceHandlerCallbackParameter);
1162     if(ehResult == OC_EH_SLOW)
1163     {
1164         OIC_LOG(INFO, TAG, "This is a slow resource");
1165         request->slowFlag = 1;
1166     }
1167
1168     result = EntityHandlerCodeToOCStackCode(ehResult);
1169
1170     // Clear server request on error case
1171     if (!OCResultToSuccess(result))
1172     {
1173         FindAndDeleteServerRequest(request);
1174     }
1175
1176 exit:
1177     OCPayloadDestroy(ehRequest.payload);
1178     return result;
1179 }
1180
1181 static OCStackResult
1182 HandleResourceWithEntityHandler(OCServerRequest *request,
1183                                 OCResource *resource)
1184 {
1185     if(!request || ! resource)
1186     {
1187         return OC_STACK_INVALID_PARAM;
1188     }
1189
1190     OCStackResult result = OC_STACK_ERROR;
1191     OCEntityHandlerResult ehResult = OC_EH_ERROR;
1192     OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
1193     ResourceObserver *resObs = NULL;
1194
1195     OCEntityHandlerRequest ehRequest = {0};
1196
1197     OIC_LOG(INFO, TAG, "Entering HandleResourceWithEntityHandler");
1198     OCPayloadType type = PAYLOAD_TYPE_REPRESENTATION;
1199     // check the security resource
1200     if (request && request->resourceUrl && SRMIsSecurityResourceURI(request->resourceUrl))
1201     {
1202         type = PAYLOAD_TYPE_SECURITY;
1203     }
1204
1205     result = EHRequest(&ehRequest, type, request, resource);
1206     VERIFY_SUCCESS(result);
1207
1208     if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
1209     {
1210         OIC_LOG(INFO, TAG, "No observation requested");
1211         ehFlag = OC_REQUEST_FLAG;
1212     }
1213     else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER)
1214     {
1215         OIC_LOG(INFO, TAG, "Observation registration requested");
1216
1217         ResourceObserver *obs = GetObserverUsingToken (request->requestToken,
1218                                     request->tokenLength);
1219
1220         if (obs)
1221         {
1222             OIC_LOG (INFO, TAG, "Observer with this token already present");
1223             OIC_LOG (INFO, TAG, "Possibly re-transmitted CON OBS request");
1224             OIC_LOG (INFO, TAG, "Not adding observer. Not responding to client");
1225             OIC_LOG (INFO, TAG, "The first request for this token is already ACKED.");
1226
1227             // server requests are usually free'd when the response is sent out
1228             // for the request in ocserverrequest.c : HandleSingleResponse()
1229             // Since we are making an early return and not responding, the server request
1230             // needs to be deleted.
1231             FindAndDeleteServerRequest (request);
1232             FreeObserver(obs);
1233             return OC_STACK_OK;
1234         }
1235
1236         result = GenerateObserverId(&ehRequest.obsInfo.obsId);
1237         VERIFY_SUCCESS(result);
1238
1239         result = AddObserver ((const char*)(request->resourceUrl),
1240                 (const char *)(request->query),
1241                 ehRequest.obsInfo.obsId, request->requestToken, request->tokenLength,
1242                 resource, request->qos, request->acceptFormat,
1243                 &request->devAddr);
1244
1245         if(result == OC_STACK_OK)
1246         {
1247             OIC_LOG(INFO, TAG, "Added observer successfully");
1248             request->observeResult = OC_STACK_OK;
1249             ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
1250         }
1251         else if (result == OC_STACK_RESOURCE_ERROR)
1252         {
1253             OIC_LOG(INFO, TAG, "The Resource is not active, discoverable or observable");
1254             request->observeResult = OC_STACK_ERROR;
1255             ehFlag = OC_REQUEST_FLAG;
1256         }
1257         else
1258         {
1259             // The error in observeResult for the request will be used when responding to this
1260             // request by omitting the observation option/sequence number.
1261             request->observeResult = OC_STACK_ERROR;
1262             OIC_LOG(ERROR, TAG, "Observer Addition failed");
1263             ehFlag = OC_REQUEST_FLAG;
1264             FindAndDeleteServerRequest(request);
1265             goto exit;
1266         }
1267
1268     }
1269     else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER)
1270     {
1271         OIC_LOG(INFO, TAG, "Deregistering observation requested");
1272
1273         resObs = GetObserverUsingToken (request->requestToken, request->tokenLength);
1274
1275         if (NULL == resObs)
1276         {
1277             // Stack does not contain this observation request
1278             // Either token is incorrect or observation list is corrupted
1279             result = OC_STACK_NO_RESOURCE;
1280             goto exit;
1281         }
1282         ehRequest.obsInfo.obsId = resObs->observeId;
1283         ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
1284
1285         result = DeleteObserverUsingToken (request->requestToken, request->tokenLength);
1286
1287         if(result == OC_STACK_OK)
1288         {
1289             OIC_LOG(INFO, TAG, "Removed observer successfully");
1290             request->observeResult = OC_STACK_OK;
1291             // There should be no observe option header for de-registration response.
1292             // Set as an invalid value here so we can detect it later and remove the field in response.
1293             request->observationOption = MAX_SEQUENCE_NUMBER + 1;
1294         }
1295         else
1296         {
1297             request->observeResult = OC_STACK_ERROR;
1298             OIC_LOG(ERROR, TAG, "Observer Removal failed");
1299             FindAndDeleteServerRequest(request);
1300             goto exit;
1301         }
1302     }
1303     else
1304     {
1305         result = OC_STACK_ERROR;
1306         goto exit;
1307     }
1308
1309     ehResult = resource->entityHandler(ehFlag, &ehRequest, resource->entityHandlerCallbackParam);
1310     if(ehResult == OC_EH_SLOW)
1311     {
1312         OIC_LOG(INFO, TAG, "This is a slow resource");
1313         request->slowFlag = 1;
1314     }
1315
1316     result = EntityHandlerCodeToOCStackCode(ehResult);
1317
1318     // Clear server request on error case
1319     if (!OCResultToSuccess(result))
1320     {
1321         FindAndDeleteServerRequest(request);
1322     }
1323
1324 exit:
1325     OCPayloadDestroy(ehRequest.payload);
1326     FreeObserver(resObs);
1327     return result;
1328 }
1329
1330 static OCStackResult HandleCollectionResourceDefaultEntityHandler(OCServerRequest *request,
1331                                                                   OCResource *resource)
1332 {
1333     if (!request || !resource)
1334     {
1335         return OC_STACK_INVALID_PARAM;
1336     }
1337
1338     OCEntityHandlerRequest ehRequest = {0};
1339     OCStackResult result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, resource);
1340     if(result == OC_STACK_OK)
1341     {
1342         result = DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest);
1343     }
1344
1345     OCPayloadDestroy(ehRequest.payload);
1346     return result;
1347 }
1348
1349 OCStackResult
1350 ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request)
1351 {
1352     OCStackResult ret = OC_STACK_OK;
1353
1354     switch (resHandling)
1355     {
1356         case OC_RESOURCE_VIRTUAL:
1357         {
1358             ret = HandleVirtualResource (request, resource);
1359             break;
1360         }
1361         case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER:
1362         {
1363             ret = HandleDefaultDeviceEntityHandler(request);
1364             break;
1365         }
1366         case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
1367         {
1368             OIC_LOG(INFO, TAG, "OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER");
1369             return OC_STACK_ERROR;
1370         }
1371         case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
1372         {
1373             ret = HandleResourceWithEntityHandler (request, resource);
1374             break;
1375         }
1376         case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
1377         {
1378             ret = HandleResourceWithEntityHandler (request, resource);
1379             break;
1380         }
1381         case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
1382         {
1383             ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
1384             break;
1385         }
1386         case OC_RESOURCE_NOT_SPECIFIED:
1387         {
1388             ret = OC_STACK_NO_RESOURCE;
1389             break;
1390         }
1391         default:
1392         {
1393             OIC_LOG(INFO, TAG, "Invalid Resource Determination");
1394             return OC_STACK_ERROR;
1395         }
1396     }
1397     return ret;
1398 }
1399
1400 OCStackResult OCSetPlatformInfo(OCPlatformInfo info)
1401 {
1402     OCResource *resource = NULL;
1403     if (!info.platformID || !info.manufacturerName)
1404     {
1405         OIC_LOG(ERROR, TAG, "No value specified.");
1406         goto exit;
1407     }
1408     if (0 == strlen(info.platformID) || 0 == strlen(info.manufacturerName))
1409     {
1410         OIC_LOG(ERROR, TAG, "The passed value cannot be empty");
1411         goto exit;
1412     }
1413     if ((info.manufacturerName && strlen(info.manufacturerName) > MAX_PLATFORM_NAME_LENGTH) ||
1414         (info.manufacturerUrl && strlen(info.manufacturerUrl) > MAX_PLATFORM_URL_LENGTH) ||
1415         (info.modelNumber && strlen(info.modelNumber) > MAX_PLATFORM_NAME_LENGTH) ||
1416         (info.platformVersion && strlen(info.platformVersion) > MAX_PLATFORM_NAME_LENGTH) ||
1417         (info.operatingSystemVersion && strlen(info.operatingSystemVersion) > MAX_PLATFORM_NAME_LENGTH) ||
1418         (info.hardwareVersion && strlen(info.hardwareVersion) > MAX_PLATFORM_NAME_LENGTH) ||
1419         (info.firmwareVersion && strlen(info.firmwareVersion) > MAX_PLATFORM_NAME_LENGTH) ||
1420         (info.supportUrl && strlen(info.supportUrl) > MAX_PLATFORM_URL_LENGTH))
1421     {
1422         OIC_LOG(ERROR, TAG, "The passed value is bigger than permitted.");
1423         goto exit;
1424     }
1425
1426     resource = FindResourceByUri(OC_RSRVD_PLATFORM_URI);
1427     if (!resource)
1428     {
1429         OIC_LOG(ERROR, TAG, "Platform Resource does not exist.");
1430         goto exit;
1431     }
1432     OIC_LOG(INFO, TAG, "Entering OCSetPlatformInfo");
1433     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_PLATFORM_ID, info.platformID));
1434     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_NAME, info.manufacturerName));
1435     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_URL, info.manufacturerUrl);
1436     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MODEL_NUM, info.modelNumber);
1437     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_DATE, info.dateOfManufacture);
1438     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_PLATFORM_VERSION, info.platformVersion);
1439     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_OS_VERSION, info.operatingSystemVersion);
1440     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_HARDWARE_VERSION, info.hardwareVersion);
1441     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_FIRMWARE_VERSION, info.firmwareVersion);
1442     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_SUPPORT_URL, info.supportUrl);
1443     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_SYSTEM_TIME, info.systemTime);
1444     OIC_LOG(INFO, TAG, "Platform parameter initialized successfully.");
1445     return OC_STACK_OK;
1446
1447 exit:
1448     return OC_STACK_INVALID_PARAM;
1449 }
1450
1451 OCStackResult OCSetDeviceInfo(OCDeviceInfo info)
1452 {
1453     OCStringLL *dataModelVersion = NULL;
1454     OCResource *resource = FindResourceByUri(OC_RSRVD_DEVICE_URI);
1455     if (!resource)
1456     {
1457         OIC_LOG(ERROR, TAG, "Device Resource does not exist.");
1458         goto exit;
1459     }
1460     if (!info.deviceName || info.deviceName[0] == '\0')
1461     {
1462         OIC_LOG(ERROR, TAG, "Null or empty device name.");
1463        return OC_STACK_INVALID_PARAM;
1464     }
1465
1466     if (OCGetServerInstanceIDString() == NULL)
1467     {
1468         OIC_LOG(INFO, TAG, "Device ID generation failed");
1469         goto exit;
1470     }
1471
1472     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, info.deviceName));
1473     for (OCStringLL *temp = info.types; temp; temp = temp->next)
1474     {
1475         if (temp->value)
1476         {
1477             VERIFY_SUCCESS(OCBindResourceTypeToResource(resource, temp->value));
1478         }
1479     }
1480     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_SPEC_VERSION, info.specVersion ?
1481         info.specVersion: OC_SPEC_VERSION));
1482     if (info.dataModelVersions)
1483     {
1484         VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION, info.dataModelVersions));
1485     }
1486     else
1487     {
1488         dataModelVersion = OCCreateOCStringLL(OC_DATA_MODEL_VERSION);
1489         VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION, dataModelVersion));
1490 #ifdef __TIZENRT__
1491         OCFreeOCStringLL(dataModelVersion);
1492 #endif
1493     }
1494     OIC_LOG(INFO, TAG, "Device parameter initialized successfully.");
1495     return OC_STACK_OK;
1496
1497 exit:
1498     if (dataModelVersion)
1499     {
1500         OCFreeOCStringLL(dataModelVersion);
1501     }
1502     return OC_STACK_ERROR;
1503 }
1504
1505 OCStackResult OCGetAttribute(const OCResource *resource, const char *attribute, void **value)
1506 {
1507     if (!resource || !attribute)
1508     {
1509         return OC_STACK_INVALID_PARAM;
1510     }
1511     if (0 == strlen(attribute))
1512     {
1513         return OC_STACK_INVALID_PARAM;
1514     }
1515     for (OCAttribute *temp = resource->rsrcAttributes; temp; temp = temp->next)
1516     {
1517         if (0 == strcmp(attribute, temp->attrName))
1518         {
1519             // A special case as this type return OCStringLL
1520             if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, attribute))
1521             {
1522                 *value = CloneOCStringLL((OCStringLL *)temp->attrValue);
1523                 return OC_STACK_OK;
1524             }
1525             else
1526             {
1527                 *value = OICStrdup((char *)temp->attrValue);
1528                 return OC_STACK_OK;
1529             }
1530         }
1531     }
1532     return OC_STACK_NO_RESOURCE;
1533 }
1534
1535 OCStackResult OCGetPropertyValue(OCPayloadType type, const char *prop, void **value)
1536 {
1537     if (!prop || *value)
1538     {
1539         return OC_STACK_INVALID_PARAM;
1540     }
1541     if (strlen(prop) == 0)
1542     {
1543         return OC_STACK_INVALID_PARAM;
1544     }
1545     OCStackResult res =  OC_STACK_NO_RESOURCE;
1546     if (PAYLOAD_TYPE_DEVICE == type || PAYLOAD_TYPE_PLATFORM == type)
1547     {
1548         const char *pathType = (type == PAYLOAD_TYPE_DEVICE) ? OC_RSRVD_DEVICE_URI : OC_RSRVD_PLATFORM_URI;
1549         OCResource *resource = FindResourceByUri(pathType);
1550         if (!resource)
1551         {
1552             return OC_STACK_NO_RESOURCE;
1553         }
1554
1555         res = OCGetAttribute(resource, prop, value);
1556     }
1557     return res;
1558 }
1559
1560 OCStackResult OCSetAttribute(OCResource* resource, const char* attribute, const void* value)
1561 {
1562     // See if the attribute already exists in the list.
1563     OCAttribute *resAttrib;
1564     for (resAttrib = resource->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
1565     {
1566         if (0 == strcmp(attribute, resAttrib->attrName))
1567         {
1568             // Found, free the old value.
1569             if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName))
1570             {
1571                 OCFreeOCStringLL((OCStringLL *)resAttrib->attrValue);
1572             }
1573             else
1574             {
1575                 OICFree((char *)resAttrib->attrValue);
1576             }
1577             break;
1578         }
1579     }
1580
1581     // If not already in the list, add it.
1582     if (NULL == resAttrib)
1583     {
1584         resAttrib = (OCAttribute *)OICCalloc(1, sizeof(OCAttribute));
1585         VERIFY_PARAM_NON_NULL(TAG, resAttrib, "Failed allocating OCAttribute");
1586         resAttrib->attrName = OICStrdup(attribute);
1587         VERIFY_PARAM_NON_NULL(TAG, resAttrib->attrName, "Failed allocating attribute name");
1588         resAttrib->next = resource->rsrcAttributes;
1589         resource->rsrcAttributes = resAttrib;
1590     }
1591
1592     // Fill in the new value.
1593     if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, attribute))
1594     {
1595         resAttrib->attrValue = CloneOCStringLL((OCStringLL *)value);
1596     }
1597     else
1598     {
1599         resAttrib->attrValue = OICStrdup((char *)value);
1600     }
1601     VERIFY_PARAM_NON_NULL(TAG, resAttrib->attrValue, "Failed allocating attribute value");
1602
1603     return OC_STACK_OK;
1604
1605 exit:
1606     OCDeleteResourceAttributes(resAttrib);
1607     return OC_STACK_NO_MEMORY;
1608
1609 }
1610
1611 OCStackResult OCSetPropertyValue(OCPayloadType type, const char *prop, const void *value)
1612 {
1613     if (!prop || !value)
1614     {
1615         return OC_STACK_INVALID_PARAM;
1616     }
1617     if (strlen(prop) == 0)
1618     {
1619         return OC_STACK_INVALID_PARAM;
1620     }
1621
1622     OCStackResult res = OC_STACK_ERROR;
1623     if (PAYLOAD_TYPE_DEVICE == type || PAYLOAD_TYPE_PLATFORM == type)
1624     {
1625         const char *pathType = (type == PAYLOAD_TYPE_DEVICE) ? OC_RSRVD_DEVICE_URI : OC_RSRVD_PLATFORM_URI;
1626         OCResource *resource = FindResourceByUri(pathType);
1627         if (!resource)
1628         {
1629             OIC_LOG(ERROR, TAG, "Resource does not exist.");
1630         }
1631         else
1632         {
1633             res = OCSetAttribute(resource, prop, value);
1634         }
1635     }
1636
1637     return res;
1638 }