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