CONPRO-1542 Adding left out error codes conversion from EntityHandler to OCStackResult
[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 #if defined(TCP_ADAPTER) && !defined(DISABLE_TCP_SERVER)
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_PRIVATE, 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             OCPayloadDestroy((OCPayload *)tempPayload);
366             return OC_STACK_ERROR;
367         }
368         OCRepPayloadSetPropString(tempPayload, OC_RSRVD_DEVICE_ID, deviceId);
369     }
370
371     OCResourceType *resType = resourcePtr->rsrcType;
372     while(resType)
373     {
374         OCRepPayloadAddResourceType(tempPayload, resType->resourcetypename);
375         resType = resType->next;
376     }
377
378     OCResourceInterface *resInterface = resourcePtr->rsrcInterface;
379     while(resInterface)
380     {
381         OCRepPayloadAddInterface(tempPayload, resInterface->name);
382         resInterface = resInterface->next;
383     }
384
385     OCAttribute *resAttrib = resourcePtr->rsrcAttributes;
386     while(resAttrib)
387     {
388         if (resAttrib->attrName && resAttrib->attrValue)
389         {
390             if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName))
391             {
392                 char *dmv = OCCreateString((OCStringLL *)resAttrib->attrValue);
393                 if (dmv)
394                 {
395                     OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, dmv);
396                     OICFree(dmv);
397                 }
398             }
399             else
400             {
401                 OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, (char *)resAttrib->attrValue);
402             }
403         }
404         resAttrib = resAttrib->next;
405     }
406
407     if(!*payload)
408     {
409         *payload = tempPayload;
410     }
411     else
412     {
413         OCRepPayloadAppend(*payload, tempPayload);
414     }
415
416     return OC_STACK_OK;
417 }
418
419 OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr,
420                     OCRepPayload** payload, OCDevAddr *devAddr)
421 {
422     if (!resourcePtr)
423     {
424         return OC_STACK_INVALID_PARAM;
425     }
426
427     OCRepPayload *tempPayload = OCRepPayloadCreate();
428     if(!tempPayload)
429     {
430         return OC_STACK_NO_MEMORY;
431     }
432
433     OCRepPayloadSetPropString(tempPayload, OC_RSRVD_HREF, resourcePtr->uri);
434
435     uint8_t numElement = 0;
436     if (OC_STACK_OK == OCGetNumberOfResourceTypes((OCResource *)resourcePtr, &numElement))
437     {
438         size_t rtDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
439         char **rt = (char **)OICMalloc(sizeof(char *) * numElement);
440         if (!rt)
441         {
442             OIC_LOG(ERROR, TAG, "Resource type allocation failed.");
443             OCRepPayloadDestroy(tempPayload);
444             return OC_STACK_NO_MEMORY;
445         }
446         for (uint8_t i = 0; i < numElement; ++i)
447         {
448             const char *value = OCGetResourceTypeName((OCResource *)resourcePtr, i);
449             OIC_LOG_V(DEBUG, TAG, "value: %s", value);
450             rt[i] = OICStrdup(value);
451         }
452         OCRepPayloadSetStringArrayAsOwner(tempPayload, OC_RSRVD_RESOURCE_TYPE, rt, rtDim);
453     }
454
455     numElement = 0;
456     if (OC_STACK_OK == OCGetNumberOfResourceInterfaces((OCResource *)resourcePtr, &numElement))
457     {
458         size_t ifDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
459         char **itf = (char **)OICMalloc(sizeof(char *) * numElement);
460         if (!itf)
461         {
462             OIC_LOG(ERROR, TAG, "Resource interface allocation failed.");
463             OCRepPayloadDestroy(tempPayload);
464             return OC_STACK_NO_MEMORY;
465         }
466         for (uint8_t i = 0; i < numElement; ++i)
467         {
468             const char *value = OCGetResourceInterfaceName((OCResource *)resourcePtr, i);
469             OIC_LOG_V(DEBUG, TAG, "value: %s", value);
470             itf[i] = OICStrdup(value);
471         }
472         OCRepPayloadSetStringArrayAsOwner(tempPayload, OC_RSRVD_INTERFACE, itf, ifDim);
473     }
474
475     for (OCAttribute *resAttrib = resourcePtr->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
476     {
477         if (resAttrib->attrName && resAttrib->attrValue)
478         {
479             if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName))
480             {
481                 char *dmv = OCCreateString((OCStringLL *)resAttrib->attrValue);
482                 if (dmv)
483                 {
484                     OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, dmv);
485                     OICFree(dmv);
486                 }
487             }
488             else
489             {
490                 OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, (char *)resAttrib->attrValue);
491             }
492         }
493     }
494
495     if (devAddr)
496     {
497         OCResourceProperty p = OCGetResourceProperties((OCResourceHandle *)resourcePtr);
498         OCRepPayload *policy = OCRepPayloadCreate();
499         if (!policy)
500         {
501             OCPayloadDestroy((OCPayload *)tempPayload);
502             return OC_STACK_NO_MEMORY;
503         }
504         OCRepPayloadSetPropInt(policy, OC_RSRVD_BITMAP, ((p & OC_DISCOVERABLE) | (p & OC_OBSERVABLE)));
505         if (p & OC_SECURE)
506         {
507             OCRepPayloadSetPropBool(policy, OC_RSRVD_SECURE, p & OC_SECURE);
508             uint16_t securePort = 0;
509             if (GetSecurePortInfo(devAddr, &securePort) != OC_STACK_OK)
510             {
511                 securePort = 0;
512             }
513             OCRepPayloadSetPropInt(policy, OC_RSRVD_HOSTING_PORT, securePort);
514         }
515         OCRepPayloadSetPropObjectAsOwner(tempPayload, OC_RSRVD_POLICY, policy);
516     }
517
518     if (!*payload)
519     {
520         *payload = tempPayload;
521     }
522     else
523     {
524         OCRepPayloadAppend(*payload, tempPayload);
525     }
526
527     return OC_STACK_OK;
528 }
529
530 OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
531                         OCDiscoveryPayload *payload, OCDevAddr *devAddr)
532 {
533     if (!resourcePtr || !payload)
534     {
535         return OC_STACK_INVALID_PARAM;
536     }
537     uint16_t securePort = 0;
538     if (resourcePtr->resourceProperties & OC_SECURE)
539     {
540        if (GetSecurePortInfo(devAddr, &securePort) != OC_STACK_OK)
541        {
542            securePort = 0;
543        }
544     }
545
546 #if defined(TCP_ADAPTER) && !defined(DISABLE_TCP_SERVER)
547     uint16_t tcpPort = 0;
548     GetTCPPortInfo(devAddr, &tcpPort, (resourcePtr->resourceProperties & OC_SECURE));
549
550     OCDiscoveryPayloadAddResource(payload, resourcePtr, securePort, tcpPort);
551 #else
552     OCDiscoveryPayloadAddResource(payload, resourcePtr, securePort);
553 #endif
554
555     return OC_STACK_OK;
556 }
557
558 // TODO: headResource needs to be accessed in a thread-safe manner
559 OCResource *FindResourceByUri(const char* resourceUri)
560 {
561     if(!resourceUri)
562     {
563         return NULL;
564     }
565
566     OCResource * pointer = headResource;
567     while (pointer)
568     {
569         if (pointer->uri && strcmp(resourceUri, pointer->uri) == 0)
570         {
571             return pointer;
572         }
573         pointer = pointer->next;
574     }
575     OIC_LOG_V(INFO, TAG, "Resource %s not found", resourceUri);
576     return NULL;
577 }
578
579 OCStackResult DetermineResourceHandling (const OCServerRequest *request,
580                                          ResourceHandling *handling,
581                                          OCResource **resource)
582 {
583     if(!request || !handling || !resource)
584     {
585         return OC_STACK_INVALID_PARAM;
586     }
587
588     OIC_LOG_V(INFO, TAG, "DetermineResourceHandling for %s", request->resourceUrl);
589
590     // Check if virtual resource
591     if (GetTypeOfVirtualURI(request->resourceUrl) != OC_UNKNOWN_URI)
592     {
593         OIC_LOG_V (INFO, TAG, "%s is virtual", request->resourceUrl);
594         *handling = OC_RESOURCE_VIRTUAL;
595         *resource = headResource;
596         return OC_STACK_OK;
597     }
598     if (strlen((const char*)(request->resourceUrl)) == 0)
599     {
600         // Resource URL not specified
601         *handling = OC_RESOURCE_NOT_SPECIFIED;
602         return OC_STACK_NO_RESOURCE;
603     }
604     else
605     {
606         OCResource *resourcePtr = FindResourceByUri((const char*)request->resourceUrl);
607         *resource = resourcePtr;
608         if (!resourcePtr)
609         {
610             if(defaultDeviceHandler)
611             {
612                 *handling = OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER;
613                 return OC_STACK_OK;
614             }
615
616             // Resource does not exist
617             // and default device handler does not exist
618             *handling = OC_RESOURCE_NOT_SPECIFIED;
619             return OC_STACK_NO_RESOURCE;
620         }
621
622         if (resourcePtr->rsrcChildResourcesHead != NULL)
623         {
624             // Collection resource
625             if (resourcePtr->entityHandler != defaultResourceEHandler)
626             {
627                 *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER;
628                 return OC_STACK_OK;
629             }
630             else
631             {
632                 *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER;
633                 return OC_STACK_OK;
634             }
635         }
636         else
637         {
638             // Resource not a collection
639             if (resourcePtr->entityHandler != defaultResourceEHandler)
640             {
641                 *handling = OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER;
642                 return OC_STACK_OK;
643             }
644             else
645             {
646                 *handling = OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER;
647                 return OC_STACK_OK;
648             }
649         }
650     }
651 }
652
653 OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
654 {
655     OCStackResult result;
656
657     switch (ehResult)
658     {
659         case OC_EH_OK:
660         case OC_EH_CONTENT:
661         case OC_EH_VALID:
662             result = OC_STACK_OK;
663             break;
664         case OC_EH_SLOW:
665             result = OC_STACK_SLOW_RESOURCE;
666             break;
667         case OC_EH_ERROR:
668             result = OC_STACK_ERROR;
669             break;
670         case OC_EH_FORBIDDEN:
671             result = OC_STACK_FORBIDDEN_REQ;
672             break;
673         case OC_EH_RESOURCE_CREATED:
674             result = OC_STACK_RESOURCE_CREATED;
675             break;
676         case OC_EH_RESOURCE_DELETED:
677             result = OC_STACK_RESOURCE_DELETED;
678             break;
679         case OC_EH_CHANGED:
680             result = OC_STACK_RESOURCE_CHANGED;
681             break;
682         case OC_EH_RESOURCE_NOT_FOUND:
683             result = OC_STACK_NO_RESOURCE;
684             break;
685         case OC_EH_TOO_MANY_REQUESTS:
686             result = OC_STACK_TOO_MANY_REQUESTS;
687             break;
688         case OC_EH_INTERNAL_SERVER_ERROR:
689             result = OC_STACK_INTERNAL_SERVER_ERROR;
690             break;
691         case OC_EH_NOT_IMPLEMENTED:
692             result = OC_STACK_NOT_IMPLEMENTED;
693             break;
694         case OC_EH_BAD_GATEWAY:
695             result = OC_STACK_BAD_GATEWAY;
696             break;
697         case OC_EH_SERVICE_UNAVAILABLE:
698             result = OC_STACK_SERVICE_UNAVAILABLE;
699             break;
700         case OC_EH_RETRANSMIT_TIMEOUT:
701             result = OC_STACK_GATEWAY_TIMEOUT;
702             break;
703         case OC_EH_PROXY_NOT_SUPPORTED:
704             result = OC_STACK_PROXY_NOT_SUPPORTED;
705             break;
706         case OC_EH_BAD_REQ:
707             result = OC_STACK_INVALID_QUERY;
708             break;
709         case OC_EH_UNAUTHORIZED_REQ:
710             result = OC_STACK_UNAUTHORIZED_REQ;
711             break;
712         case OC_EH_BAD_OPT:
713             result = OC_STACK_INVALID_OPTION;
714             break;
715         case OC_EH_TOO_LARGE:
716             result = OC_STACK_TOO_LARGE_REQ;
717             break;
718         case OC_EH_NOT_ACCEPTABLE:
719             result = OC_STACK_NOT_ACCEPTABLE;
720             break;
721         case OC_EH_METHOD_NOT_ALLOWED:
722             result = OC_STACK_METHOD_NOT_ALLOWED;
723             break;
724         default:
725             result = OC_STACK_ERROR;
726     }
727
728     return result;
729 }
730
731 static bool resourceMatchesRTFilter(OCResource *resource, char *resourceTypeFilter)
732 {
733     if (!resource)
734     {
735         return false;
736     }
737
738     // Null is analogous to no filter.
739     if (NULL == resourceTypeFilter)
740     {
741         return true;
742     }
743
744     // Empty resourceType filter is analogous to error query
745     if (0 == strlen(resourceTypeFilter))
746     {
747         return false;
748     }
749
750     for (OCResourceType *rtPtr = resource->rsrcType; rtPtr; rtPtr = rtPtr->next)
751     {
752         if (0 == strcmp(rtPtr->resourcetypename, resourceTypeFilter))
753         {
754             return true;
755         }
756     }
757
758     OIC_LOG_V(INFO, TAG, "%s does not contain rt=%s.", resource->uri, resourceTypeFilter);
759     return false;
760 }
761
762 static bool resourceMatchesIFFilter(OCResource *resource, char *interfaceFilter)
763 {
764     if (!resource)
765     {
766         return false;
767     }
768
769     // Null is analogous to no filter.
770     if (NULL == interfaceFilter)
771     {
772         return true;
773     }
774
775     // Empty interface filter is analogous to error query
776     if (0 == strlen(interfaceFilter))
777     {
778         return false;
779     }
780
781     for (OCResourceInterface *ifPtr = resource->rsrcInterface; ifPtr; ifPtr = ifPtr->next)
782     {
783         if (0 == strcmp(ifPtr->name, interfaceFilter) ||
784             0 == strcmp(OC_RSRVD_INTERFACE_LL, interfaceFilter) ||
785             0 == strcmp(OC_RSRVD_INTERFACE_DEFAULT, interfaceFilter))
786         {
787             return true;
788         }
789     }
790
791     OIC_LOG_V(INFO, TAG, "%s does not contain if=%s.", resource->uri, interfaceFilter);
792     return false;
793 }
794
795 /*
796  * If the filters are null, they will be assumed to NOT be present
797  * and the resource will not be matched against them.
798  * Function will return true if all non null AND non empty filters passed in find a match.
799  */
800 static bool includeThisResourceInResponse(OCResource *resource,
801                                           char *interfaceFilter,
802                                           char *resourceTypeFilter)
803 {
804     if (!resource)
805     {
806         OIC_LOG(ERROR, TAG, "Invalid resource");
807         return false;
808     }
809
810     if (resource->resourceProperties & OC_EXPLICIT_DISCOVERABLE)
811     {
812         /*
813          * At least one valid filter should be available to
814          * include the resource in discovery response
815          */
816         if (!(resourceTypeFilter && *resourceTypeFilter))
817         {
818             OIC_LOG_V(INFO, TAG, "%s no query string for EXPLICIT_DISCOVERABLE\
819                 resource", resource->uri);
820             return false;
821         }
822     }
823     else if (!(resource->resourceProperties & OC_ACTIVE) ||
824          !(resource->resourceProperties & OC_DISCOVERABLE))
825     {
826         OIC_LOG_V(INFO, TAG, "%s not ACTIVE or DISCOVERABLE", resource->uri);
827         return false;
828     }
829
830     return resourceMatchesIFFilter(resource, interfaceFilter) &&
831            resourceMatchesRTFilter(resource, resourceTypeFilter);
832 }
833
834 OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCResource *resource,
835                                 OCPayload *discoveryPayload, OCEntityHandlerResult ehResult)
836 {
837     OCEntityHandlerResponse response = {0};
838
839     response.ehResult = ehResult;
840     response.payload = discoveryPayload;
841     response.persistentBufferFlag = 0;
842     response.requestHandle = (OCRequestHandle) request->requestId;
843     response.resourceHandle = (OCResourceHandle) resource;
844
845     return OCDoResponse(&response);
846 }
847
848 static OCStackResult EHRequest(OCEntityHandlerRequest *ehRequest, OCPayloadType type,
849     OCServerRequest *request, OCResource *resource)
850 {
851     return FormOCEntityHandlerRequest(ehRequest,
852                                      (OCRequestHandle)request->requestId,
853                                      request->method,
854                                      &request->devAddr,
855                                      (OCResourceHandle)resource,
856                                      request->query,
857                                      type,
858                                      request->payload,
859                                      request->payloadSize,
860                                      request->numRcvdVendorSpecificHeaderOptions,
861                                      request->rcvdVendorSpecificHeaderOptions,
862                                      (OCObserveAction)request->observationOption,
863                                      (OCObservationId)0,
864                                      request->coapID);
865 }
866
867 #ifdef RD_SERVER
868 /**
869  * Find resource at the resource directory server. This resource is not local resource but a
870  * remote resource.
871  *
872  * @param resource The resource to check the matching resource URI.
873  * @param interfaceQuery The interface query parameter.
874  * @param resourceTypeQuery The resourceType query parameter.
875  * @param discPayload The payload that will be added with the resource information if found at RD.
876  *
877  * @return ::OC_STACK_OK if the resource is found else ::OC_STACK_NO_RESOURCE.
878  * In case if build is not with flag RD_SERVER, it returns ::OC_STACK_NO_RESOURCE.
879  */
880 static OCStackResult findResourceAtRD(const OCResource* resource, const char *interfaceQuery,
881     const char *resourceTypeQuery, OCDiscoveryPayload *discPayload)
882 {
883     if (strcmp(resource->uri, OC_RSRVD_RD_URI) == 0)
884     {
885         if (OC_STACK_OK == OCRDDatabaseCheckResources(interfaceQuery, resourceTypeQuery, discPayload))
886         {
887             return OC_STACK_OK;
888         }
889     }
890
891     return OC_STACK_NO_RESOURCE;
892 }
893 #endif
894
895 /**
896  * Creates a discovery payload and add device id information. This information is included in all
897  * /oic/res response.
898  *
899  * @param payload  payload that will have memory alllocated and device id information added.
900  *
901  * @return ::OC_STACK_OK if successful in allocating memory and adding ID information.
902  * ::OC_STACK_NO_MEMORY if failed allocating the memory.
903  */
904 static OCStackResult discoveryPayloadCreateAndAddDeviceId(OCPayload **payload)
905 {
906     if (*payload)
907     {
908         OIC_LOG(DEBUG, TAG, "Payload is already allocated");
909         return OC_STACK_OK;
910     }
911
912     *payload = (OCPayload *) OCDiscoveryPayloadCreate();
913     VERIFY_PARAM_NON_NULL(TAG, *payload, "Failed adding device id to discovery payload.");
914
915     {
916         OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)*payload;
917         discPayload->sid = (char *)OICCalloc(1, UUID_STRING_SIZE);
918         VERIFY_PARAM_NON_NULL(TAG, discPayload->sid, "Failed adding device id to discovery payload.");
919
920         const char* uid = OCGetServerInstanceIDString();
921         if (uid)
922         {
923             memcpy(discPayload->sid, uid, UUID_STRING_SIZE);
924         }
925
926     }
927     return OC_STACK_OK;
928 exit:
929     OCPayloadDestroy(*payload);
930     return OC_STACK_NO_MEMORY;
931 }
932
933 /**
934  * Add the common properties to the payload, they are only included in case of oic.if.baseline response.
935  *
936  * @param discPayload payload that will have the baseline information included.
937  *
938  * @return ::OC_STACK_OK if successful in adding all the information. ::OC_STACK_NO_MEMORY if failed
939  * allocating the memory for the baseline information.
940  */
941 static OCStackResult addDiscoveryBaselineCommonProperties(OCDiscoveryPayload *discPayload)
942 {
943     if (!discPayload)
944     {
945         OIC_LOG(ERROR, TAG, "Payload is not allocated");
946         return OC_STACK_ERROR;
947     }
948
949     OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, (void **)&discPayload->name);
950
951     discPayload->type = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
952     VERIFY_PARAM_NON_NULL(TAG, discPayload->type, "Failed adding rt to discovery payload.");
953     discPayload->type->value = OICStrdup(OC_RSRVD_RESOURCE_TYPE_RES);
954     VERIFY_PARAM_NON_NULL(TAG, discPayload->type, "Failed adding rt value to discovery payload.");
955
956     OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_LL);
957     OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_DEFAULT);
958     VERIFY_PARAM_NON_NULL(TAG, discPayload->iface, "Failed adding if to discovery payload.");
959
960     return OC_STACK_OK;
961
962 exit:
963     return OC_STACK_NO_MEMORY;
964 }
965
966 static bool isUnicast(OCServerRequest *request)
967 {
968     bool isMulticast = request->devAddr.flags &  OC_MULTICAST;
969     return (isMulticast == false &&
970            (request->devAddr.adapter != OC_ADAPTER_RFCOMM_BTEDR) &&
971            (request->devAddr.adapter != OC_ADAPTER_GATT_BTLE));
972 }
973
974 static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource)
975 {
976     if (!request || !resource)
977     {
978         return OC_STACK_INVALID_PARAM;
979     }
980
981     OCPayload* payload = NULL;
982     char *interfaceQuery = NULL;
983     char *resourceTypeQuery = NULL;
984
985     OIC_LOG(INFO, TAG, "Entering HandleVirtualResource");
986
987     OCVirtualResources virtualUriInRequest = GetTypeOfVirtualURI (request->resourceUrl);
988
989 #ifdef TCP_ADAPTER
990     if (OC_KEEPALIVE_RESOURCE_URI == virtualUriInRequest)
991     {
992         // Received request for a keepalive
993         OIC_LOG(INFO, TAG, "Request is for KeepAlive Request");
994         return OCHandleKeepAliveRequest(request, resource);
995     }
996 #endif
997
998     OCStackResult discoveryResult = OC_STACK_ERROR;
999     if (request->method == OC_REST_PUT || request->method == OC_REST_POST ||
1000         request->method == OC_REST_DELETE)
1001     {
1002         OIC_LOG_V(ERROR, TAG, "Resource : %s not permitted for method: %d",
1003             request->resourceUrl, request->method);
1004         return OC_STACK_UNAUTHORIZED_REQ;
1005     }
1006
1007     // Step 1: Generate the response to discovery request
1008     if (virtualUriInRequest == OC_WELL_KNOWN_URI
1009 #ifdef MQ_BROKER
1010             || virtualUriInRequest == OC_MQ_BROKER_URI
1011 #endif
1012             )
1013     {
1014         discoveryResult = getQueryParamsForFiltering(virtualUriInRequest, request->query,
1015                 &interfaceQuery, &resourceTypeQuery);
1016         VERIFY_SUCCESS(discoveryResult);
1017
1018         if (!interfaceQuery && !resourceTypeQuery)
1019         {
1020             // If no query is sent, default interface is used i.e. oic.if.ll.
1021             interfaceQuery = OICStrdup(OC_RSRVD_INTERFACE_LL);
1022         }
1023
1024         discoveryResult = discoveryPayloadCreateAndAddDeviceId(&payload);
1025         VERIFY_PARAM_NON_NULL(TAG, payload, "Failed creating Discovery Payload.");
1026         VERIFY_SUCCESS(discoveryResult);
1027
1028         OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)payload;
1029         if (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_DEFAULT))
1030         {
1031             discoveryResult = addDiscoveryBaselineCommonProperties(discPayload);
1032             VERIFY_SUCCESS(discoveryResult);
1033         }
1034         OCResourceProperty prop = OC_DISCOVERABLE;
1035 #ifdef MQ_BROKER
1036         prop = (OC_MQ_BROKER_URI == virtualUriInRequest) ? OC_MQ_BROKER : prop;
1037 #endif
1038         for (; resource && discoveryResult == OC_STACK_OK; resource = resource->next)
1039         {
1040             // This case will handle when no resource type and it is oic.if.ll.
1041             // Do not assume check if the query is ll
1042             if (!resourceTypeQuery &&
1043                 (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_LL)))
1044             {
1045                 // Only include discoverable type
1046                 if (resource->resourceProperties & prop)
1047                 {
1048                     discoveryResult = BuildVirtualResourceResponse(resource, discPayload, &request->devAddr);
1049                 }
1050             }
1051             else if (includeThisResourceInResponse(resource, interfaceQuery, resourceTypeQuery))
1052             {
1053                 discoveryResult = BuildVirtualResourceResponse(resource, discPayload, &request->devAddr);
1054             }
1055             else
1056             {
1057                 discoveryResult = OC_STACK_OK;
1058             }
1059         }
1060         if (discPayload->resources == NULL)
1061         {
1062             discoveryResult = OC_STACK_NO_RESOURCE;
1063         }
1064     }
1065     else if (virtualUriInRequest == OC_DEVICE_URI)
1066     {
1067         OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_DEVICE_URI);
1068         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Device URI not found.");
1069         discoveryResult = BuildDevicePlatformPayload(resourcePtr, (OCRepPayload **)&payload, true);
1070     }
1071     else if (virtualUriInRequest == OC_PLATFORM_URI)
1072     {
1073         OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_PLATFORM_URI);
1074         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Platform URI not found.");
1075         discoveryResult = BuildDevicePlatformPayload(resourcePtr, (OCRepPayload **)&payload, false);
1076     }
1077 #ifdef ROUTING_GATEWAY
1078     else if (OC_GATEWAY_URI == virtualUriInRequest)
1079     {
1080         // Received request for a gateway
1081         OIC_LOG(INFO, TAG, "Request is for Gateway Virtual Request");
1082         discoveryResult = RMHandleGatewayRequest(request, resource);
1083     }
1084 #endif
1085
1086     /**
1087      * Step 2: Send the discovery response
1088      *
1089      * Iotivity should respond to discovery requests in below manner:
1090      * 1)If query filter matching fails and discovery request is multicast,
1091      *   it should NOT send any response.
1092      * 2)If query filter matching fails and discovery request is unicast,
1093      *   it should send an error(RESOURCE_NOT_FOUND - 404) response.
1094      * 3)If Server does not have any 'DISCOVERABLE' resources and discovery
1095      *   request is multicast, it should NOT send any response.
1096      * 4)If Server does not have any 'DISCOVERABLE' resources and discovery
1097      *   request is unicast, it should send an error(RESOURCE_NOT_FOUND - 404) response.
1098      */
1099
1100 #ifdef WITH_PRESENCE
1101     if ((virtualUriInRequest == OC_PRESENCE) &&
1102         (resource->resourceProperties & OC_ACTIVE))
1103     {
1104         // Need to send ACK when the request is CON.
1105         if (request->qos == OC_HIGH_QOS)
1106         {
1107             CAEndpoint_t endpoint = { .adapter = CA_DEFAULT_ADAPTER };
1108             CopyDevAddrToEndpoint(&request->devAddr, &endpoint);
1109             SendDirectStackResponse(&endpoint, request->coapID, CA_EMPTY, CA_MSG_ACKNOWLEDGE,
1110                                     0, NULL, NULL, 0, NULL, CA_RESPONSE_FOR_RES);
1111         }
1112         FindAndDeleteServerRequest(request);
1113
1114         // Presence uses observer notification api to respond via SendPresenceNotification.
1115         SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
1116     }
1117     else
1118 #endif
1119 #if ROUTING_GATEWAY
1120     // Gateway uses the RMHandleGatewayRequest to respond to the request.
1121     if (OC_GATEWAY_URI != virtualUriInRequest)
1122 #endif
1123     {
1124         OIC_LOG_PAYLOAD(DEBUG, payload);
1125         if(discoveryResult == OC_STACK_OK)
1126         {
1127
1128             SendNonPersistantDiscoveryResponse(request, resource, payload, OC_EH_OK);
1129         }
1130         else // Error handling
1131         {
1132             if (isUnicast(request))
1133             {
1134                 OIC_LOG_V(ERROR, TAG, "Sending a (%d) error to (%d) discovery request",
1135                     discoveryResult, virtualUriInRequest);
1136                 SendNonPersistantDiscoveryResponse(request, resource, NULL,
1137                     (discoveryResult == OC_STACK_NO_RESOURCE) ?
1138                         OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR);
1139             }
1140             else // Multicast
1141             {
1142                 // Ignoring the discovery request as per RFC 7252, Section #8.2
1143                 OIC_LOG(INFO, TAG, "Silently ignoring the request since no useful data to send.");
1144                 // the request should be removed.
1145                 // since it never remove and causes a big memory waste.
1146                 FindAndDeleteServerRequest(request);
1147             }
1148             discoveryResult = OC_STACK_CONTINUE;
1149         }
1150     }
1151
1152 exit:
1153     if (interfaceQuery)
1154     {
1155         OICFree(interfaceQuery);
1156     }
1157
1158     if (resourceTypeQuery)
1159     {
1160         OICFree(resourceTypeQuery);
1161     }
1162     OCPayloadDestroy(payload);
1163
1164     // To ignore the message, OC_STACK_CONTINUE is sent
1165     return discoveryResult;
1166 }
1167
1168 static OCStackResult
1169 HandleDefaultDeviceEntityHandler(OCServerRequest *request)
1170 {
1171     if (!request)
1172     {
1173         return OC_STACK_INVALID_PARAM;
1174     }
1175
1176     OCEntityHandlerResult ehResult = OC_EH_ERROR;
1177     OCEntityHandlerRequest ehRequest = {0};
1178     OIC_LOG(INFO, TAG, "Entering HandleResourceWithDefaultDeviceEntityHandler");
1179     OCStackResult result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, NULL);
1180     VERIFY_SUCCESS(result);
1181
1182     // At this point we know for sure that defaultDeviceHandler exists
1183     ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
1184                                   (char*) request->resourceUrl, defaultDeviceHandlerCallbackParameter);
1185     if(ehResult == OC_EH_SLOW)
1186     {
1187         OIC_LOG(INFO, TAG, "This is a slow resource");
1188         request->slowFlag = 1;
1189     }
1190
1191     result = EntityHandlerCodeToOCStackCode(ehResult);
1192
1193     // Clear server request on error case
1194     if (!OCResultToSuccess(result))
1195     {
1196         FindAndDeleteServerRequest(request);
1197     }
1198
1199 exit:
1200     OCPayloadDestroy(ehRequest.payload);
1201     return result;
1202 }
1203
1204 static OCStackResult
1205 HandleResourceWithEntityHandler(OCServerRequest *request,
1206                                 OCResource *resource)
1207 {
1208     if(!request || ! resource)
1209     {
1210         return OC_STACK_INVALID_PARAM;
1211     }
1212
1213     OCStackResult result = OC_STACK_ERROR;
1214     OCEntityHandlerResult ehResult = OC_EH_ERROR;
1215     OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
1216     ResourceObserver *resObs = NULL;
1217
1218     OCEntityHandlerRequest ehRequest = {0};
1219
1220     OIC_LOG(INFO, TAG, "Entering HandleResourceWithEntityHandler");
1221     OCPayloadType type = PAYLOAD_TYPE_REPRESENTATION;
1222     // check the security resource
1223     if (request && request->resourceUrl && SRMIsSecurityResourceURI(request->resourceUrl))
1224     {
1225         type = PAYLOAD_TYPE_SECURITY;
1226     }
1227
1228     result = EHRequest(&ehRequest, type, request, resource);
1229     VERIFY_SUCCESS(result);
1230
1231     if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
1232     {
1233         OIC_LOG(INFO, TAG, "No observation requested");
1234         ehFlag = OC_REQUEST_FLAG;
1235     }
1236     else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER)
1237     {
1238         OIC_LOG(INFO, TAG, "Observation registration requested");
1239
1240         ResourceObserver *obs = GetObserverUsingToken (request->requestToken,
1241                                     request->tokenLength);
1242
1243         if (obs)
1244         {
1245             OIC_LOG (INFO, TAG, "Observer with this token already present");
1246             OIC_LOG (INFO, TAG, "Possibly re-transmitted CON OBS request");
1247             OIC_LOG (INFO, TAG, "Not adding observer. Not responding to client");
1248             OIC_LOG (INFO, TAG, "The first request for this token is already ACKED.");
1249
1250             FreeObserver(obs);
1251             return OC_STACK_OK;
1252         }
1253
1254         result = GenerateObserverId(&ehRequest.obsInfo.obsId);
1255         VERIFY_SUCCESS(result);
1256
1257         result = AddObserver ((const char*)(request->resourceUrl),
1258                 (const char *)(request->query),
1259                 ehRequest.obsInfo.obsId, request->requestToken, request->tokenLength,
1260                 resource, request->qos, request->acceptFormat,
1261                 &request->devAddr);
1262
1263         if(result == OC_STACK_OK)
1264         {
1265             OIC_LOG(INFO, TAG, "Added observer successfully");
1266             request->observeResult = OC_STACK_OK;
1267             ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
1268         }
1269         else if (result == OC_STACK_RESOURCE_ERROR)
1270         {
1271             OIC_LOG(INFO, TAG, "The Resource is not active, discoverable or observable");
1272             request->observeResult = OC_STACK_ERROR;
1273             ehFlag = OC_REQUEST_FLAG;
1274         }
1275         else
1276         {
1277             // The error in observeResult for the request will be used when responding to this
1278             // request by omitting the observation option/sequence number.
1279             request->observeResult = OC_STACK_ERROR;
1280             OIC_LOG(ERROR, TAG, "Observer Addition failed");
1281             ehFlag = OC_REQUEST_FLAG;
1282             FindAndDeleteServerRequest(request);
1283             goto exit;
1284         }
1285
1286     }
1287     else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER)
1288     {
1289         OIC_LOG(INFO, TAG, "Deregistering observation requested");
1290
1291         resObs = GetObserverUsingToken (request->requestToken, request->tokenLength);
1292
1293         if (NULL == resObs)
1294         {
1295             // Stack does not contain this observation request
1296             // Either token is incorrect or observation list is corrupted
1297             result = OC_STACK_NO_RESOURCE;
1298             goto exit;
1299         }
1300         ehRequest.obsInfo.obsId = resObs->observeId;
1301         ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
1302
1303         result = DeleteObserverUsingToken (request->requestToken, request->tokenLength);
1304
1305         if(result == OC_STACK_OK)
1306         {
1307             OIC_LOG(INFO, TAG, "Removed observer successfully");
1308             request->observeResult = OC_STACK_OK;
1309             // There should be no observe option header for de-registration response.
1310             // Set as an invalid value here so we can detect it later and remove the field in response.
1311             request->observationOption = MAX_SEQUENCE_NUMBER + 1;
1312         }
1313         else
1314         {
1315             request->observeResult = OC_STACK_ERROR;
1316             OIC_LOG(ERROR, TAG, "Observer Removal failed");
1317             FindAndDeleteServerRequest(request);
1318             goto exit;
1319         }
1320     }
1321     else
1322     {
1323         result = OC_STACK_ERROR;
1324         goto exit;
1325     }
1326
1327     ehResult = resource->entityHandler(ehFlag, &ehRequest, resource->entityHandlerCallbackParam);
1328     if(ehResult == OC_EH_SLOW)
1329     {
1330         OIC_LOG(INFO, TAG, "This is a slow resource");
1331         request->slowFlag = 1;
1332     }
1333
1334     result = EntityHandlerCodeToOCStackCode(ehResult);
1335
1336     // Clear server request on error case
1337     if (!OCResultToSuccess(result))
1338     {
1339         FindAndDeleteServerRequest(request);
1340     }
1341
1342 exit:
1343     OCPayloadDestroy(ehRequest.payload);
1344     FreeObserver(resObs);
1345     return result;
1346 }
1347
1348 static OCStackResult HandleCollectionResourceDefaultEntityHandler(OCServerRequest *request,
1349                                                                   OCResource *resource)
1350 {
1351     if (!request || !resource)
1352     {
1353         return OC_STACK_INVALID_PARAM;
1354     }
1355
1356     OCEntityHandlerRequest ehRequest = {0};
1357     OCStackResult result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, resource);
1358     if(result == OC_STACK_OK)
1359     {
1360         result = DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest);
1361     }
1362
1363     OCPayloadDestroy(ehRequest.payload);
1364     return result;
1365 }
1366
1367 OCStackResult
1368 ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request)
1369 {
1370     OCStackResult ret = OC_STACK_OK;
1371
1372     switch (resHandling)
1373     {
1374         case OC_RESOURCE_VIRTUAL:
1375         {
1376             ret = HandleVirtualResource (request, resource);
1377             break;
1378         }
1379         case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER:
1380         {
1381             ret = HandleDefaultDeviceEntityHandler(request);
1382             break;
1383         }
1384         case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
1385         {
1386             OIC_LOG(INFO, TAG, "OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER");
1387             return OC_STACK_ERROR;
1388         }
1389         case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
1390         {
1391             ret = HandleResourceWithEntityHandler (request, resource);
1392             break;
1393         }
1394         case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
1395         {
1396             ret = HandleResourceWithEntityHandler (request, resource);
1397             break;
1398         }
1399         case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
1400         {
1401             ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
1402             break;
1403         }
1404         case OC_RESOURCE_NOT_SPECIFIED:
1405         {
1406             ret = OC_STACK_NO_RESOURCE;
1407             break;
1408         }
1409         default:
1410         {
1411             OIC_LOG(INFO, TAG, "Invalid Resource Determination");
1412             return OC_STACK_ERROR;
1413         }
1414     }
1415     return ret;
1416 }
1417
1418 OCStackResult OCSetPlatformInfo(OCPlatformInfo info)
1419 {
1420     OCResource *resource = NULL;
1421     if (!info.platformID || !info.manufacturerName)
1422     {
1423         OIC_LOG(ERROR, TAG, "No value specified.");
1424         goto exit;
1425     }
1426     if (0 == strlen(info.platformID) || 0 == strlen(info.manufacturerName))
1427     {
1428         OIC_LOG(ERROR, TAG, "The passed value cannot be empty");
1429         goto exit;
1430     }
1431     if ((info.manufacturerName && strlen(info.manufacturerName) > MAX_PLATFORM_NAME_LENGTH) ||
1432         (info.manufacturerUrl && strlen(info.manufacturerUrl) > MAX_PLATFORM_URL_LENGTH) ||
1433         (info.modelNumber && strlen(info.modelNumber) > MAX_PLATFORM_NAME_LENGTH) ||
1434         (info.platformVersion && strlen(info.platformVersion) > MAX_PLATFORM_NAME_LENGTH) ||
1435         (info.operatingSystemVersion && strlen(info.operatingSystemVersion) > MAX_PLATFORM_NAME_LENGTH) ||
1436         (info.hardwareVersion && strlen(info.hardwareVersion) > MAX_PLATFORM_NAME_LENGTH) ||
1437         (info.firmwareVersion && strlen(info.firmwareVersion) > MAX_PLATFORM_NAME_LENGTH) ||
1438         (info.supportUrl && strlen(info.supportUrl) > MAX_PLATFORM_URL_LENGTH))
1439     {
1440         OIC_LOG(ERROR, TAG, "The passed value is bigger than permitted.");
1441         goto exit;
1442     }
1443
1444     resource = FindResourceByUri(OC_RSRVD_PLATFORM_URI);
1445     if (!resource)
1446     {
1447         OIC_LOG(ERROR, TAG, "Platform Resource does not exist.");
1448         goto exit;
1449     }
1450     OIC_LOG(INFO, TAG, "Entering OCSetPlatformInfo");
1451     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_PLATFORM_ID, info.platformID));
1452     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_NAME, info.manufacturerName));
1453     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_URL, info.manufacturerUrl);
1454     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MODEL_NUM, info.modelNumber);
1455     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_DATE, info.dateOfManufacture);
1456     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_PLATFORM_VERSION, info.platformVersion);
1457     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_OS_VERSION, info.operatingSystemVersion);
1458     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_HARDWARE_VERSION, info.hardwareVersion);
1459     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_FIRMWARE_VERSION, info.firmwareVersion);
1460     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_SUPPORT_URL, info.supportUrl);
1461     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_SYSTEM_TIME, info.systemTime);
1462     OIC_LOG(INFO, TAG, "Platform parameter initialized successfully.");
1463     return OC_STACK_OK;
1464
1465 exit:
1466     return OC_STACK_INVALID_PARAM;
1467 }
1468
1469 OCStackResult OCSetDeviceInfo(OCDeviceInfo info)
1470 {
1471     OCStringLL *dataModelVersion = NULL;
1472     OCResource *resource = FindResourceByUri(OC_RSRVD_DEVICE_URI);
1473     if (!resource)
1474     {
1475         OIC_LOG(ERROR, TAG, "Device Resource does not exist.");
1476         goto exit;
1477     }
1478     if (!info.deviceName || info.deviceName[0] == '\0')
1479     {
1480         OIC_LOG(ERROR, TAG, "Null or empty device name.");
1481        return OC_STACK_INVALID_PARAM;
1482     }
1483
1484     if (OCGetServerInstanceIDString() == NULL)
1485     {
1486         OIC_LOG(INFO, TAG, "Device ID generation failed");
1487         goto exit;
1488     }
1489
1490     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, info.deviceName));
1491     for (OCStringLL *temp = info.types; temp; temp = temp->next)
1492     {
1493         if (temp->value)
1494         {
1495             VERIFY_SUCCESS(OCBindResourceTypeToResource(resource, temp->value));
1496         }
1497     }
1498     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_SPEC_VERSION, info.specVersion ?
1499         info.specVersion: OC_SPEC_VERSION));
1500     if (info.dataModelVersions)
1501     {
1502         VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION, info.dataModelVersions));
1503     }
1504     else
1505     {
1506         dataModelVersion = OCCreateOCStringLL(OC_DATA_MODEL_VERSION);
1507         VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION, dataModelVersion));
1508 #ifdef __TIZENRT__
1509         OCFreeOCStringLL(dataModelVersion);
1510 #endif
1511     }
1512     OIC_LOG(INFO, TAG, "Device parameter initialized successfully.");
1513     return OC_STACK_OK;
1514
1515 exit:
1516     if (dataModelVersion)
1517     {
1518         OCFreeOCStringLL(dataModelVersion);
1519     }
1520     return OC_STACK_ERROR;
1521 }
1522
1523 OCStackResult OCGetAttribute(const OCResource *resource, const char *attribute, void **value)
1524 {
1525     if (!resource || !attribute)
1526     {
1527         return OC_STACK_INVALID_PARAM;
1528     }
1529     if (0 == strlen(attribute))
1530     {
1531         return OC_STACK_INVALID_PARAM;
1532     }
1533     for (OCAttribute *temp = resource->rsrcAttributes; temp; temp = temp->next)
1534     {
1535         if (0 == strcmp(attribute, temp->attrName))
1536         {
1537             // A special case as this type return OCStringLL
1538             if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, attribute))
1539             {
1540                 *value = CloneOCStringLL((OCStringLL *)temp->attrValue);
1541                 return OC_STACK_OK;
1542             }
1543             else
1544             {
1545                 *value = OICStrdup((char *)temp->attrValue);
1546                 return OC_STACK_OK;
1547             }
1548         }
1549     }
1550     return OC_STACK_NO_RESOURCE;
1551 }
1552
1553 OCStackResult OCGetPropertyValue(OCPayloadType type, const char *prop, void **value)
1554 {
1555     if (!prop || *value)
1556     {
1557         return OC_STACK_INVALID_PARAM;
1558     }
1559     if (strlen(prop) == 0)
1560     {
1561         return OC_STACK_INVALID_PARAM;
1562     }
1563     OCStackResult res =  OC_STACK_NO_RESOURCE;
1564     if (PAYLOAD_TYPE_DEVICE == type || PAYLOAD_TYPE_PLATFORM == type)
1565     {
1566         const char *pathType = (type == PAYLOAD_TYPE_DEVICE) ? OC_RSRVD_DEVICE_URI : OC_RSRVD_PLATFORM_URI;
1567         OCResource *resource = FindResourceByUri(pathType);
1568         if (!resource)
1569         {
1570             return OC_STACK_NO_RESOURCE;
1571         }
1572
1573         res = OCGetAttribute(resource, prop, value);
1574     }
1575     return res;
1576 }
1577
1578 OCStackResult OCSetAttribute(OCResource* resource, const char* attribute, const void* value)
1579 {
1580     // See if the attribute already exists in the list.
1581     OCAttribute *resAttrib;
1582     for (resAttrib = resource->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
1583     {
1584         if (0 == strcmp(attribute, resAttrib->attrName))
1585         {
1586             // Found, free the old value.
1587             if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName))
1588             {
1589                 OCFreeOCStringLL((OCStringLL *)resAttrib->attrValue);
1590             }
1591             else
1592             {
1593                 OICFree((char *)resAttrib->attrValue);
1594             }
1595             break;
1596         }
1597     }
1598
1599     // If not already in the list, add it.
1600     if (NULL == resAttrib)
1601     {
1602         resAttrib = (OCAttribute *)OICCalloc(1, sizeof(OCAttribute));
1603         VERIFY_PARAM_NON_NULL(TAG, resAttrib, "Failed allocating OCAttribute");
1604         resAttrib->attrName = OICStrdup(attribute);
1605         VERIFY_PARAM_NON_NULL(TAG, resAttrib->attrName, "Failed allocating attribute name");
1606         resAttrib->next = resource->rsrcAttributes;
1607         resource->rsrcAttributes = resAttrib;
1608     }
1609
1610     // Fill in the new value.
1611     if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, attribute))
1612     {
1613         resAttrib->attrValue = CloneOCStringLL((OCStringLL *)value);
1614     }
1615     else
1616     {
1617         resAttrib->attrValue = OICStrdup((char *)value);
1618     }
1619     VERIFY_PARAM_NON_NULL(TAG, resAttrib->attrValue, "Failed allocating attribute value");
1620
1621     return OC_STACK_OK;
1622
1623 exit:
1624     OCDeleteResourceAttributes(resAttrib);
1625     return OC_STACK_NO_MEMORY;
1626
1627 }
1628
1629 OCStackResult OCSetPropertyValue(OCPayloadType type, const char *prop, const void *value)
1630 {
1631     if (!prop || !value)
1632     {
1633         return OC_STACK_INVALID_PARAM;
1634     }
1635     if (strlen(prop) == 0)
1636     {
1637         return OC_STACK_INVALID_PARAM;
1638     }
1639
1640     OCStackResult res = OC_STACK_ERROR;
1641     if (PAYLOAD_TYPE_DEVICE == type || PAYLOAD_TYPE_PLATFORM == type)
1642     {
1643         const char *pathType = (type == PAYLOAD_TYPE_DEVICE) ? OC_RSRVD_DEVICE_URI : OC_RSRVD_PLATFORM_URI;
1644         OCResource *resource = FindResourceByUri(pathType);
1645         if (!resource)
1646         {
1647             OIC_LOG(ERROR, TAG, "Resource does not exist.");
1648         }
1649         else
1650         {
1651             res = OCSetAttribute(resource, prop, value);
1652         }
1653     }
1654
1655     return res;
1656 }