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