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