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