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