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