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