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