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