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