[IOT-1685] Make /oic/res observable.
[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 "ocpayload.h"
48 #include "secureresourcemanager.h"
49 #include "cacommon.h"
50 #include "cainterface.h"
51 #include "ocpayload.h"
52 #include "oickeepalive.h"
53 #include "platform_features.h"
54 #include "payload_logging.h"
55 #include "ocendpoint.h"
56 #include "ocstackinternal.h"
57
58 #ifdef ROUTING_GATEWAY
59 #include "routingmanager.h"
60 #endif
61
62 /// Module Name
63 #define TAG "OIC_RI_RESOURCE"
64
65 // using 1k as block size since most persistent storage implementations use a power of 2.
66 #define INTROSPECTION_FILE_SIZE_BLOCK 1024
67
68 #define VERIFY_SUCCESS(op) { if (op != (OC_STACK_OK)) \
69             {OIC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
70
71 extern OCResource *headResource;
72
73 /**
74  * Prepares a Payload for response.
75  */
76 static OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
77                                                   OCDiscoveryPayload *payload,
78                                                   OCDevAddr *endpoint,
79                                                   CAEndpoint_t *networkInfo,
80                                                   uint32_t infoSize);
81
82 //-----------------------------------------------------------------------------
83 // Default resource entity handler function
84 //-----------------------------------------------------------------------------
85 OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag,
86         OCEntityHandlerRequest * request, void* callbackParam)
87 {
88     //TODO ("Implement me!!!!");
89     // TODO:  remove silence unused param warnings
90     (void) flag;
91     (void) request;
92     (void) callbackParam;
93     return  OC_EH_OK; // Making sure that the Default EH and the Vendor EH have matching signatures
94 }
95
96 /* This method will retrieve the port at which the secure resource is hosted */
97 static OCStackResult GetSecurePortInfo(OCDevAddr *endpoint, uint16_t *port)
98 {
99     uint16_t p = 0;
100
101     if (endpoint->adapter == OC_ADAPTER_IP)
102     {
103         if (endpoint->flags & OC_IP_USE_V6)
104         {
105             p = caglobals.ip.u6s.port;
106         }
107         else if (endpoint->flags & OC_IP_USE_V4)
108         {
109             p = caglobals.ip.u4s.port;
110         }
111     }
112
113     *port = p;
114     return OC_STACK_OK;
115 }
116
117 #ifdef TCP_ADAPTER
118 /* This method will retrieve the tcp port */
119 static OCStackResult GetTCPPortInfo(OCDevAddr *endpoint, uint16_t *port, bool secured)
120 {
121     uint16_t p = 0;
122
123     if (endpoint->adapter == OC_ADAPTER_IP)
124     {
125         if (endpoint->flags & OC_IP_USE_V4)
126         {
127             p = secured ? caglobals.tcp.ipv4s.port : caglobals.tcp.ipv4.port;
128         }
129         else if (endpoint->flags & OC_IP_USE_V6)
130         {
131             p = secured ? caglobals.tcp.ipv6s.port : caglobals.tcp.ipv6.port;
132         }
133     }
134
135     *port = p;
136     return OC_STACK_OK;
137 }
138 #endif
139
140 /*
141  * Function will extract 0, 1 or 2 filters from query.
142  * More than 2 filters or unsupported filters will result in error.
143  * If both filters are of the same supported type, the 2nd one will be picked.
144  * Resource and device filters in the SAME query are NOT validated
145  * and resources will likely not clear filters.
146  */
147 OCStackResult ExtractFiltersFromQuery(const char *query, char **filterOne, char **filterTwo)
148 {
149     if (!query)
150     {
151         OIC_LOG_V(ERROR, TAG, "Query is empty!");
152         return OC_STACK_INVALID_QUERY;
153     }
154     char *key = NULL;
155     char *value = NULL;
156     char *queryDup = NULL;
157     char *restOfQuery = NULL;
158     char *keyValuePair = NULL;
159     int numKeyValuePairsParsed = 0;
160
161     *filterOne = NULL;
162     *filterTwo = NULL;
163
164     queryDup = OICStrdup(query);
165     if (NULL == queryDup)
166     {
167         OIC_LOG_V(ERROR, TAG, "Creating duplicate string failed!");
168         return OC_STACK_NO_MEMORY;
169     }
170
171     OIC_LOG_V(INFO, TAG, "Extracting params from %s", queryDup);
172
173     OCStackResult eCode = OC_STACK_INVALID_QUERY;
174     if (strnlen(queryDup, MAX_QUERY_LENGTH) >= MAX_QUERY_LENGTH)
175     {
176         OIC_LOG(ERROR, TAG, "Query exceeds maximum length.");
177         goto exit;
178     }
179
180     keyValuePair = strtok_r (queryDup, OC_QUERY_SEPARATOR, &restOfQuery);
181
182     while(keyValuePair)
183     {
184         if (numKeyValuePairsParsed >= 2)
185         {
186             OIC_LOG(ERROR, TAG, "More than 2 queries params in URI.");
187             goto exit;
188         }
189
190         key = strtok_r(keyValuePair, OC_KEY_VALUE_DELIMITER, &value);
191
192         if (!key || !value)
193         {
194             goto exit;
195         }
196         else if (strncasecmp(key, OC_RSRVD_INTERFACE, sizeof(OC_RSRVD_INTERFACE) - 1) == 0)
197         {
198             *filterOne = value;     // if
199         }
200         else if (strncasecmp(key, OC_RSRVD_RESOURCE_TYPE, sizeof(OC_RSRVD_INTERFACE) - 1) == 0)
201         {
202             *filterTwo = value;     // rt
203         }
204         else
205         {
206             OIC_LOG_V(ERROR, TAG, "Unsupported query key: %s", key);
207             goto exit;
208         }
209         ++numKeyValuePairsParsed;
210
211         keyValuePair = strtok_r(NULL, OC_QUERY_SEPARATOR, &restOfQuery);
212     }
213
214     if (*filterOne)
215     {
216         *filterOne = OICStrdup(*filterOne);
217         if (NULL == *filterOne)
218         {
219             OIC_LOG_V(ERROR, TAG, "Creating duplicate string failed!");
220             eCode = OC_STACK_NO_MEMORY;
221             goto exit;
222         }
223     }
224
225     if (*filterTwo)
226     {
227         *filterTwo = OICStrdup(*filterTwo);
228         if (NULL == *filterTwo)
229         {
230             OIC_LOG_V(ERROR, TAG, "Creating duplicate string failed!");
231             OICFree(*filterOne);
232             eCode = OC_STACK_NO_MEMORY;
233             goto exit;
234         }
235     }
236
237     OICFree(queryDup);
238     OIC_LOG_V(INFO, TAG, "Extracted params if: %s and rt: %s.", *filterOne, *filterTwo);
239     return OC_STACK_OK;
240
241 exit:
242     *filterOne = NULL;
243     *filterTwo = NULL;
244     OICFree(queryDup);
245     return eCode;
246 }
247
248 OCVirtualResources GetTypeOfVirtualURI(const char *uriInRequest)
249 {
250     if (strcmp(uriInRequest, OC_RSRVD_WELL_KNOWN_URI) == 0)
251     {
252         return OC_WELL_KNOWN_URI;
253     }
254     else if (strcmp(uriInRequest, OC_RSRVD_DEVICE_URI) == 0)
255     {
256         return OC_DEVICE_URI;
257     }
258     else if (strcmp(uriInRequest, OC_RSRVD_PLATFORM_URI) == 0)
259     {
260         return OC_PLATFORM_URI;
261     }
262     else if (strcmp(uriInRequest, OC_RSRVD_RESOURCE_TYPES_URI) == 0)
263     {
264         return OC_RESOURCE_TYPES_URI;
265     }
266     else if (strcmp(uriInRequest, OC_RSRVD_INTROSPECTION_URI) == 0)
267     {
268         return OC_INTROSPECTION_URI;
269     }
270     else if (strcmp(uriInRequest, OC_RSRVD_INTROSPECTION_PAYLOAD_URI) == 0)
271     {
272         return OC_INTROSPECTION_PAYLOAD_URI;
273     }
274 #ifdef ROUTING_GATEWAY
275     else if (0 == strcmp(uriInRequest, OC_RSRVD_GATEWAY_URI))
276     {
277         return OC_GATEWAY_URI;
278     }
279 #endif
280 #ifdef WITH_PRESENCE
281     else if (strcmp(uriInRequest, OC_RSRVD_PRESENCE_URI) == 0)
282     {
283         return OC_PRESENCE;
284     }
285 #endif //WITH_PRESENCE
286
287 #ifdef MQ_BROKER
288     else if (0 == strcmp(uriInRequest, OC_RSRVD_WELL_KNOWN_MQ_URI))
289     {
290         return OC_MQ_BROKER_URI;
291     }
292 #endif //MQ_BROKER
293
294 #ifdef TCP_ADAPTER
295     else if (strcmp(uriInRequest, OC_RSRVD_KEEPALIVE_URI) == 0)
296     {
297         return OC_KEEPALIVE_RESOURCE_URI;
298     }
299 #endif
300
301     return OC_UNKNOWN_URI;
302 }
303
304 static OCStackResult getQueryParamsForFiltering (OCVirtualResources uri, char *query,
305                                             char **filterOne, char **filterTwo)
306 {
307     if(!filterOne || !filterTwo)
308     {
309         return OC_STACK_INVALID_PARAM;
310     }
311
312     *filterOne = NULL;
313     *filterTwo = NULL;
314
315 #ifdef WITH_PRESENCE
316     if (uri == OC_PRESENCE)
317     {
318         //Nothing needs to be done, except for pass a OC_PRESENCE query through as OC_STACK_OK.
319         OIC_LOG(INFO, TAG, "OC_PRESENCE Request for virtual resource.");
320         return OC_STACK_OK;
321     }
322 #endif
323
324     OCStackResult result = OC_STACK_OK;
325
326     if (query && *query)
327     {
328         result = ExtractFiltersFromQuery(query, filterOne, filterTwo);
329     }
330
331     return result;
332 }
333
334 static OCStackResult BuildDevicePlatformPayload(const OCResource *resourcePtr, OCRepPayload** payload,
335     bool addDeviceId)
336 {
337     OCRepPayload *tempPayload = OCRepPayloadCreate();
338
339     if (!resourcePtr)
340     {
341         OCRepPayloadDestroy(tempPayload);
342         return OC_STACK_INVALID_PARAM;
343     }
344
345     if (!tempPayload)
346     {
347         return OC_STACK_NO_MEMORY;
348     }
349
350     if (addDeviceId)
351     {
352         const char *deviceId = OCGetServerInstanceIDString();
353         if (!deviceId)
354         {
355             OIC_LOG(ERROR, TAG, "Failed retrieving device id.");
356             return OC_STACK_ERROR;
357         }
358         OCRepPayloadSetPropString(tempPayload, OC_RSRVD_DEVICE_ID, deviceId);
359     }
360
361     for (OCResourceType *resType = resourcePtr->rsrcType; resType; resType = resType->next)
362     {
363         OCRepPayloadAddResourceType(tempPayload, resType->resourcetypename);
364     }
365
366     for (OCResourceInterface *resInterface = resourcePtr->rsrcInterface; resInterface;
367         resInterface = resInterface->next)
368     {
369         OCRepPayloadAddInterface(tempPayload, resInterface->name);
370     }
371
372     for (OCAttribute *resAttrib = resourcePtr->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
373     {
374         if (resAttrib->attrName && resAttrib->attrValue)
375         {
376             if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName))
377             {
378                 char *dmv = OCCreateString((OCStringLL *)resAttrib->attrValue);
379                 if (dmv)
380                 {
381                     OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, dmv);
382                     OICFree(dmv);
383                 }
384             }
385             else
386             {
387                 OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, (char *)resAttrib->attrValue);
388             }
389         }
390     }
391
392     if (!*payload)
393     {
394         *payload = tempPayload;
395     }
396     else
397     {
398         OCRepPayloadAppend(*payload, tempPayload);
399     }
400
401     return OC_STACK_OK;
402 }
403
404 OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr,
405                     OCRepPayload** payload, OCDevAddr *devAddr)
406 {
407     OCRepPayload *tempPayload = OCRepPayloadCreate();
408
409     if (!resourcePtr)
410     {
411         OCRepPayloadDestroy(tempPayload);
412         return OC_STACK_INVALID_PARAM;
413     }
414
415     if(!tempPayload)
416     {
417         return OC_STACK_NO_MEMORY;
418     }
419
420     OCRepPayloadSetPropString(tempPayload, OC_RSRVD_HREF, resourcePtr->uri);
421
422     uint8_t numElement = 0;
423     if (OC_STACK_OK == OCGetNumberOfResourceTypes((OCResource *)resourcePtr, &numElement))
424     {
425         size_t rtDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
426         char **rt = (char **)OICMalloc(sizeof(char *) * numElement);
427         for (uint8_t i = 0; i < numElement; ++i)
428         {
429             const char *value = OCGetResourceTypeName((OCResource *)resourcePtr, i);
430             OIC_LOG_V(DEBUG, TAG, "value: %s", value);
431             rt[i] = OICStrdup(value);
432         }
433         OCRepPayloadSetStringArrayAsOwner(tempPayload, OC_RSRVD_RESOURCE_TYPE, rt, rtDim);
434     }
435
436     numElement = 0;
437     if (OC_STACK_OK == OCGetNumberOfResourceInterfaces((OCResource *)resourcePtr, &numElement))
438     {
439         size_t ifDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0};
440         char **itf = (char **)OICMalloc(sizeof(char *) * numElement);
441         for (uint8_t i = 0; i < numElement; ++i)
442         {
443             const char *value = OCGetResourceInterfaceName((OCResource *)resourcePtr, i);
444             OIC_LOG_V(DEBUG, TAG, "value: %s", value);
445             itf[i] = OICStrdup(value);
446         }
447         OCRepPayloadSetStringArrayAsOwner(tempPayload, OC_RSRVD_INTERFACE, itf, ifDim);
448     }
449
450     for (OCAttribute *resAttrib = resourcePtr->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
451     {
452         if (resAttrib->attrName && resAttrib->attrValue)
453         {
454             OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, (char *)resAttrib->attrValue);
455         }
456     }
457
458     OCResourceProperty p = OCGetResourceProperties((OCResourceHandle *)resourcePtr);
459     OCRepPayload *policy = OCRepPayloadCreate();
460     if (!policy)
461     {
462         OCPayloadDestroy((OCPayload *)tempPayload);
463         return OC_STACK_NO_MEMORY;
464     }
465     OCRepPayloadSetPropInt(policy, OC_RSRVD_BITMAP, ((p & OC_DISCOVERABLE) | (p & OC_OBSERVABLE)));
466     if (p & OC_SECURE)
467     {
468         OCRepPayloadSetPropBool(policy, OC_RSRVD_SECURE, p & OC_SECURE);
469         uint16_t securePort = 0;
470         if (GetSecurePortInfo(devAddr, &securePort) != OC_STACK_OK)
471         {
472             securePort = 0;
473         }
474         OCRepPayloadSetPropInt(policy, OC_RSRVD_HOSTING_PORT, securePort);
475     }
476     OCRepPayloadSetPropObjectAsOwner(tempPayload, OC_RSRVD_POLICY, policy);
477
478     if (!*payload)
479     {
480         *payload = tempPayload;
481     }
482     else
483     {
484         OCRepPayloadAppend(*payload, tempPayload);
485     }
486
487     return OC_STACK_OK;
488 }
489
490 static size_t GetIntrospectionDataSize(const OCPersistentStorage *ps)
491 {
492     size_t size = 0;
493     char buffer[INTROSPECTION_FILE_SIZE_BLOCK];
494     FILE *fp;
495
496     if (!ps)
497     {
498         return 0;
499     }
500
501     fp = ps->open(OC_INTROSPECTION_FILE_NAME, "rb");
502     if (fp)
503     {
504         size_t bytesRead = 0;
505         do
506         {
507             bytesRead = ps->read(buffer, 1, INTROSPECTION_FILE_SIZE_BLOCK, fp);
508             size += bytesRead;
509         } while (bytesRead);
510         ps->close(fp);
511     }
512     return size;
513 }
514
515 OCStackResult GetIntrospectionDataFromPS(char **data, size_t *size)
516 {
517     OIC_LOG(DEBUG, TAG, "GetIntrospectionDataFromPS IN");
518
519     FILE *fp = NULL;
520     uint8_t *fsData = NULL;
521     size_t fileSize = 0;
522     OCStackResult ret = OC_STACK_ERROR;
523     OCPersistentStorage *ps = NULL;
524
525     if (!data || *data || !size)
526     {
527         return OC_STACK_INVALID_PARAM;
528     }
529
530     ps = OCGetPersistentStorageHandler();
531     if (!ps)
532     {
533         OIC_LOG(ERROR, TAG, "Persistent Storage handler is NULL");
534         goto exit;
535     }
536
537     fileSize = GetIntrospectionDataSize(ps);
538     OIC_LOG_V(DEBUG, TAG, "File Read Size: %zu", fileSize);
539     if (fileSize)
540     {
541         // allocate one more byte to accomodate null terminator for string we are reading.
542         fsData = (uint8_t *)OICCalloc(1, fileSize + 1);
543         if (!fsData)
544         {
545             OIC_LOG(ERROR, TAG, "Could not allocate memory for introspection data");
546             goto exit;
547         }
548
549         fp = ps->open(OC_INTROSPECTION_FILE_NAME, "rb");
550         if (!fp)
551         {
552             OIC_LOG(ERROR, TAG, "Could not open persistent storage file for introspection data");
553             goto exit;
554         }
555         if (ps->read(fsData, 1, fileSize, fp) == fileSize)
556         {
557             *size = fileSize;
558             fsData[fileSize] = '\0';
559             *data = (char *)fsData;
560             fsData = NULL;
561             ret = OC_STACK_OK;
562         }
563     }
564     OIC_LOG(DEBUG, TAG, "GetIntrospectionDataFromPS OUT");
565
566 exit:
567     if (fp)
568     {
569         ps->close(fp);
570     }
571     if (fsData)
572     {
573         OICFree(fsData);
574     }
575     return ret;
576 }
577
578 OCStackResult BuildIntrospectionPayloadResponse(const OCResource *resourcePtr,
579     OCRepPayload** payload, OCDevAddr *devAddr)
580 {
581     OCRepPayload *tempPayload = NULL;
582     OCStackResult ret;
583     char *introspectionData = NULL;
584     size_t size = 0;
585     ret = GetIntrospectionDataFromPS(&introspectionData, &size);
586     if (OC_STACK_OK == ret)
587     {
588         OCRepPayload *tempPayload = OCRepPayloadCreate();
589         if (tempPayload)
590         {
591             if (OCRepPayloadSetPropStringAsOwner(tempPayload, OC_RSRVD_INTROSPECTION_DATA_NAME, introspectionData))
592             {
593                 *payload = tempPayload;
594             }
595         }
596         else
597         {
598             ret = OC_STACK_NO_MEMORY;
599         }
600     }
601     if (ret != OC_STACK_OK)
602     {
603         OICFree(introspectionData);
604         OCRepPayloadDestroy(tempPayload);
605     }
606
607     return ret;
608 }
609
610 OCRepPayload *BuildUrlInfoWithProtocol(const char *protocol)
611 {
612     OCStackResult result = OC_STACK_OK;
613     OCRepPayload *urlInfoPayload = OCRepPayloadCreate();
614     if (!urlInfoPayload)
615     {
616         OIC_LOG_V(ERROR, TAG, "Failed to create a new RepPayload");
617         result = OC_STACK_NO_MEMORY;
618         goto exit;
619     }
620
621     if (!OCRepPayloadSetPropString(urlInfoPayload, OC_RSRVD_INTROSPECTION_URL, OC_RSRVD_INTROSPECTION_PAYLOAD_URI))
622     {
623         OIC_LOG_V(ERROR, TAG, "Failed to add url");
624         result = OC_STACK_ERROR;
625         goto exit;
626     }
627     if (!OCRepPayloadSetPropString(urlInfoPayload, OC_RSRVD_INTROSPECTION_PROTOCOL, protocol))
628     {
629         OIC_LOG_V(ERROR, TAG, "Failed to add protocol");
630         result = OC_STACK_ERROR;
631         goto exit;
632     }
633     if (!OCRepPayloadSetPropString(urlInfoPayload, OC_RSRVD_INTROSPECTION_CONTENT_TYPE, OC_RSRVD_INTROSPECTION_CONTENT_TYPE_VALUE))
634     {
635         OIC_LOG_V(ERROR, TAG, "Failed to add content type");
636         result = OC_STACK_ERROR;
637         goto exit;
638     }
639     if (!OCRepPayloadSetPropInt(urlInfoPayload, OC_RSRVD_INTROSPECTION_VERSION, OC_RSRVD_INTROSPECTION_VERSION_VALUE))
640     {
641         OIC_LOG_V(ERROR, TAG, "Failed to add version");
642         result = OC_STACK_ERROR;
643         goto exit;
644     }
645
646 exit:
647     if (result != OC_STACK_OK)
648     {
649         OCRepPayloadDestroy(urlInfoPayload);
650         urlInfoPayload = NULL;
651     }
652     return urlInfoPayload;
653 }
654
655 OCStackResult AddProtocolToLL(OCStringLL **protoLL, const char *protocol)
656 {
657     OCStringLL* cur = *protoLL;
658     // Check if protocol is already in list
659     while (cur)
660     {
661         if (strcmp(cur->value, protocol) == 0)
662         {
663             break;
664         }
665         cur = cur->next;
666     }
667     if (cur)
668     {
669         // The intent of the protocol list is to collect all unique protocols available on this
670         // endpoint. Set an error that can be used to skip processing this protocol further as
671         // it already exists in the list.
672         return OC_STACK_INVALID_PARAM;
673     }
674     else
675     {
676         cur = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
677         if (!cur)
678         {
679             return OC_STACK_NO_MEMORY;
680         }
681     }
682
683     cur->value = OICStrdup(protocol);
684     if (!cur->value)
685     {
686         OICFree(cur);
687         return OC_STACK_NO_MEMORY;
688     }
689
690     cur->next = *protoLL;
691     *protoLL = cur;
692     return OC_STACK_OK;
693 }
694
695 void FreeProtocolLL(OCStringLL *protoLL)
696 {
697     OCStringLL* cur = protoLL;
698     while (cur)
699     {
700         OCStringLL *temp = cur;
701         cur = cur->next;
702         OICFree(temp->value);
703         OICFree(temp);
704     }
705 }
706
707 OCStackResult BuildIntrospectionResponseRepresentation(const OCResource *resourcePtr,
708     OCRepPayload** payload, OCDevAddr *devAddr)
709 {
710     size_t dimensions[3] = { 0, 0, 0 };
711     OCRepPayload *tempPayload = NULL;
712     OCRepPayload **urlInfoPayload = NULL;
713     OCStringLL *protoLL = NULL;
714     OCStackResult ret = OC_STACK_OK;
715     OCResourceType *resType = NULL;
716     OCResourceInterface *resInterface = NULL;
717
718     if (!resourcePtr)
719     {
720         ret = OC_STACK_INVALID_PARAM;
721         goto exit;
722     }
723
724     tempPayload = OCRepPayloadCreate();
725     if (!tempPayload)
726     {
727         ret = OC_STACK_NO_MEMORY;
728         goto exit;
729     }
730
731     if (!OCRepPayloadSetUri(tempPayload, resourcePtr->uri))
732     {
733         OIC_LOG_V(ERROR, TAG, "Failed to set payload URI");
734         ret = OC_STACK_ERROR;
735         goto exit;
736     }
737
738     resType = resourcePtr->rsrcType;
739     while (resType)
740     {
741         if (!OCRepPayloadAddResourceType(tempPayload, resType->resourcetypename))
742         {
743             OIC_LOG_V(ERROR, TAG, "Failed at add resource type");
744             ret = OC_STACK_ERROR;
745             goto exit;
746         }
747         resType = resType->next;
748     }
749
750     resInterface = resourcePtr->rsrcInterface;
751     while (resInterface)
752     {
753         if (!OCRepPayloadAddInterface(tempPayload, resInterface->name))
754         {
755             OIC_LOG_V(ERROR, TAG, "Failed to add interface");
756             ret = OC_STACK_ERROR;
757             goto exit;
758         }
759         resInterface = resInterface->next;
760     }
761     if (!OCRepPayloadSetPropString(tempPayload, OC_RSRVD_INTROSPECTION_NAME, OC_RSRVD_INTROSPECTION_NAME_VALUE))
762     {
763         OIC_LOG_V(ERROR, TAG, "Failed to set Name property.");
764         ret = OC_STACK_ERROR;
765         goto exit;
766     }
767
768     // Figure out which protocols this endpoint supports
769     if (resourcePtr->endpointType & OC_COAP)
770     {
771         if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAP_STR))
772         {
773             dimensions[0]++;
774         }
775     }
776     if (resourcePtr->endpointType & OC_COAPS)
777     {
778         if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAPS_STR))
779         {
780             dimensions[0]++;
781         }
782     }
783 #ifdef TCP_ADAPTER
784     if (resourcePtr->endpointType & OC_COAP_TCP)
785     {
786         if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAP_STR))
787         {
788             dimensions[0]++;
789         }
790     }
791     if (resourcePtr->endpointType & OC_COAPS_TCP)
792     {
793         if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAPS_STR))
794         {
795             dimensions[0]++;
796         }
797     }
798 #endif
799 #ifdef HTTP_ADAPTER
800     if (resourcePtr->endpointType & OC_HTTP)
801     {
802         if (OC_STACK_OK == AddProtocolToLL(&protoLL, HTTP_STR))
803         {
804             dimensions[0]++;
805         }
806     }
807     if (resourcePtr->endpointType & OC_HTTPS)
808     {
809         if (OC_STACK_OK == AddProtocolToLL(&protoLL, HTTPS_STR))
810         {
811             dimensions[0]++;
812         }
813     }
814 #endif
815 #ifdef EDR_ADAPTER
816     if (resourcePtr->endpointType & OC_COAP_RFCOMM)
817     {
818         if (OC_STACK_OK == AddProtocolToLL(&protoLL, COAP_STR))
819         {
820             dimensions[0]++;
821         }
822     }
823 #endif
824     // Add a urlInfo object for each protocol supported
825     if (dimensions[0] >= 0)
826     {
827         urlInfoPayload = (OCRepPayload **)OICMalloc(dimensions[0] * sizeof(OCRepPayload));
828         if (urlInfoPayload)
829         {
830             OCStringLL *proto = protoLL;
831             size_t i = 0;
832             while (proto)
833             {
834                 urlInfoPayload[i] = BuildUrlInfoWithProtocol(proto->value);
835                 if (!urlInfoPayload[i])
836                 {
837                     OIC_LOG_V(ERROR, TAG, "Unable to build urlInfo object for protocol");
838                     ret = OC_STACK_ERROR;
839                     goto exit;
840                 }
841                 proto = proto->next;
842                 i++;
843             }
844             if (!OCRepPayloadSetPropObjectArrayAsOwner(tempPayload,
845                                                        OC_RSRVD_INTROSPECTION_URL_INFO,
846                                                        urlInfoPayload,
847                                                        dimensions))
848             {
849                 OIC_LOG_V(ERROR, TAG, "Unable to add urlInfo object to introspection payload ");
850                 ret = OC_STACK_ERROR;
851                 goto exit;
852             }
853         }
854         else
855         {
856             OIC_LOG_V(ERROR, TAG, "Unable to allocate memory for urlInfo ");
857             ret = OC_STACK_NO_MEMORY;
858             goto exit;
859         }
860     }
861
862     if (!*payload)
863     {
864         *payload = tempPayload;
865     }
866     else
867     {
868         OCRepPayloadAppend(*payload, tempPayload);
869     }
870 exit:
871     if (ret != OC_STACK_OK)
872     {
873         OCRepPayloadDestroy(tempPayload);
874         if (urlInfoPayload)
875         {
876             OICFree(urlInfoPayload);
877         }
878     }
879     FreeProtocolLL(protoLL);
880
881     return OC_STACK_OK;
882 }
883
884 OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
885                                            OCDiscoveryPayload *payload,
886                                            OCDevAddr *devAddr,
887                                            CAEndpoint_t *networkInfo,
888                                            uint32_t infoSize)
889 {
890     if (!resourcePtr || !payload)
891     {
892         return OC_STACK_INVALID_PARAM;
893     }
894     uint16_t securePort = 0;
895     if (resourcePtr->resourceProperties & OC_SECURE)
896     {
897        if (GetSecurePortInfo(devAddr, &securePort) != OC_STACK_OK)
898        {
899            securePort = 0;
900        }
901     }
902
903     bool isVirtual = false;
904     if (GetTypeOfVirtualURI(resourcePtr->uri) != OC_UNKNOWN_URI)
905     {
906         isVirtual = true;
907     }
908 #ifdef TCP_ADAPTER
909     uint16_t tcpPort = 0;
910     GetTCPPortInfo(devAddr, &tcpPort, (resourcePtr->resourceProperties & OC_SECURE));
911
912     OCDiscoveryPayloadAddResourceWithEps(payload, resourcePtr, securePort,
913                                          isVirtual, networkInfo, infoSize, devAddr, tcpPort);
914 #else
915     OCDiscoveryPayloadAddResourceWithEps(payload, resourcePtr, securePort,
916                                          isVirtual, networkInfo, infoSize, devAddr);
917 #endif
918
919     return OC_STACK_OK;
920 }
921
922 OCResource *FindResourceByUri(const char* resourceUri)
923 {
924     if(!resourceUri)
925     {
926         return NULL;
927     }
928
929     OCResource * pointer = headResource;
930     while (pointer)
931     {
932         if (strcmp(resourceUri, pointer->uri) == 0)
933         {
934             return pointer;
935         }
936         pointer = pointer->next;
937     }
938     OIC_LOG_V(INFO, TAG, "Resource %s not found", resourceUri);
939     return NULL;
940 }
941
942 OCStackResult CheckRequestsEndpoint(const OCDevAddr *reqDevAddr,
943                                     OCTpsSchemeFlags resTpsFlags)
944 {
945     if (!reqDevAddr)
946     {
947         OIC_LOG(ERROR, TAG, "OCDevAddr* is NULL!!!");
948         return OC_STACK_INVALID_PARAM;
949     }
950
951     OCTpsSchemeFlags reqTpsFlags = OC_NO_TPS;
952     OCStackResult result = OCGetMatchedTpsFlags((CATransportAdapter_t)reqDevAddr->adapter,
953                                   (CATransportFlags_t)reqDevAddr->flags, &reqTpsFlags);
954
955     if (result != OC_STACK_OK)
956     {
957         OIC_LOG_V(ERROR, TAG, "Failed at get TPS flags. errcode is %d", result);
958         return result;
959     }
960
961     // bit compare between request tps flags and resource tps flags
962     if (reqTpsFlags & resTpsFlags)
963     {
964         OIC_LOG(INFO, TAG, "Request come from registered TPS");
965         return OC_STACK_OK;
966     }
967     else
968     {
969         OIC_LOG(ERROR, TAG, "Request come from unregistered TPS!!!");
970         return OC_STACK_BAD_ENDPOINT;
971     }
972 }
973
974 OCStackResult DetermineResourceHandling (const OCServerRequest *request,
975                                          ResourceHandling *handling,
976                                          OCResource **resource)
977 {
978     if(!request || !handling || !resource)
979     {
980         return OC_STACK_INVALID_PARAM;
981     }
982
983     OIC_LOG_V(INFO, TAG, "DetermineResourceHandling for %s", request->resourceUrl);
984
985     // Check if virtual resource
986     if (GetTypeOfVirtualURI(request->resourceUrl) != OC_UNKNOWN_URI)
987     {
988         OIC_LOG_V (INFO, TAG, "%s is virtual", request->resourceUrl);
989         *handling = OC_RESOURCE_VIRTUAL;
990         *resource = headResource;
991         return OC_STACK_OK;
992     }
993     if (strlen((const char*)(request->resourceUrl)) == 0)
994     {
995         // Resource URL not specified
996         *handling = OC_RESOURCE_NOT_SPECIFIED;
997         return OC_STACK_NO_RESOURCE;
998     }
999     else
1000     {
1001         OCResource *resourcePtr = FindResourceByUri((const char*)request->resourceUrl);
1002         *resource = resourcePtr;
1003
1004         // Checking resource TPS flags if resource exist in stack.
1005         if (resourcePtr)
1006         {
1007             OCStackResult result = CheckRequestsEndpoint(&(request->devAddr), resourcePtr->endpointType);
1008
1009             if (result != OC_STACK_OK)
1010             {
1011                 if (result == OC_STACK_BAD_ENDPOINT)
1012                 {
1013                     OIC_LOG(ERROR, TAG, "Request come from bad endpoint. ignore request!!!");
1014                     return OC_STACK_BAD_ENDPOINT;
1015                 }
1016                 else
1017                 {
1018                     OIC_LOG_V(ERROR, TAG, "Failed at get tps flag errcode: %d", result);
1019                     return result;
1020                 }
1021             }
1022         }
1023
1024         if (!resourcePtr)
1025         {
1026             if(defaultDeviceHandler)
1027             {
1028                 *handling = OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER;
1029                 return OC_STACK_OK;
1030             }
1031
1032             // Resource does not exist
1033             // and default device handler does not exist
1034             *handling = OC_RESOURCE_NOT_SPECIFIED;
1035             return OC_STACK_NO_RESOURCE;
1036         }
1037
1038         if (resourcePtr && resourcePtr->rsrcChildResourcesHead != NULL)
1039         {
1040             // Collection resource
1041             if (resourcePtr->entityHandler != defaultResourceEHandler)
1042             {
1043                 *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER;
1044                 return OC_STACK_OK;
1045             }
1046             else
1047             {
1048                 *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER;
1049                 return OC_STACK_OK;
1050             }
1051         }
1052         else
1053         {
1054             // Resource not a collection
1055             if (resourcePtr->entityHandler != defaultResourceEHandler)
1056             {
1057                 *handling = OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER;
1058                 return OC_STACK_OK;
1059             }
1060             else
1061             {
1062                 *handling = OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER;
1063                 return OC_STACK_OK;
1064             }
1065         }
1066     }
1067 }
1068
1069 OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
1070 {
1071     OCStackResult result;
1072
1073     switch (ehResult)
1074     {
1075         case OC_EH_OK:
1076         case OC_EH_CONTENT:
1077         case OC_EH_VALID:
1078             result = OC_STACK_OK;
1079             break;
1080         case OC_EH_SLOW:
1081             result = OC_STACK_SLOW_RESOURCE;
1082             break;
1083         case OC_EH_ERROR:
1084             result = OC_STACK_ERROR;
1085             break;
1086         case OC_EH_FORBIDDEN:
1087             result = OC_STACK_FORBIDDEN_REQ;
1088             break;
1089         case OC_EH_INTERNAL_SERVER_ERROR:
1090             result = OC_STACK_INTERNAL_SERVER_ERROR;
1091             break;
1092         case OC_EH_RESOURCE_CREATED:
1093             result = OC_STACK_RESOURCE_CREATED;
1094             break;
1095         case OC_EH_RESOURCE_DELETED:
1096             result = OC_STACK_RESOURCE_DELETED;
1097             break;
1098         case OC_EH_CHANGED:
1099             result = OC_STACK_RESOURCE_CHANGED;
1100             break;
1101         case OC_EH_RESOURCE_NOT_FOUND:
1102             result = OC_STACK_NO_RESOURCE;
1103             break;
1104         default:
1105             result = OC_STACK_ERROR;
1106     }
1107
1108     return result;
1109 }
1110
1111 static bool resourceMatchesRTFilter(OCResource *resource, char *resourceTypeFilter)
1112 {
1113     if (!resource)
1114     {
1115         return false;
1116     }
1117
1118     // Null is analogous to no filter.i.e. query is of form /oic/res?if=oic.if.baseline or /oic/res,
1119     // without rt query.
1120     if (NULL == resourceTypeFilter)
1121     {
1122         return true;
1123     }
1124
1125     // Empty resourceType filter is analogous to error query
1126     // It is an error as query is of form /oic/res?rt=
1127     if (0 == strlen(resourceTypeFilter))
1128     {
1129         return false;
1130     }
1131
1132     for (OCResourceType *rtPtr = resource->rsrcType; rtPtr; rtPtr = rtPtr->next)
1133     {
1134         if (0 == strcmp(rtPtr->resourcetypename, resourceTypeFilter))
1135         {
1136             return true;
1137         }
1138     }
1139
1140     OIC_LOG_V(INFO, TAG, "%s does not contain rt=%s.", resource->uri, resourceTypeFilter);
1141     return false;
1142 }
1143
1144 static bool resourceMatchesIFFilter(OCResource *resource, char *interfaceFilter)
1145 {
1146     if (!resource)
1147     {
1148         return false;
1149     }
1150
1151     // Null is analogous to no filter i.e. query is of form /oic/res?rt=core.light or /oic/res,
1152     // without if query.
1153     if (NULL == interfaceFilter)
1154     {
1155         return true;
1156     }
1157
1158     // Empty interface filter is analogous to error query
1159     // It is an error as query is of form /oic/res?if=
1160     if (0 == strlen(interfaceFilter))
1161     {
1162         return false;
1163     }
1164
1165     for (OCResourceInterface *ifPtr = resource->rsrcInterface; ifPtr; ifPtr = ifPtr->next)
1166     {
1167         if (0 == strcmp(ifPtr->name, interfaceFilter) ||
1168             0 == strcmp(OC_RSRVD_INTERFACE_LL, interfaceFilter) ||
1169             0 == strcmp(OC_RSRVD_INTERFACE_DEFAULT, interfaceFilter))
1170         {
1171             return true;
1172         }
1173     }
1174
1175     OIC_LOG_V(INFO, TAG, "%s does not contain if=%s.", resource->uri, interfaceFilter);
1176     return false;
1177 }
1178
1179 /*
1180  * If the filters are null, they will be assumed to NOT be present
1181  * and the resource will not be matched against them.
1182  * Function will return true if all non null AND non empty filters passed in find a match.
1183  */
1184 static bool includeThisResourceInResponse(OCResource *resource,
1185                                           char *interfaceFilter,
1186                                           char *resourceTypeFilter)
1187 {
1188     if (!resource)
1189     {
1190         OIC_LOG(ERROR, TAG, "Invalid resource");
1191         return false;
1192     }
1193
1194     if (resource->resourceProperties & OC_EXPLICIT_DISCOVERABLE)
1195     {
1196         /*
1197          * At least one valid filter should be available to
1198          * include the resource in discovery response
1199          */
1200         if (!(resourceTypeFilter && *resourceTypeFilter))
1201         {
1202             OIC_LOG_V(INFO, TAG, "%s no query string for EXPLICIT_DISCOVERABLE\
1203                 resource", resource->uri);
1204             return false;
1205         }
1206     }
1207     else if (!(resource->resourceProperties & OC_ACTIVE) ||
1208          !(resource->resourceProperties & OC_DISCOVERABLE))
1209     {
1210         OIC_LOG_V(INFO, TAG, "%s not ACTIVE or DISCOVERABLE", resource->uri);
1211         return false;
1212     }
1213
1214     return resourceMatchesIFFilter(resource, interfaceFilter) &&
1215            resourceMatchesRTFilter(resource, resourceTypeFilter);
1216 }
1217
1218 OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCResource *resource,
1219                                 OCPayload *discoveryPayload, OCEntityHandlerResult ehResult)
1220 {
1221     OCEntityHandlerResponse *response = NULL;
1222     OCStackResult result = OC_STACK_ERROR;
1223
1224     response = (OCEntityHandlerResponse *)OICCalloc(1, sizeof(*response));
1225     VERIFY_PARAM_NON_NULL(TAG, response, "Failed allocating OCEntityHandlerResponse");
1226
1227     response->ehResult = ehResult;
1228     response->payload = discoveryPayload;
1229     response->persistentBufferFlag = 0;
1230     response->requestHandle = (OCRequestHandle) request;
1231     response->resourceHandle = (OCResourceHandle) resource;
1232
1233     result = OCDoResponse(response);
1234
1235     OICFree(response);
1236     return result;
1237
1238 exit:
1239     return OC_STACK_NO_MEMORY;
1240 }
1241
1242 static OCStackResult EHRequest(OCEntityHandlerRequest *ehRequest, OCPayloadType type,
1243     OCServerRequest *request, OCResource *resource)
1244 {
1245     return FormOCEntityHandlerRequest(ehRequest,
1246                                      (OCRequestHandle)request,
1247                                      request->method,
1248                                      &request->devAddr,
1249                                      (OCResourceHandle)resource,
1250                                      request->query,
1251                                      type,
1252                                      request->payload,
1253                                      request->payloadSize,
1254                                      request->numRcvdVendorSpecificHeaderOptions,
1255                                      request->rcvdVendorSpecificHeaderOptions,
1256                                      (OCObserveAction)(request->notificationFlag ? OC_OBSERVE_NO_OPTION :
1257                                                        request->observationOption),
1258                                      (OCObservationId)0,
1259                                      request->coapID);
1260 }
1261
1262 #ifdef RD_SERVER
1263 /**
1264  * Find resources at the resource directory server. These resources are not local resources but
1265  * remote resources.
1266  *
1267  * @param interfaceQuery The interface query parameter.
1268  * @param resourceTypeQuery The resourceType query parameter.
1269  * @param discPayload The payload that will be added with the resource information if found at RD.
1270  *
1271  * @return ::OC_STACK_OK if any resources are found else ::OC_STACK_NO_RESOURCE.
1272  * In case if RD server is not started, it returns ::OC_STACK_NO_RESOURCE.
1273  */
1274 static OCStackResult findResourcesAtRD(const char *interfaceQuery,
1275                                        const char *resourceTypeQuery, OCDiscoveryPayload **discPayload)
1276 {
1277     OCStackResult result = OC_STACK_NO_RESOURCE;
1278     if (OCGetResourceHandleAtUri(OC_RSRVD_RD_URI) != NULL)
1279     {
1280         result = OCRDDatabaseDiscoveryPayloadCreate(interfaceQuery, resourceTypeQuery,
1281             (*discPayload) ? &(*discPayload)->next : discPayload);
1282     }
1283     if ((*discPayload) && (*discPayload)->resources)
1284     {
1285         result = OC_STACK_OK;
1286     }
1287     return result;
1288 }
1289 #endif
1290
1291 /**
1292  * Creates a discovery payload and add device id information. This information is included in all
1293  * /oic/res response.
1294  *
1295  * @param payload  payload that will have memory alllocated and device id information added.
1296  *
1297  * @return ::OC_STACK_OK if successful in allocating memory and adding ID information.
1298  * ::OC_STACK_NO_MEMORY if failed allocating the memory.
1299  */
1300 static OCStackResult discoveryPayloadCreateAndAddDeviceId(OCPayload **payload)
1301 {
1302     if (*payload)
1303     {
1304         OIC_LOG(DEBUG, TAG, "Payload is already allocated");
1305         return OC_STACK_OK;
1306     }
1307
1308     *payload = (OCPayload *) OCDiscoveryPayloadCreate();
1309     VERIFY_PARAM_NON_NULL(TAG, *payload, "Failed adding device id to discovery payload.");
1310
1311     {
1312         OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)*payload;
1313         discPayload->sid = (char *)OICCalloc(1, UUID_STRING_SIZE);
1314         VERIFY_PARAM_NON_NULL(TAG, discPayload->sid, "Failed adding device id to discovery payload.");
1315
1316         const char* uid = OCGetServerInstanceIDString();
1317         if (uid)
1318         {
1319             memcpy(discPayload->sid, uid, UUID_STRING_SIZE);
1320         }
1321
1322     }
1323     return OC_STACK_OK;
1324 exit:
1325     OCPayloadDestroy(*payload);
1326     return OC_STACK_NO_MEMORY;
1327 }
1328
1329 /**
1330  * Add the common properties to the payload, they are only included in case of oic.if.baseline response.
1331  *
1332  * @param discPayload payload that will have the baseline information included.
1333  *
1334  * @return ::OC_STACK_OK if successful in adding all the information. ::OC_STACK_NO_MEMORY if failed
1335  * allocating the memory for the baseline information.
1336  */
1337 static OCStackResult addDiscoveryBaselineCommonProperties(OCDiscoveryPayload *discPayload)
1338 {
1339     if (!discPayload)
1340     {
1341         OIC_LOG(ERROR, TAG, "Payload is not allocated");
1342         return OC_STACK_INVALID_PARAM;
1343     }
1344
1345     OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, (void **)&discPayload->name);
1346
1347     discPayload->type = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1348     VERIFY_PARAM_NON_NULL(TAG, discPayload->type, "Failed adding rt to discovery payload.");
1349     discPayload->type->value = OICStrdup(OC_RSRVD_RESOURCE_TYPE_RES);
1350     VERIFY_PARAM_NON_NULL(TAG, discPayload->type, "Failed adding rt value to discovery payload.");
1351
1352     OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_LL);
1353     OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_DEFAULT);
1354     VERIFY_PARAM_NON_NULL(TAG, discPayload->iface, "Failed adding if to discovery payload.");
1355
1356     return OC_STACK_OK;
1357
1358 exit:
1359     return OC_STACK_NO_MEMORY;
1360 }
1361
1362 static bool isUnicast(OCServerRequest *request)
1363 {
1364     bool isMulticast = request->devAddr.flags & OC_MULTICAST;
1365     return (isMulticast == false &&
1366            (request->devAddr.adapter != OC_ADAPTER_RFCOMM_BTEDR) &&
1367            (request->devAddr.adapter != OC_ADAPTER_GATT_BTLE));
1368 }
1369
1370 static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource)
1371 {
1372     if (!request || !resource)
1373     {
1374         return OC_STACK_INVALID_PARAM;
1375     }
1376
1377     OCPayload* payload = NULL;
1378     char *interfaceQuery = NULL;
1379     char *resourceTypeQuery = NULL;
1380     char *dataModelVersions = NULL;
1381
1382     OIC_LOG(INFO, TAG, "Entering HandleVirtualResource");
1383
1384     OCVirtualResources virtualUriInRequest = GetTypeOfVirtualURI (request->resourceUrl);
1385
1386 #ifdef TCP_ADAPTER
1387     if (OC_KEEPALIVE_RESOURCE_URI == virtualUriInRequest)
1388     {
1389         // Received request for a keepalive
1390         OIC_LOG(INFO, TAG, "Request is for KeepAlive Request");
1391         return HandleKeepAliveRequest(request, resource);
1392     }
1393 #endif
1394
1395     OCStackResult discoveryResult = OC_STACK_ERROR;
1396     if (request->method == OC_REST_PUT || request->method == OC_REST_POST ||
1397         request->method == OC_REST_DELETE)
1398     {
1399         OIC_LOG_V(ERROR, TAG, "Resource : %s not permitted for method: %d",
1400             request->resourceUrl, request->method);
1401         return OC_STACK_UNAUTHORIZED_REQ;
1402     }
1403
1404     discoveryResult = HandleVirtualObserveRequest(request);
1405     if (discoveryResult == OC_STACK_DUPLICATE_REQUEST)
1406     {
1407         // server requests are usually free'd when the response is sent out
1408         // for the request in ocserverrequest.c : HandleSingleResponse()
1409         // Since we are making an early return and not responding, the server request
1410         // needs to be deleted.
1411         FindAndDeleteServerRequest (request);
1412         discoveryResult = OC_STACK_OK;
1413         goto exit;
1414     }
1415     else if (discoveryResult != OC_STACK_OK)
1416     {
1417         goto exit;
1418     }
1419
1420     // Step 1: Generate the response to discovery request
1421     if (virtualUriInRequest == OC_WELL_KNOWN_URI
1422 #ifdef MQ_BROKER
1423             || virtualUriInRequest == OC_MQ_BROKER_URI
1424 #endif
1425             )
1426     {
1427         char *interfaceQuery = NULL;
1428         char *resourceTypeQuery = NULL;
1429
1430         CAEndpoint_t *networkInfo = NULL;
1431         uint32_t infoSize = 0;
1432
1433         CAResult_t caResult = CAGetNetworkInformation(&networkInfo, &infoSize);
1434         if (CA_STATUS_FAILED == caResult)
1435         {
1436             OIC_LOG(ERROR, TAG, "CAGetNetworkInformation has error on parsing network infomation");
1437             return OC_STACK_ERROR;
1438         }
1439
1440         discoveryResult = getQueryParamsForFiltering (virtualUriInRequest, request->query,
1441                 &interfaceQuery, &resourceTypeQuery);
1442         VERIFY_SUCCESS(discoveryResult);
1443
1444         if (!interfaceQuery && !resourceTypeQuery)
1445         {
1446             // If no query is sent, default interface is used i.e. oic.if.ll.
1447             interfaceQuery = OICStrdup(OC_RSRVD_INTERFACE_LL);
1448         }
1449
1450         discoveryResult = discoveryPayloadCreateAndAddDeviceId(&payload);
1451         VERIFY_PARAM_NON_NULL(TAG, payload, "Failed creating Discovery Payload.");
1452         VERIFY_SUCCESS(discoveryResult);
1453
1454         OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)payload;
1455         if (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_DEFAULT))
1456         {
1457             discoveryResult = addDiscoveryBaselineCommonProperties(discPayload);
1458             VERIFY_SUCCESS(discoveryResult);
1459         }
1460         OCResourceProperty prop = OC_DISCOVERABLE;
1461 #ifdef MQ_BROKER
1462         prop = (OC_MQ_BROKER_URI == virtualUriInRequest) ? OC_MQ_BROKER : prop;
1463 #endif
1464         for (; resource && discoveryResult == OC_STACK_OK; resource = resource->next)
1465         {
1466             // This case will handle when no resource type and it is oic.if.ll.
1467             // Do not assume check if the query is ll
1468             if (!resourceTypeQuery &&
1469                 (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_LL)))
1470             {
1471                 // Only include discoverable type
1472                 if (resource->resourceProperties & prop)
1473                 {
1474                     discoveryResult = BuildVirtualResourceResponse(resource,
1475                                                                    discPayload,
1476                                                                    &request->devAddr,
1477                                                                    networkInfo,
1478                                                                    infoSize);
1479                 }
1480             }
1481             else if (includeThisResourceInResponse(resource, interfaceQuery, resourceTypeQuery))
1482             {
1483                 discoveryResult = BuildVirtualResourceResponse(resource,
1484                                                                discPayload,
1485                                                                &request->devAddr,
1486                                                                networkInfo,
1487                                                                infoSize);
1488             }
1489             else
1490             {
1491                 discoveryResult = OC_STACK_OK;
1492             }
1493         }
1494         if (discPayload->resources == NULL)
1495         {
1496             discoveryResult = OC_STACK_NO_RESOURCE;
1497             OCPayloadDestroy(payload);
1498             payload = NULL;
1499         }
1500
1501         if (networkInfo)
1502         {
1503             OICFree(networkInfo);
1504         }
1505 #ifdef RD_SERVER
1506         discoveryResult = findResourcesAtRD(interfaceQuery, resourceTypeQuery, (OCDiscoveryPayload **)&payload);
1507 #endif
1508     }
1509     else if (virtualUriInRequest == OC_DEVICE_URI)
1510     {
1511         OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_DEVICE_URI);
1512         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Device URI not found.");
1513         discoveryResult = BuildDevicePlatformPayload(resourcePtr, (OCRepPayload **)&payload, true);
1514     }
1515     else if (virtualUriInRequest == OC_PLATFORM_URI)
1516     {
1517         OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_PLATFORM_URI);
1518         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Platform URI not found.");
1519         discoveryResult = BuildDevicePlatformPayload(resourcePtr, (OCRepPayload **)&payload, false);
1520     }
1521 #ifdef ROUTING_GATEWAY
1522     else if (OC_GATEWAY_URI == virtualUriInRequest)
1523     {
1524         // Received request for a gateway
1525         OIC_LOG(INFO, TAG, "Request is for Gateway Virtual Request");
1526         discoveryResult = RMHandleGatewayRequest(request, resource);
1527     }
1528 #endif
1529     else if (OC_INTROSPECTION_URI == virtualUriInRequest)
1530     {
1531         // Received request for introspection
1532         OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_INTROSPECTION_URI);
1533         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Introspection URI not found.");
1534         discoveryResult = BuildIntrospectionResponseRepresentation(resourcePtr, (OCRepPayload **)&payload, &request->devAddr);
1535         OIC_LOG(INFO, TAG, "Request is for Introspection");
1536     }
1537     else if (OC_INTROSPECTION_PAYLOAD_URI == virtualUriInRequest)
1538     {
1539         // Received request for introspection payload
1540         OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_INTROSPECTION_PAYLOAD_URI);
1541         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Introspection Payload URI not found.");
1542         discoveryResult = BuildIntrospectionPayloadResponse(resourcePtr, (OCRepPayload **)&payload, &request->devAddr);
1543         OIC_LOG(INFO, TAG, "Request is for Introspection Payload");
1544     }
1545     /**
1546      * Step 2: Send the discovery response
1547      *
1548      * Iotivity should respond to discovery requests in below manner:
1549      * 1)If query filter matching fails and discovery request is multicast,
1550      *   it should NOT send any response.
1551      * 2)If query filter matching fails and discovery request is unicast,
1552      *   it should send an error(RESOURCE_NOT_FOUND - 404) response.
1553      * 3)If Server does not have any 'DISCOVERABLE' resources and discovery
1554      *   request is multicast, it should NOT send any response.
1555      * 4)If Server does not have any 'DISCOVERABLE' resources and discovery
1556      *   request is unicast, it should send an error(RESOURCE_NOT_FOUND - 404) response.
1557      */
1558
1559 #ifdef WITH_PRESENCE
1560     if ((virtualUriInRequest == OC_PRESENCE) &&
1561         (resource->resourceProperties & OC_ACTIVE))
1562     {
1563         // Need to send ACK when the request is CON.
1564         if (request->qos == OC_HIGH_QOS)
1565         {
1566             CAEndpoint_t endpoint = { .adapter = CA_DEFAULT_ADAPTER };
1567             CopyDevAddrToEndpoint(&request->devAddr, &endpoint);
1568             SendDirectStackResponse(&endpoint, request->coapID, CA_EMPTY, CA_MSG_ACKNOWLEDGE,
1569                                     0, NULL, NULL, 0, NULL, CA_RESPONSE_FOR_RES);
1570         }
1571         FindAndDeleteServerRequest(request);
1572
1573         // Presence uses observer notification api to respond via SendPresenceNotification.
1574         SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
1575     }
1576     else
1577 #endif
1578 #if ROUTING_GATEWAY
1579     // Gateway uses the RMHandleGatewayRequest to respond to the request.
1580     if (OC_GATEWAY_URI != virtualUriInRequest)
1581 #endif
1582     {
1583         OIC_LOG_PAYLOAD(DEBUG, payload);
1584         if(discoveryResult == OC_STACK_OK)
1585         {
1586
1587             SendNonPersistantDiscoveryResponse(request, resource, payload, OC_EH_OK);
1588         }
1589         else // Error handling
1590         {
1591             if (isUnicast(request))
1592             {
1593                 OIC_LOG_V(ERROR, TAG, "Sending a (%d) error to (%d) discovery request",
1594                     discoveryResult, virtualUriInRequest);
1595                 SendNonPersistantDiscoveryResponse(request, resource, NULL,
1596                     (discoveryResult == OC_STACK_NO_RESOURCE) ?
1597                         OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR);
1598             }
1599             else // Multicast
1600             {
1601                 // Ignoring the discovery request as per RFC 7252, Section #8.2
1602                 OIC_LOG(INFO, TAG, "Silently ignoring the request since no useful data to send.");
1603                 // the request should be removed.
1604                 // since it never remove and causes a big memory waste.
1605                 FindAndDeleteServerRequest(request);
1606             }
1607             discoveryResult = OC_STACK_CONTINUE;
1608         }
1609     }
1610
1611 exit:
1612     if (interfaceQuery)
1613     {
1614         OICFree(interfaceQuery);
1615     }
1616
1617     if (resourceTypeQuery)
1618     {
1619         OICFree(resourceTypeQuery);
1620     }
1621     OCPayloadDestroy(payload);
1622     if (dataModelVersions)
1623     {
1624         OICFree(dataModelVersions);
1625     }
1626     // To ignore the message, OC_STACK_CONTINUE is sent
1627     return discoveryResult;
1628 }
1629
1630 static OCStackResult
1631 HandleDefaultDeviceEntityHandler(OCServerRequest *request)
1632 {
1633     if (!request)
1634     {
1635         return OC_STACK_INVALID_PARAM;
1636     }
1637
1638     OCEntityHandlerResult ehResult = OC_EH_ERROR;
1639     OCEntityHandlerRequest ehRequest = {0};
1640     OIC_LOG(INFO, TAG, "Entering HandleResourceWithDefaultDeviceEntityHandler");
1641     OCStackResult result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, NULL);
1642     VERIFY_SUCCESS(result);
1643
1644     // At this point we know for sure that defaultDeviceHandler exists
1645     ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
1646                                   (char*) request->resourceUrl, defaultDeviceHandlerCallbackParameter);
1647     if(ehResult == OC_EH_SLOW)
1648     {
1649         OIC_LOG(INFO, TAG, "This is a slow resource");
1650         request->slowFlag = 1;
1651     }
1652     else if(ehResult == OC_EH_ERROR)
1653     {
1654         FindAndDeleteServerRequest(request);
1655     }
1656     result = EntityHandlerCodeToOCStackCode(ehResult);
1657 exit:
1658     OCPayloadDestroy(ehRequest.payload);
1659     return result;
1660 }
1661
1662 static OCStackResult
1663 HandleResourceWithEntityHandler(OCServerRequest *request,
1664                                 OCResource *resource)
1665 {
1666     if(!request || ! resource)
1667     {
1668         return OC_STACK_INVALID_PARAM;
1669     }
1670
1671     OCStackResult result = OC_STACK_ERROR;
1672     OCEntityHandlerResult ehResult = OC_EH_ERROR;
1673     OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
1674     ResourceObserver *resObs = NULL;
1675
1676     OCEntityHandlerRequest ehRequest = {0};
1677
1678     OIC_LOG(INFO, TAG, "Entering HandleResourceWithEntityHandler");
1679     OCPayloadType type = PAYLOAD_TYPE_REPRESENTATION;
1680     // check the security resource
1681     if (request && request->resourceUrl && SRMIsSecurityResourceURI(request->resourceUrl))
1682     {
1683         type = PAYLOAD_TYPE_SECURITY;
1684
1685     }
1686
1687     result = EHRequest(&ehRequest, type, request, resource);
1688     VERIFY_SUCCESS(result);
1689
1690     if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
1691     {
1692         OIC_LOG(INFO, TAG, "No observation requested");
1693         ehFlag = OC_REQUEST_FLAG;
1694     }
1695     else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER)
1696     {
1697         OIC_LOG(INFO, TAG, "Observation registration requested");
1698
1699         ResourceObserver *obs = GetObserverUsingToken (request->requestToken,
1700                                     request->tokenLength);
1701
1702         if (obs)
1703         {
1704             OIC_LOG (INFO, TAG, "Observer with this token already present");
1705             OIC_LOG (INFO, TAG, "Possibly re-transmitted CON OBS request");
1706             OIC_LOG (INFO, TAG, "Not adding observer. Not responding to client");
1707             OIC_LOG (INFO, TAG, "The first request for this token is already ACKED.");
1708
1709             // server requests are usually free'd when the response is sent out
1710             // for the request in ocserverrequest.c : HandleSingleResponse()
1711             // Since we are making an early return and not responding, the server request
1712             // needs to be deleted.
1713             FindAndDeleteServerRequest (request);
1714             return OC_STACK_OK;
1715         }
1716
1717         result = GenerateObserverId(&ehRequest.obsInfo.obsId);
1718         VERIFY_SUCCESS(result);
1719
1720         result = AddObserver ((const char*)(request->resourceUrl),
1721                 (const char *)(request->query),
1722                 ehRequest.obsInfo.obsId, request->requestToken, request->tokenLength,
1723                 resource, request->qos, request->acceptFormat,
1724                 request->acceptVersion, &request->devAddr);
1725
1726         if(result == OC_STACK_OK)
1727         {
1728             OIC_LOG(INFO, TAG, "Added observer successfully");
1729             request->observeResult = OC_STACK_OK;
1730             ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
1731         }
1732         else if (result == OC_STACK_RESOURCE_ERROR)
1733         {
1734             OIC_LOG(INFO, TAG, "The Resource is not active, discoverable or observable");
1735             request->observeResult = OC_STACK_ERROR;
1736             ehFlag = OC_REQUEST_FLAG;
1737         }
1738         else
1739         {
1740             // The error in observeResult for the request will be used when responding to this
1741             // request by omitting the observation option/sequence number.
1742             request->observeResult = OC_STACK_ERROR;
1743             OIC_LOG(ERROR, TAG, "Observer Addition failed");
1744             ehFlag = OC_REQUEST_FLAG;
1745             FindAndDeleteServerRequest(request);
1746             goto exit;
1747         }
1748
1749     }
1750     else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER)
1751     {
1752         OIC_LOG(INFO, TAG, "Deregistering observation requested");
1753
1754         resObs = GetObserverUsingToken (request->requestToken, request->tokenLength);
1755
1756         if (NULL == resObs)
1757         {
1758             // Stack does not contain this observation request
1759             // Either token is incorrect or observation list is corrupted
1760             result = OC_STACK_ERROR;
1761             goto exit;
1762         }
1763         ehRequest.obsInfo.obsId = resObs->observeId;
1764         ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
1765
1766         result = DeleteObserverUsingToken (request->requestToken, request->tokenLength);
1767
1768         if(result == OC_STACK_OK)
1769         {
1770             OIC_LOG(INFO, TAG, "Removed observer successfully");
1771             request->observeResult = OC_STACK_OK;
1772             // There should be no observe option header for de-registration response.
1773             // Set as an invalid value here so we can detect it later and remove the field in response.
1774             request->observationOption = MAX_SEQUENCE_NUMBER + 1;
1775         }
1776         else
1777         {
1778             request->observeResult = OC_STACK_ERROR;
1779             OIC_LOG(ERROR, TAG, "Observer Removal failed");
1780             FindAndDeleteServerRequest(request);
1781             goto exit;
1782         }
1783     }
1784     else
1785     {
1786         result = OC_STACK_ERROR;
1787         goto exit;
1788     }
1789
1790     ehResult = resource->entityHandler(ehFlag, &ehRequest, resource->entityHandlerCallbackParam);
1791     if(ehResult == OC_EH_SLOW)
1792     {
1793         OIC_LOG(INFO, TAG, "This is a slow resource");
1794         request->slowFlag = 1;
1795     }
1796     else if(ehResult == OC_EH_ERROR)
1797     {
1798         FindAndDeleteServerRequest(request);
1799     }
1800     result = EntityHandlerCodeToOCStackCode(ehResult);
1801 exit:
1802     OCPayloadDestroy(ehRequest.payload);
1803     return result;
1804 }
1805
1806 static OCStackResult HandleCollectionResourceDefaultEntityHandler(OCServerRequest *request,
1807                                                                   OCResource *resource)
1808 {
1809     if (!request || !resource)
1810     {
1811         return OC_STACK_INVALID_PARAM;
1812     }
1813
1814     OCEntityHandlerRequest ehRequest = {0};
1815     OCStackResult result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, resource);
1816     if(result == OC_STACK_OK)
1817     {
1818         result = DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest);
1819     }
1820
1821     OCPayloadDestroy(ehRequest.payload);
1822     return result;
1823 }
1824
1825 OCStackResult
1826 ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request)
1827 {
1828     OCStackResult ret = OC_STACK_OK;
1829
1830     switch (resHandling)
1831     {
1832         case OC_RESOURCE_VIRTUAL:
1833         {
1834             ret = HandleVirtualResource (request, resource);
1835             break;
1836         }
1837         case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER:
1838         {
1839             ret = HandleDefaultDeviceEntityHandler(request);
1840             break;
1841         }
1842         case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
1843         {
1844             OIC_LOG(INFO, TAG, "OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER");
1845             return OC_STACK_ERROR;
1846         }
1847         case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
1848         {
1849             ret = HandleResourceWithEntityHandler (request, resource);
1850             break;
1851         }
1852         case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
1853         {
1854             ret = HandleResourceWithEntityHandler (request, resource);
1855             break;
1856         }
1857         case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
1858         {
1859             ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
1860             break;
1861         }
1862         case OC_RESOURCE_NOT_SPECIFIED:
1863         {
1864             ret = OC_STACK_NO_RESOURCE;
1865             break;
1866         }
1867         default:
1868         {
1869             OIC_LOG(INFO, TAG, "Invalid Resource Determination");
1870             return OC_STACK_ERROR;
1871         }
1872     }
1873     return ret;
1874 }
1875
1876 OCStackResult OCSetPlatformInfo(OCPlatformInfo info)
1877 {
1878     OCResource *resource = NULL;
1879     if (!info.platformID || !info.manufacturerName)
1880     {
1881         OIC_LOG(ERROR, TAG, "No value specified.");
1882         goto exit;
1883     }
1884     if (0 == strlen(info.platformID) || 0 == strlen(info.manufacturerName))
1885     {
1886         OIC_LOG(ERROR, TAG, "The passed value cannot be empty");
1887         goto exit;
1888     }
1889     if ((info.manufacturerName && strlen(info.manufacturerName) > MAX_PLATFORM_NAME_LENGTH) ||
1890         (info.manufacturerUrl && strlen(info.manufacturerUrl) > MAX_PLATFORM_URL_LENGTH) ||
1891         (info.modelNumber && strlen(info.modelNumber) > MAX_PLATFORM_NAME_LENGTH) ||
1892         (info.platformVersion && strlen(info.platformVersion) > MAX_PLATFORM_NAME_LENGTH) ||
1893         (info.operatingSystemVersion && strlen(info.operatingSystemVersion) > MAX_PLATFORM_NAME_LENGTH) ||
1894         (info.hardwareVersion && strlen(info.hardwareVersion) > MAX_PLATFORM_NAME_LENGTH) ||
1895         (info.firmwareVersion && strlen(info.firmwareVersion) > MAX_PLATFORM_NAME_LENGTH) ||
1896         (info.supportUrl && strlen(info.supportUrl) > MAX_PLATFORM_URL_LENGTH))
1897     {
1898         OIC_LOG(ERROR, TAG, "The passed value is bigger than permitted.");
1899         goto exit;
1900     }
1901
1902     /*
1903      * @todo (IOT-1541) There are several versions of a UUID structure and conversion
1904      * methods scattered around the IoTivity code base.  They need to be combined
1905      * into one PAL API.
1906      */
1907     uint8_t uuid[UUID_SIZE];
1908     if (!OCConvertStringToUuid(info.platformID, uuid))
1909     {
1910         OIC_LOG(ERROR, TAG, "Platform ID is not a UUID.");
1911         goto exit;
1912     }
1913
1914     resource = FindResourceByUri(OC_RSRVD_PLATFORM_URI);
1915     if (!resource)
1916     {
1917         OIC_LOG(ERROR, TAG, "Platform Resource does not exist.");
1918         goto exit;
1919     }
1920     OIC_LOG(INFO, TAG, "Entering OCSetPlatformInfo");
1921     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_PLATFORM_ID, info.platformID));
1922     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_NAME, info.manufacturerName));
1923     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_URL, info.manufacturerUrl);
1924     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MODEL_NUM, info.modelNumber);
1925     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_DATE, info.dateOfManufacture);
1926     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_PLATFORM_VERSION, info.platformVersion);
1927     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_OS_VERSION, info.operatingSystemVersion);
1928     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_HARDWARE_VERSION, info.hardwareVersion);
1929     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_FIRMWARE_VERSION, info.firmwareVersion);
1930     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_SUPPORT_URL, info.supportUrl);
1931     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_SYSTEM_TIME, info.systemTime);
1932     OIC_LOG(INFO, TAG, "Platform parameter initialized successfully.");
1933     return OC_STACK_OK;
1934
1935 exit:
1936     return OC_STACK_INVALID_PARAM;
1937 }
1938
1939 OCStackResult OCSetDeviceInfo(OCDeviceInfo info)
1940 {
1941     OCResource *resource = FindResourceByUri(OC_RSRVD_DEVICE_URI);
1942     if (!resource)
1943     {
1944         OIC_LOG(ERROR, TAG, "Device Resource does not exist.");
1945         goto exit;
1946     }
1947     if (!info.deviceName || info.deviceName[0] == '\0')
1948     {
1949         OIC_LOG(ERROR, TAG, "Null or empty device name.");
1950        return OC_STACK_INVALID_PARAM;
1951     }
1952
1953     if (OCGetServerInstanceIDString() == NULL)
1954     {
1955         OIC_LOG(INFO, TAG, "Device ID generation failed");
1956         goto exit;
1957     }
1958
1959     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, info.deviceName));
1960     for (OCStringLL *temp = info.types; temp; temp = temp->next)
1961     {
1962         if (temp->value)
1963         {
1964             VERIFY_SUCCESS(OCBindResourceTypeToResource(resource, temp->value));
1965         }
1966     }
1967     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_SPEC_VERSION, info.specVersion ?
1968         info.specVersion: OC_SPEC_VERSION));
1969
1970     if (info.dataModelVersions)
1971     {
1972         char *dmv = OCCreateString(info.dataModelVersions);
1973         VERIFY_PARAM_NON_NULL(TAG, dmv, "Failed allocating dataModelVersions");
1974         OCStackResult r = OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION, dmv);
1975         OICFree(dmv);
1976         VERIFY_SUCCESS(r);
1977     }
1978     else
1979     {
1980         VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION,
1981             OC_DATA_MODEL_VERSION));
1982     }
1983     OIC_LOG(INFO, TAG, "Device parameter initialized successfully.");
1984     return OC_STACK_OK;
1985
1986 exit:
1987     return OC_STACK_ERROR;
1988 }
1989
1990 OCStackResult OCGetAttribute(const OCResource *resource, const char *attribute, void **value)
1991 {
1992     if (!resource || !attribute)
1993     {
1994         return OC_STACK_INVALID_PARAM;
1995     }
1996     if (0 == strlen(attribute))
1997     {
1998         return OC_STACK_INVALID_PARAM;
1999     }
2000     for (OCAttribute *temp = resource->rsrcAttributes; temp; temp = temp->next)
2001     {
2002         if (0 == strcmp(attribute, temp->attrName))
2003         {
2004             // A special case as this type return OCStringLL
2005             if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, attribute))
2006             {
2007                 *value = CloneOCStringLL((OCStringLL *)temp->attrValue);
2008                 return OC_STACK_OK;
2009             }
2010             else
2011             {
2012                 *value = OICStrdup((char *)temp->attrValue);
2013                 return OC_STACK_OK;
2014             }
2015         }
2016     }
2017     return OC_STACK_NO_RESOURCE;
2018 }
2019
2020 OCStackResult OCGetPropertyValue(OCPayloadType type, const char *prop, void **value)
2021 {
2022     if (!prop)
2023     {
2024         return OC_STACK_INVALID_PARAM;
2025     }
2026     if (strlen(prop) == 0)
2027     {
2028         return OC_STACK_INVALID_PARAM;
2029     }
2030     if (*value)
2031     {
2032         *value = NULL;
2033     }
2034     OCStackResult res =  OC_STACK_NO_RESOURCE;
2035     if (PAYLOAD_TYPE_DEVICE == type || PAYLOAD_TYPE_PLATFORM == type)
2036     {
2037         const char *pathType = (type == PAYLOAD_TYPE_DEVICE) ? OC_RSRVD_DEVICE_URI : OC_RSRVD_PLATFORM_URI;
2038         OCResource *resource = FindResourceByUri(pathType);
2039         if (!resource)
2040         {
2041             return OC_STACK_NO_RESOURCE;
2042         }
2043
2044         res = OCGetAttribute(resource, prop, value);
2045     }
2046     return res;
2047 }
2048
2049 OCStackResult OCSetAttribute(OCResource* resource, const char* attribute, const void* value)
2050 {
2051     // See if the attribute already exists in the list.
2052     OCAttribute *resAttrib = NULL;
2053     for (resAttrib = resource->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
2054     {
2055         if (0 == strcmp(attribute, resAttrib->attrName))
2056         {
2057             // Found, free the old value.
2058             if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName))
2059             {
2060                 OCFreeOCStringLL((OCStringLL *)resAttrib->attrValue);
2061             }
2062             else
2063             {
2064                 OICFree((char *)resAttrib->attrValue);
2065             }
2066             break;
2067         }
2068     }
2069
2070     // If not already in the list, add it.
2071     if (NULL == resAttrib)
2072     {
2073         resAttrib = (OCAttribute *)OICCalloc(1, sizeof(OCAttribute));
2074         VERIFY_PARAM_NON_NULL(TAG, resAttrib, "Failed allocating OCAttribute");
2075         resAttrib->attrName = OICStrdup(attribute);
2076         VERIFY_PARAM_NON_NULL(TAG, resAttrib->attrName, "Failed allocating attribute name");
2077         resAttrib->next = resource->rsrcAttributes;
2078         resource->rsrcAttributes = resAttrib;
2079     }
2080
2081     // Fill in the new value.
2082     if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, attribute))
2083     {
2084         resAttrib->attrValue = OCCreateOCStringLL((char *)value);
2085     }
2086     else
2087     {
2088         resAttrib->attrValue = OICStrdup((char *)value);
2089     }
2090     VERIFY_PARAM_NON_NULL(TAG, resAttrib->attrValue, "Failed allocating attribute value");
2091
2092     return OC_STACK_OK;
2093
2094 exit:
2095     OCDeleteResourceAttributes(resAttrib);
2096     return OC_STACK_NO_MEMORY;
2097
2098 }
2099
2100 OCStackResult OCSetPropertyValue(OCPayloadType type, const char *prop, const void *value)
2101 {
2102     if (!prop || !value)
2103     {
2104         return OC_STACK_INVALID_PARAM;
2105     }
2106     if (strlen(prop) == 0)
2107     {
2108         return OC_STACK_INVALID_PARAM;
2109     }
2110
2111     OCStackResult res = OC_STACK_ERROR;
2112     if (PAYLOAD_TYPE_DEVICE == type || PAYLOAD_TYPE_PLATFORM == type)
2113     {
2114         const char *pathType = (type == PAYLOAD_TYPE_DEVICE) ? OC_RSRVD_DEVICE_URI : OC_RSRVD_PLATFORM_URI;
2115         OCResource *resource = FindResourceByUri(pathType);
2116         if (!resource)
2117         {
2118             OIC_LOG(ERROR, TAG, "Resource does not exist.");
2119         }
2120         else
2121         {
2122             res = OCSetAttribute(resource, prop, value);
2123         }
2124     }
2125
2126     return res;
2127 }