build: Updated boost Framework path for ios
[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 static 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->observationOption,
1257                                      (OCObservationId)0,
1258                                      request->coapID);
1259 }
1260
1261 #ifdef RD_SERVER
1262 /**
1263  * Find resource at the resource directory server. This resource is not local resource but a
1264  * remote resource.
1265  *
1266  * @param resource The resource to check the matching resource URI.
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 the resource is found else ::OC_STACK_NO_RESOURCE.
1272  * In case if build is not with flag RD_SERVER, it returns ::OC_STACK_NO_RESOURCE.
1273  */
1274 static OCStackResult findResourceAtRD(const OCResource* resource, const char *interfaceQuery,
1275     const char *resourceTypeQuery, OCDiscoveryPayload *discPayload)
1276 {
1277     if (strcmp(resource->uri, OC_RSRVD_RD_URI) == 0)
1278     {
1279         if (OC_STACK_OK == OCRDDatabaseCheckResources(interfaceQuery, resourceTypeQuery, discPayload))
1280         {
1281             return OC_STACK_OK;
1282         }
1283     }
1284
1285     return OC_STACK_NO_RESOURCE;
1286 }
1287 #endif
1288
1289 /**
1290  * Creates a discovery payload and add device id information. This information is included in all
1291  * /oic/res response.
1292  *
1293  * @param payload  payload that will have memory alllocated and device id information added.
1294  *
1295  * @return ::OC_STACK_OK if successful in allocating memory and adding ID information.
1296  * ::OC_STACK_NO_MEMORY if failed allocating the memory.
1297  */
1298 static OCStackResult discoveryPayloadCreateAndAddDeviceId(OCPayload **payload)
1299 {
1300     if (*payload)
1301     {
1302         OIC_LOG(DEBUG, TAG, "Payload is already allocated");
1303         return OC_STACK_OK;
1304     }
1305
1306     *payload = (OCPayload *) OCDiscoveryPayloadCreate();
1307     VERIFY_PARAM_NON_NULL(TAG, *payload, "Failed adding device id to discovery payload.");
1308
1309     {
1310         OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)*payload;
1311         discPayload->sid = (char *)OICCalloc(1, UUID_STRING_SIZE);
1312         VERIFY_PARAM_NON_NULL(TAG, discPayload->sid, "Failed adding device id to discovery payload.");
1313
1314         const char* uid = OCGetServerInstanceIDString();
1315         if (uid)
1316         {
1317             memcpy(discPayload->sid, uid, UUID_STRING_SIZE);
1318         }
1319
1320     }
1321     return OC_STACK_OK;
1322 exit:
1323     OCPayloadDestroy(*payload);
1324     return OC_STACK_NO_MEMORY;
1325 }
1326
1327 /**
1328  * Add the common properties to the payload, they are only included in case of oic.if.baseline response.
1329  *
1330  * @param discPayload payload that will have the baseline information included.
1331  *
1332  * @return ::OC_STACK_OK if successful in adding all the information. ::OC_STACK_NO_MEMORY if failed
1333  * allocating the memory for the baseline information.
1334  */
1335 static OCStackResult addDiscoveryBaselineCommonProperties(OCDiscoveryPayload *discPayload)
1336 {
1337     if (!discPayload)
1338     {
1339         OIC_LOG(ERROR, TAG, "Payload is not allocated");
1340         return OC_STACK_INVALID_PARAM;
1341     }
1342
1343     OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, (void **)&discPayload->name);
1344
1345     discPayload->type = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
1346     VERIFY_PARAM_NON_NULL(TAG, discPayload->type, "Failed adding rt to discovery payload.");
1347     discPayload->type->value = OICStrdup(OC_RSRVD_RESOURCE_TYPE_RES);
1348     VERIFY_PARAM_NON_NULL(TAG, discPayload->type, "Failed adding rt value to discovery payload.");
1349
1350     OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_LL);
1351     OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_DEFAULT);
1352     VERIFY_PARAM_NON_NULL(TAG, discPayload->iface, "Failed adding if to discovery payload.");
1353
1354     return OC_STACK_OK;
1355
1356 exit:
1357     return OC_STACK_NO_MEMORY;
1358 }
1359
1360 static bool isUnicast(OCServerRequest *request)
1361 {
1362     bool isMulticast = request->devAddr.flags & OC_MULTICAST;
1363     return (isMulticast == false &&
1364            (request->devAddr.adapter != OC_ADAPTER_RFCOMM_BTEDR) &&
1365            (request->devAddr.adapter != OC_ADAPTER_GATT_BTLE));
1366 }
1367
1368 static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource)
1369 {
1370     if (!request || !resource)
1371     {
1372         return OC_STACK_INVALID_PARAM;
1373     }
1374
1375     OCPayload* payload = NULL;
1376     char *interfaceQuery = NULL;
1377     char *resourceTypeQuery = NULL;
1378     char *dataModelVersions = NULL;
1379
1380     OIC_LOG(INFO, TAG, "Entering HandleVirtualResource");
1381
1382     OCVirtualResources virtualUriInRequest = GetTypeOfVirtualURI (request->resourceUrl);
1383
1384 #ifdef TCP_ADAPTER
1385     if (OC_KEEPALIVE_RESOURCE_URI == virtualUriInRequest)
1386     {
1387         // Received request for a keepalive
1388         OIC_LOG(INFO, TAG, "Request is for KeepAlive Request");
1389         return HandleKeepAliveRequest(request, resource);
1390     }
1391 #endif
1392
1393     OCStackResult discoveryResult = OC_STACK_ERROR;
1394     if (request->method == OC_REST_PUT || request->method == OC_REST_POST ||
1395         request->method == OC_REST_DELETE)
1396     {
1397         OIC_LOG_V(ERROR, TAG, "Resource : %s not permitted for method: %d",
1398             request->resourceUrl, request->method);
1399         return OC_STACK_UNAUTHORIZED_REQ;
1400     }
1401
1402     // Step 1: Generate the response to discovery request
1403     if (virtualUriInRequest == OC_WELL_KNOWN_URI
1404 #ifdef MQ_BROKER
1405             || virtualUriInRequest == OC_MQ_BROKER_URI
1406 #endif
1407             )
1408     {
1409         char *interfaceQuery = NULL;
1410         char *resourceTypeQuery = NULL;
1411
1412         CAEndpoint_t *networkInfo = NULL;
1413         uint32_t infoSize = 0;
1414
1415         CAResult_t caResult = CAGetNetworkInformation(&networkInfo, &infoSize);
1416         if (CA_STATUS_FAILED == caResult)
1417         {
1418             OIC_LOG(ERROR, TAG, "CAGetNetworkInformation has error on parsing network infomation");
1419             return OC_STACK_ERROR;
1420         }
1421
1422         discoveryResult = getQueryParamsForFiltering (virtualUriInRequest, request->query,
1423                 &interfaceQuery, &resourceTypeQuery);
1424         VERIFY_SUCCESS(discoveryResult);
1425
1426         if (!interfaceQuery && !resourceTypeQuery)
1427         {
1428             // If no query is sent, default interface is used i.e. oic.if.ll.
1429             interfaceQuery = OICStrdup(OC_RSRVD_INTERFACE_LL);
1430         }
1431
1432         discoveryResult = discoveryPayloadCreateAndAddDeviceId(&payload);
1433         VERIFY_PARAM_NON_NULL(TAG, payload, "Failed creating Discovery Payload.");
1434         VERIFY_SUCCESS(discoveryResult);
1435
1436         OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)payload;
1437         if (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_DEFAULT))
1438         {
1439             discoveryResult = addDiscoveryBaselineCommonProperties(discPayload);
1440             VERIFY_SUCCESS(discoveryResult);
1441         }
1442         OCResourceProperty prop = OC_DISCOVERABLE;
1443 #ifdef MQ_BROKER
1444         prop = (OC_MQ_BROKER_URI == virtualUriInRequest) ? OC_MQ_BROKER : prop;
1445 #endif
1446         for (; resource && discoveryResult == OC_STACK_OK; resource = resource->next)
1447         {
1448             // This case will handle when no resource type and it is oic.if.ll.
1449             // Do not assume check if the query is ll
1450             if (!resourceTypeQuery &&
1451                 (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_LL)))
1452             {
1453                 // Only include discoverable type
1454                 if (resource->resourceProperties & prop)
1455                 {
1456                     discoveryResult = BuildVirtualResourceResponse(resource,
1457                                                                    discPayload,
1458                                                                    &request->devAddr,
1459                                                                    networkInfo,
1460                                                                    infoSize);
1461                 }
1462             }
1463             else if (includeThisResourceInResponse(resource, interfaceQuery, resourceTypeQuery))
1464             {
1465                 discoveryResult = BuildVirtualResourceResponse(resource,
1466                                                                discPayload,
1467                                                                &request->devAddr,
1468                                                                networkInfo,
1469                                                                infoSize);
1470             }
1471             else
1472             {
1473                 discoveryResult = OC_STACK_OK;
1474             }
1475         }
1476         if (discPayload->resources == NULL)
1477         {
1478             discoveryResult = OC_STACK_NO_RESOURCE;
1479         }
1480
1481         if (networkInfo)
1482         {
1483             OICFree(networkInfo);
1484         }
1485     }
1486     else if (virtualUriInRequest == OC_DEVICE_URI)
1487     {
1488         OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_DEVICE_URI);
1489         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Device URI not found.");
1490         discoveryResult = BuildDevicePlatformPayload(resourcePtr, (OCRepPayload **)&payload, true);
1491     }
1492     else if (virtualUriInRequest == OC_PLATFORM_URI)
1493     {
1494         OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_PLATFORM_URI);
1495         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Platform URI not found.");
1496         discoveryResult = BuildDevicePlatformPayload(resourcePtr, (OCRepPayload **)&payload, false);
1497     }
1498 #ifdef ROUTING_GATEWAY
1499     else if (OC_GATEWAY_URI == virtualUriInRequest)
1500     {
1501         // Received request for a gateway
1502         OIC_LOG(INFO, TAG, "Request is for Gateway Virtual Request");
1503         discoveryResult = RMHandleGatewayRequest(request, resource);
1504     }
1505 #endif
1506     else if (OC_INTROSPECTION_URI == virtualUriInRequest)
1507     {
1508         // Received request for introspection
1509         OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_INTROSPECTION_URI);
1510         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Introspection URI not found.");
1511         discoveryResult = BuildIntrospectionResponseRepresentation(resourcePtr, (OCRepPayload **)&payload, &request->devAddr);
1512         OIC_LOG(INFO, TAG, "Request is for Introspection");
1513     }
1514     else if (OC_INTROSPECTION_PAYLOAD_URI == virtualUriInRequest)
1515     {
1516         // Received request for introspection payload
1517         OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_INTROSPECTION_PAYLOAD_URI);
1518         VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Introspection Payload URI not found.");
1519         discoveryResult = BuildIntrospectionPayloadResponse(resourcePtr, (OCRepPayload **)&payload, &request->devAddr);
1520         OIC_LOG(INFO, TAG, "Request is for Introspection Payload");
1521     }
1522     /**
1523      * Step 2: Send the discovery response
1524      *
1525      * Iotivity should respond to discovery requests in below manner:
1526      * 1)If query filter matching fails and discovery request is multicast,
1527      *   it should NOT send any response.
1528      * 2)If query filter matching fails and discovery request is unicast,
1529      *   it should send an error(RESOURCE_NOT_FOUND - 404) response.
1530      * 3)If Server does not have any 'DISCOVERABLE' resources and discovery
1531      *   request is multicast, it should NOT send any response.
1532      * 4)If Server does not have any 'DISCOVERABLE' resources and discovery
1533      *   request is unicast, it should send an error(RESOURCE_NOT_FOUND - 404) response.
1534      */
1535
1536 #ifdef WITH_PRESENCE
1537     if ((virtualUriInRequest == OC_PRESENCE) &&
1538         (resource->resourceProperties & OC_ACTIVE))
1539     {
1540         // Need to send ACK when the request is CON.
1541         if (request->qos == OC_HIGH_QOS)
1542         {
1543             CAEndpoint_t endpoint = { .adapter = CA_DEFAULT_ADAPTER };
1544             CopyDevAddrToEndpoint(&request->devAddr, &endpoint);
1545             SendDirectStackResponse(&endpoint, request->coapID, CA_EMPTY, CA_MSG_ACKNOWLEDGE,
1546                                     0, NULL, NULL, 0, NULL, CA_RESPONSE_FOR_RES);
1547         }
1548         FindAndDeleteServerRequest(request);
1549
1550         // Presence uses observer notification api to respond via SendPresenceNotification.
1551         SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
1552     }
1553     else
1554 #endif
1555 #if ROUTING_GATEWAY
1556     // Gateway uses the RMHandleGatewayRequest to respond to the request.
1557     if (OC_GATEWAY_URI != virtualUriInRequest)
1558 #endif
1559     {
1560         OIC_LOG_PAYLOAD(DEBUG, payload);
1561         if(discoveryResult == OC_STACK_OK)
1562         {
1563
1564             SendNonPersistantDiscoveryResponse(request, resource, payload, OC_EH_OK);
1565         }
1566         else // Error handling
1567         {
1568             if (isUnicast(request))
1569             {
1570                 OIC_LOG_V(ERROR, TAG, "Sending a (%d) error to (%d) discovery request",
1571                     discoveryResult, virtualUriInRequest);
1572                 SendNonPersistantDiscoveryResponse(request, resource, NULL,
1573                     (discoveryResult == OC_STACK_NO_RESOURCE) ?
1574                         OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR);
1575             }
1576             else // Multicast
1577             {
1578                 // Ignoring the discovery request as per RFC 7252, Section #8.2
1579                 OIC_LOG(INFO, TAG, "Silently ignoring the request since no useful data to send.");
1580                 // the request should be removed.
1581                 // since it never remove and causes a big memory waste.
1582                 FindAndDeleteServerRequest(request);
1583             }
1584             discoveryResult = OC_STACK_CONTINUE;
1585         }
1586     }
1587
1588 exit:
1589     if (interfaceQuery)
1590     {
1591         OICFree(interfaceQuery);
1592     }
1593
1594     if (resourceTypeQuery)
1595     {
1596         OICFree(resourceTypeQuery);
1597     }
1598     OCPayloadDestroy(payload);
1599     if (dataModelVersions)
1600     {
1601         OICFree(dataModelVersions);
1602     }
1603     // To ignore the message, OC_STACK_CONTINUE is sent
1604     return discoveryResult;
1605 }
1606
1607 static OCStackResult
1608 HandleDefaultDeviceEntityHandler(OCServerRequest *request)
1609 {
1610     if (!request)
1611     {
1612         return OC_STACK_INVALID_PARAM;
1613     }
1614
1615     OCEntityHandlerResult ehResult = OC_EH_ERROR;
1616     OCEntityHandlerRequest ehRequest = {0};
1617     OIC_LOG(INFO, TAG, "Entering HandleResourceWithDefaultDeviceEntityHandler");
1618     OCStackResult result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, NULL);
1619     VERIFY_SUCCESS(result);
1620
1621     // At this point we know for sure that defaultDeviceHandler exists
1622     ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
1623                                   (char*) request->resourceUrl, defaultDeviceHandlerCallbackParameter);
1624     if(ehResult == OC_EH_SLOW)
1625     {
1626         OIC_LOG(INFO, TAG, "This is a slow resource");
1627         request->slowFlag = 1;
1628     }
1629     else if(ehResult == OC_EH_ERROR)
1630     {
1631         FindAndDeleteServerRequest(request);
1632     }
1633     result = EntityHandlerCodeToOCStackCode(ehResult);
1634 exit:
1635     OCPayloadDestroy(ehRequest.payload);
1636     return result;
1637 }
1638
1639 static OCStackResult
1640 HandleResourceWithEntityHandler(OCServerRequest *request,
1641                                 OCResource *resource)
1642 {
1643     if(!request || ! resource)
1644     {
1645         return OC_STACK_INVALID_PARAM;
1646     }
1647
1648     OCStackResult result = OC_STACK_ERROR;
1649     OCEntityHandlerResult ehResult = OC_EH_ERROR;
1650     OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
1651     ResourceObserver *resObs = NULL;
1652
1653     OCEntityHandlerRequest ehRequest = {0};
1654
1655     OIC_LOG(INFO, TAG, "Entering HandleResourceWithEntityHandler");
1656     OCPayloadType type = PAYLOAD_TYPE_REPRESENTATION;
1657     // check the security resource
1658     if (request && request->resourceUrl && SRMIsSecurityResourceURI(request->resourceUrl))
1659     {
1660         type = PAYLOAD_TYPE_SECURITY;
1661
1662     }
1663
1664     result = EHRequest(&ehRequest, type, request, resource);
1665     VERIFY_SUCCESS(result);
1666
1667     if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
1668     {
1669         OIC_LOG(INFO, TAG, "No observation requested");
1670         ehFlag = OC_REQUEST_FLAG;
1671     }
1672     else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER)
1673     {
1674         OIC_LOG(INFO, TAG, "Observation registration requested");
1675
1676         ResourceObserver *obs = GetObserverUsingToken (request->requestToken,
1677                                     request->tokenLength);
1678
1679         if (obs)
1680         {
1681             OIC_LOG (INFO, TAG, "Observer with this token already present");
1682             OIC_LOG (INFO, TAG, "Possibly re-transmitted CON OBS request");
1683             OIC_LOG (INFO, TAG, "Not adding observer. Not responding to client");
1684             OIC_LOG (INFO, TAG, "The first request for this token is already ACKED.");
1685
1686             // server requests are usually free'd when the response is sent out
1687             // for the request in ocserverrequest.c : HandleSingleResponse()
1688             // Since we are making an early return and not responding, the server request
1689             // needs to be deleted.
1690             FindAndDeleteServerRequest (request);
1691             return OC_STACK_OK;
1692         }
1693
1694         result = GenerateObserverId(&ehRequest.obsInfo.obsId);
1695         VERIFY_SUCCESS(result);
1696
1697         result = AddObserver ((const char*)(request->resourceUrl),
1698                 (const char *)(request->query),
1699                 ehRequest.obsInfo.obsId, request->requestToken, request->tokenLength,
1700                 resource, request->qos, request->acceptFormat,
1701                 request->acceptVersion, &request->devAddr);
1702
1703         if(result == OC_STACK_OK)
1704         {
1705             OIC_LOG(INFO, TAG, "Added observer successfully");
1706             request->observeResult = OC_STACK_OK;
1707             ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
1708         }
1709         else if (result == OC_STACK_RESOURCE_ERROR)
1710         {
1711             OIC_LOG(INFO, TAG, "The Resource is not active, discoverable or observable");
1712             request->observeResult = OC_STACK_ERROR;
1713             ehFlag = OC_REQUEST_FLAG;
1714         }
1715         else
1716         {
1717             // The error in observeResult for the request will be used when responding to this
1718             // request by omitting the observation option/sequence number.
1719             request->observeResult = OC_STACK_ERROR;
1720             OIC_LOG(ERROR, TAG, "Observer Addition failed");
1721             ehFlag = OC_REQUEST_FLAG;
1722             FindAndDeleteServerRequest(request);
1723             goto exit;
1724         }
1725
1726     }
1727     else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER)
1728     {
1729         OIC_LOG(INFO, TAG, "Deregistering observation requested");
1730
1731         resObs = GetObserverUsingToken (request->requestToken, request->tokenLength);
1732
1733         if (NULL == resObs)
1734         {
1735             // Stack does not contain this observation request
1736             // Either token is incorrect or observation list is corrupted
1737             result = OC_STACK_ERROR;
1738             goto exit;
1739         }
1740         ehRequest.obsInfo.obsId = resObs->observeId;
1741         ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
1742
1743         result = DeleteObserverUsingToken (request->requestToken, request->tokenLength);
1744
1745         if(result == OC_STACK_OK)
1746         {
1747             OIC_LOG(INFO, TAG, "Removed observer successfully");
1748             request->observeResult = OC_STACK_OK;
1749             // There should be no observe option header for de-registration response.
1750             // Set as an invalid value here so we can detect it later and remove the field in response.
1751             request->observationOption = MAX_SEQUENCE_NUMBER + 1;
1752         }
1753         else
1754         {
1755             request->observeResult = OC_STACK_ERROR;
1756             OIC_LOG(ERROR, TAG, "Observer Removal failed");
1757             FindAndDeleteServerRequest(request);
1758             goto exit;
1759         }
1760     }
1761     else
1762     {
1763         result = OC_STACK_ERROR;
1764         goto exit;
1765     }
1766
1767     ehResult = resource->entityHandler(ehFlag, &ehRequest, resource->entityHandlerCallbackParam);
1768     if(ehResult == OC_EH_SLOW)
1769     {
1770         OIC_LOG(INFO, TAG, "This is a slow resource");
1771         request->slowFlag = 1;
1772     }
1773     else if(ehResult == OC_EH_ERROR)
1774     {
1775         FindAndDeleteServerRequest(request);
1776     }
1777     result = EntityHandlerCodeToOCStackCode(ehResult);
1778 exit:
1779     OCPayloadDestroy(ehRequest.payload);
1780     return result;
1781 }
1782
1783 static OCStackResult HandleCollectionResourceDefaultEntityHandler(OCServerRequest *request,
1784                                                                   OCResource *resource)
1785 {
1786     if (!request || !resource)
1787     {
1788         return OC_STACK_INVALID_PARAM;
1789     }
1790
1791     OCEntityHandlerRequest ehRequest = {0};
1792     OCStackResult result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, resource);
1793     if(result == OC_STACK_OK)
1794     {
1795         result = DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest);
1796     }
1797
1798     OCPayloadDestroy(ehRequest.payload);
1799     return result;
1800 }
1801
1802 OCStackResult
1803 ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request)
1804 {
1805     OCStackResult ret = OC_STACK_OK;
1806
1807     switch (resHandling)
1808     {
1809         case OC_RESOURCE_VIRTUAL:
1810         {
1811             ret = HandleVirtualResource (request, resource);
1812             break;
1813         }
1814         case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER:
1815         {
1816             ret = HandleDefaultDeviceEntityHandler(request);
1817             break;
1818         }
1819         case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
1820         {
1821             OIC_LOG(INFO, TAG, "OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER");
1822             return OC_STACK_ERROR;
1823         }
1824         case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
1825         {
1826             ret = HandleResourceWithEntityHandler (request, resource);
1827             break;
1828         }
1829         case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
1830         {
1831             ret = HandleResourceWithEntityHandler (request, resource);
1832             break;
1833         }
1834         case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
1835         {
1836             ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
1837             break;
1838         }
1839         case OC_RESOURCE_NOT_SPECIFIED:
1840         {
1841             ret = OC_STACK_NO_RESOURCE;
1842             break;
1843         }
1844         default:
1845         {
1846             OIC_LOG(INFO, TAG, "Invalid Resource Determination");
1847             return OC_STACK_ERROR;
1848         }
1849     }
1850     return ret;
1851 }
1852
1853 OCStackResult OCSetPlatformInfo(OCPlatformInfo info)
1854 {
1855     OCResource *resource = NULL;
1856     if (!info.platformID || !info.manufacturerName)
1857     {
1858         OIC_LOG(ERROR, TAG, "No value specified.");
1859         goto exit;
1860     }
1861     if (0 == strlen(info.platformID) || 0 == strlen(info.manufacturerName))
1862     {
1863         OIC_LOG(ERROR, TAG, "The passed value cannot be empty");
1864         goto exit;
1865     }
1866     if ((info.manufacturerName && strlen(info.manufacturerName) > MAX_PLATFORM_NAME_LENGTH) ||
1867         (info.manufacturerUrl && strlen(info.manufacturerUrl) > MAX_PLATFORM_URL_LENGTH) ||
1868         (info.modelNumber && strlen(info.modelNumber) > MAX_PLATFORM_NAME_LENGTH) ||
1869         (info.platformVersion && strlen(info.platformVersion) > MAX_PLATFORM_NAME_LENGTH) ||
1870         (info.operatingSystemVersion && strlen(info.operatingSystemVersion) > MAX_PLATFORM_NAME_LENGTH) ||
1871         (info.hardwareVersion && strlen(info.hardwareVersion) > MAX_PLATFORM_NAME_LENGTH) ||
1872         (info.firmwareVersion && strlen(info.firmwareVersion) > MAX_PLATFORM_NAME_LENGTH) ||
1873         (info.supportUrl && strlen(info.supportUrl) > MAX_PLATFORM_URL_LENGTH))
1874     {
1875         OIC_LOG(ERROR, TAG, "The passed value is bigger than permitted.");
1876         goto exit;
1877     }
1878
1879     /*
1880      * @todo (IOT-1541) There are several versions of a UUID structure and conversion
1881      * methods scattered around the IoTivity code base.  They need to be combined
1882      * into one PAL API.
1883      */
1884     uint8_t uuid[UUID_SIZE];
1885     if (!OCConvertStringToUuid(info.platformID, uuid))
1886     {
1887         OIC_LOG(ERROR, TAG, "Platform ID is not a UUID.");
1888         goto exit;
1889     }
1890
1891     resource = FindResourceByUri(OC_RSRVD_PLATFORM_URI);
1892     if (!resource)
1893     {
1894         OIC_LOG(ERROR, TAG, "Platform Resource does not exist.");
1895         goto exit;
1896     }
1897     OIC_LOG(INFO, TAG, "Entering OCSetPlatformInfo");
1898     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_PLATFORM_ID, info.platformID));
1899     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_NAME, info.manufacturerName));
1900     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_URL, info.manufacturerUrl);
1901     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MODEL_NUM, info.modelNumber);
1902     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_DATE, info.dateOfManufacture);
1903     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_PLATFORM_VERSION, info.platformVersion);
1904     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_OS_VERSION, info.operatingSystemVersion);
1905     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_HARDWARE_VERSION, info.hardwareVersion);
1906     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_FIRMWARE_VERSION, info.firmwareVersion);
1907     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_SUPPORT_URL, info.supportUrl);
1908     OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_SYSTEM_TIME, info.systemTime);
1909     OIC_LOG(INFO, TAG, "Platform parameter initialized successfully.");
1910     return OC_STACK_OK;
1911
1912 exit:
1913     return OC_STACK_INVALID_PARAM;
1914 }
1915
1916 OCStackResult OCSetDeviceInfo(OCDeviceInfo info)
1917 {
1918     OCResource *resource = FindResourceByUri(OC_RSRVD_DEVICE_URI);
1919     if (!resource)
1920     {
1921         OIC_LOG(ERROR, TAG, "Device Resource does not exist.");
1922         goto exit;
1923     }
1924     if (!info.deviceName || info.deviceName[0] == '\0')
1925     {
1926         OIC_LOG(ERROR, TAG, "Null or empty device name.");
1927        return OC_STACK_INVALID_PARAM;
1928     }
1929
1930     if (OCGetServerInstanceIDString() == NULL)
1931     {
1932         OIC_LOG(INFO, TAG, "Device ID generation failed");
1933         goto exit;
1934     }
1935
1936     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, info.deviceName));
1937     for (OCStringLL *temp = info.types; temp; temp = temp->next)
1938     {
1939         if (temp->value)
1940         {
1941             VERIFY_SUCCESS(OCBindResourceTypeToResource(resource, temp->value));
1942         }
1943     }
1944     VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_SPEC_VERSION, info.specVersion ?
1945         info.specVersion: OC_SPEC_VERSION));
1946
1947     if (info.dataModelVersions)
1948     {
1949         char *dmv = OCCreateString(info.dataModelVersions);
1950         VERIFY_PARAM_NON_NULL(TAG, dmv, "Failed allocating dataModelVersions");
1951         OCStackResult r = OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION, dmv);
1952         OICFree(dmv);
1953         VERIFY_SUCCESS(r);
1954     }
1955     else
1956     {
1957         VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION,
1958             OC_DATA_MODEL_VERSION));
1959     }
1960     OIC_LOG(INFO, TAG, "Device parameter initialized successfully.");
1961     return OC_STACK_OK;
1962
1963 exit:
1964     return OC_STACK_ERROR;
1965 }
1966
1967 OCStackResult OCGetAttribute(const OCResource *resource, const char *attribute, void **value)
1968 {
1969     if (!resource || !attribute)
1970     {
1971         return OC_STACK_INVALID_PARAM;
1972     }
1973     if (0 == strlen(attribute))
1974     {
1975         return OC_STACK_INVALID_PARAM;
1976     }
1977     for (OCAttribute *temp = resource->rsrcAttributes; temp; temp = temp->next)
1978     {
1979         if (0 == strcmp(attribute, temp->attrName))
1980         {
1981             // A special case as this type return OCStringLL
1982             if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, attribute))
1983             {
1984                 *value = CloneOCStringLL((OCStringLL *)temp->attrValue);
1985                 return OC_STACK_OK;
1986             }
1987             else
1988             {
1989                 *value = OICStrdup((char *)temp->attrValue);
1990                 return OC_STACK_OK;
1991             }
1992         }
1993     }
1994     return OC_STACK_NO_RESOURCE;
1995 }
1996
1997 OCStackResult OCGetPropertyValue(OCPayloadType type, const char *prop, void **value)
1998 {
1999     if (!prop)
2000     {
2001         return OC_STACK_INVALID_PARAM;
2002     }
2003     if (strlen(prop) == 0)
2004     {
2005         return OC_STACK_INVALID_PARAM;
2006     }
2007     if (*value)
2008     {
2009         *value = NULL;
2010     }
2011     OCStackResult res =  OC_STACK_NO_RESOURCE;
2012     if (PAYLOAD_TYPE_DEVICE == type || PAYLOAD_TYPE_PLATFORM == type)
2013     {
2014         const char *pathType = (type == PAYLOAD_TYPE_DEVICE) ? OC_RSRVD_DEVICE_URI : OC_RSRVD_PLATFORM_URI;
2015         OCResource *resource = FindResourceByUri(pathType);
2016         if (!resource)
2017         {
2018             return OC_STACK_NO_RESOURCE;
2019         }
2020
2021         res = OCGetAttribute(resource, prop, value);
2022     }
2023     return res;
2024 }
2025
2026 OCStackResult OCSetAttribute(OCResource* resource, const char* attribute, const void* value)
2027 {
2028     // See if the attribute already exists in the list.
2029     OCAttribute *resAttrib = NULL;
2030     for (resAttrib = resource->rsrcAttributes; resAttrib; resAttrib = resAttrib->next)
2031     {
2032         if (0 == strcmp(attribute, resAttrib->attrName))
2033         {
2034             // Found, free the old value.
2035             if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName))
2036             {
2037                 OCFreeOCStringLL((OCStringLL *)resAttrib->attrValue);
2038             }
2039             else
2040             {
2041                 OICFree((char *)resAttrib->attrValue);
2042             }
2043             break;
2044         }
2045     }
2046
2047     // If not already in the list, add it.
2048     if (NULL == resAttrib)
2049     {
2050         resAttrib = (OCAttribute *)OICCalloc(1, sizeof(OCAttribute));
2051         VERIFY_PARAM_NON_NULL(TAG, resAttrib, "Failed allocating OCAttribute");
2052         resAttrib->attrName = OICStrdup(attribute);
2053         VERIFY_PARAM_NON_NULL(TAG, resAttrib->attrName, "Failed allocating attribute name");
2054         resAttrib->next = resource->rsrcAttributes;
2055         resource->rsrcAttributes = resAttrib;
2056     }
2057
2058     // Fill in the new value.
2059     if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, attribute))
2060     {
2061         resAttrib->attrValue = OCCreateOCStringLL((char *)value);
2062     }
2063     else
2064     {
2065         resAttrib->attrValue = OICStrdup((char *)value);
2066     }
2067     VERIFY_PARAM_NON_NULL(TAG, resAttrib->attrValue, "Failed allocating attribute value");
2068
2069     return OC_STACK_OK;
2070
2071 exit:
2072     OCDeleteResourceAttributes(resAttrib);
2073     return OC_STACK_NO_MEMORY;
2074
2075 }
2076
2077 OCStackResult OCSetPropertyValue(OCPayloadType type, const char *prop, const void *value)
2078 {
2079     if (!prop || !value)
2080     {
2081         return OC_STACK_INVALID_PARAM;
2082     }
2083     if (strlen(prop) == 0)
2084     {
2085         return OC_STACK_INVALID_PARAM;
2086     }
2087
2088     OCStackResult res = OC_STACK_ERROR;
2089     if (PAYLOAD_TYPE_DEVICE == type || PAYLOAD_TYPE_PLATFORM == type)
2090     {
2091         const char *pathType = (type == PAYLOAD_TYPE_DEVICE) ? OC_RSRVD_DEVICE_URI : OC_RSRVD_PLATFORM_URI;
2092         OCResource *resource = FindResourceByUri(pathType);
2093         if (!resource)
2094         {
2095             OIC_LOG(ERROR, TAG, "Resource does not exist.");
2096         }
2097         else
2098         {
2099             res = OCSetAttribute(resource, prop, value);
2100         }
2101     }
2102
2103     return res;
2104 }