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