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