Merge branch 'master' into simulator.
[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 "ocresource"
54 #define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
55             {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
56
57 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
58              TAG, #arg " is NULL"); return (retVal); } }
59
60 extern OCResource *headResource;
61 static OCPlatformInfo savedPlatformInfo = {0};
62 static OCDeviceInfo savedDeviceInfo = {0};
63
64 /**
65  * Prepares a Payload for response.
66  */
67 static OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
68                                                   OCDiscoveryPayload* payload,
69                                                   OCDevAddr *endpoint,
70                                                   bool rdResponse);
71
72 //-----------------------------------------------------------------------------
73 // Default resource entity handler function
74 //-----------------------------------------------------------------------------
75 OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag,
76         OCEntityHandlerRequest * request, void* callbackParam)
77 {
78     //TODO ("Implement me!!!!");
79     // TODO:  remove silence unused param warnings
80     (void) flag;
81     (void) request;
82     (void) callbackParam;
83     return  OC_EH_OK; // Making sure that the Default EH and the Vendor EH have matching signatures
84 }
85
86 /* This method will retrieve the port at which the secure resource is hosted */
87 static OCStackResult GetSecurePortInfo(OCDevAddr *endpoint, uint16_t *port)
88 {
89     uint16_t p = 0;
90
91     if (endpoint->adapter == OC_ADAPTER_IP)
92     {
93         if (endpoint->flags & OC_IP_USE_V6)
94         {
95             p = caglobals.ip.u6s.port;
96         }
97         else if (endpoint->flags & OC_IP_USE_V4)
98         {
99             p = caglobals.ip.u4s.port;
100         }
101     }
102
103     *port = p;
104     return OC_STACK_OK;
105 }
106
107 /*
108  * Function will extract 0, 1 or 2 filters from query.
109  * More than 2 filters or unsupported filters will result in error.
110  * If both filters are of the same supported type, the 2nd one will be picked.
111  * Resource and device filters in the SAME query are NOT validated
112  * and resources will likely not clear filters.
113  */
114 static OCStackResult ExtractFiltersFromQuery(char *query, char **filterOne, char **filterTwo)
115 {
116
117     char *key = NULL;
118     char *value = NULL;
119     char *restOfQuery = NULL;
120     int numKeyValuePairsParsed = 0;
121
122     *filterOne = NULL;
123     *filterTwo = NULL;
124
125     OC_LOG_V(INFO, TAG, "Extracting params from %s", query);
126
127     char *keyValuePair = strtok_r (query, OC_QUERY_SEPARATOR, &restOfQuery);
128
129     while(keyValuePair)
130     {
131         if (numKeyValuePairsParsed >= 2)
132         {
133             OC_LOG(ERROR, TAG, "More than 2 queries params in URI.");
134             return OC_STACK_INVALID_QUERY;
135         }
136
137         key = strtok_r(keyValuePair, OC_KEY_VALUE_DELIMITER, &value);
138
139         if (!key || !value)
140         {
141             return OC_STACK_INVALID_QUERY;
142         }
143         else if (strcmp (key, OC_RSRVD_INTERFACE) == 0)
144         {
145             *filterOne = value;     // if
146         }
147         else if (strcmp (key, OC_RSRVD_RESOURCE_TYPE) == 0)
148         {
149             *filterTwo = value;     // rt
150         }
151         else
152         {
153             OC_LOG_V(ERROR, TAG, "Unsupported query key: %s", key);
154             return OC_STACK_INVALID_QUERY;
155         }
156         ++numKeyValuePairsParsed;
157
158         keyValuePair = strtok_r(NULL, OC_QUERY_SEPARATOR, &restOfQuery);
159     }
160
161     OC_LOG_V(INFO, TAG, "Extracted params %s and %s.", *filterOne, *filterTwo);
162     return OC_STACK_OK;
163 }
164
165 static OCVirtualResources GetTypeOfVirtualURI(const char *uriInRequest)
166 {
167     if (strcmp(uriInRequest, OC_RSRVD_WELL_KNOWN_URI) == 0)
168     {
169         return OC_WELL_KNOWN_URI;
170     }
171     else if (strcmp(uriInRequest, OC_RSRVD_DEVICE_URI) == 0)
172     {
173         return OC_DEVICE_URI;
174     }
175     else if (strcmp(uriInRequest, OC_RSRVD_PLATFORM_URI) == 0)
176     {
177         return OC_PLATFORM_URI;
178     }
179     else if (strcmp(uriInRequest, OC_RSRVD_RESOURCE_TYPES_URI) == 0)
180     {
181         return OC_RESOURCE_TYPES_URI;
182     }
183 #ifdef ROUTING_GATEWAY
184     else if (0 == strcmp(uriInRequest, OC_RSRVD_GATEWAY_URI))
185     {
186         return OC_GATEWAY_URI;
187     }
188 #endif
189 #ifdef WITH_PRESENCE
190     else if (strcmp(uriInRequest, OC_RSRVD_PRESENCE_URI) == 0)
191     {
192         return OC_PRESENCE;
193     }
194 #endif //WITH_PRESENCE
195     return OC_UNKNOWN_URI;
196 }
197
198 static OCStackResult getQueryParamsForFiltering (OCVirtualResources uri, char *query,
199                                             char **filterOne, char **filterTwo)
200 {
201     if(!filterOne || !filterTwo)
202     {
203         return OC_STACK_INVALID_PARAM;
204     }
205
206     *filterOne = NULL;
207     *filterTwo = NULL;
208
209     #ifdef WITH_PRESENCE
210     if (uri == OC_PRESENCE)
211     {
212         //Nothing needs to be done, except for pass a OC_PRESENCE query through as OC_STACK_OK.
213         OC_LOG(INFO, TAG, "OC_PRESENCE Request for virtual resource.");
214         return OC_STACK_OK;
215     }
216     #endif
217
218     OCStackResult result = OC_STACK_OK;
219
220     if (query && *query)
221     {
222         result = ExtractFiltersFromQuery(query, filterOne, filterTwo);
223     }
224
225     return result;
226 }
227
228 OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr,
229                     OCRepPayload** payload)
230 {
231     OCRepPayload *tempPayload = OCRepPayloadCreate();
232
233     if (!resourcePtr)
234     {
235         OCRepPayloadDestroy(tempPayload);
236         return OC_STACK_INVALID_PARAM;
237     }
238
239     if(!tempPayload)
240     {
241         return OC_STACK_NO_MEMORY;
242     }
243
244     OCRepPayloadSetUri(tempPayload, resourcePtr->uri);
245
246     OCResourceType *resType = resourcePtr->rsrcType;
247     while(resType)
248     {
249         OCRepPayloadAddResourceType(tempPayload, resType->resourcetypename);
250         resType = resType->next;
251     }
252
253     OCResourceInterface *resInterface = resourcePtr->rsrcInterface;
254     while(resInterface)
255     {
256         OCRepPayloadAddInterface(tempPayload, resInterface->name);
257         resInterface = resInterface->next;
258     }
259
260     OCAttribute *resAttrib = resourcePtr->rsrcAttributes;
261     while(resAttrib)
262     {
263         OCRepPayloadSetPropString(tempPayload, resAttrib->attrName,
264                                 resAttrib->attrValue);
265         resAttrib = resAttrib->next;
266     }
267
268     if(!*payload)
269     {
270         *payload = tempPayload;
271     }
272     else
273     {
274         OCRepPayloadAppend(*payload, tempPayload);
275     }
276
277     return OC_STACK_OK;
278 }
279
280 OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
281                         OCDiscoveryPayload *payload, OCDevAddr *devAddr, bool rdResponse)
282 {
283     if (!resourcePtr || !payload)
284     {
285         return OC_STACK_INVALID_PARAM;
286     }
287     uint16_t port = 0;
288     if (resourcePtr->resourceProperties & OC_SECURE)
289     {
290        if (GetSecurePortInfo(devAddr, &port) != OC_STACK_OK)
291        {
292            port = 0;
293        }
294     }
295
296     if (rdResponse)
297     {
298         port = devAddr->port;
299     }
300
301     OCDiscoveryPayloadAddResource(payload, resourcePtr, port);
302     return OC_STACK_OK;
303 }
304
305 uint8_t IsCollectionResource (OCResource *resource)
306 {
307     if(!resource)
308     {
309         return 0;
310     }
311
312     for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
313     {
314         if (resource->rsrcResources[i])
315         {
316             return 1;
317         }
318     }
319     return 0;
320 }
321
322 OCResource *FindResourceByUri(const char* resourceUri)
323 {
324     if(!resourceUri)
325     {
326         return NULL;
327     }
328
329     OCResource * pointer = headResource;
330     while (pointer)
331     {
332         if (strcmp(resourceUri, pointer->uri) == 0)
333         {
334             return pointer;
335         }
336         pointer = pointer->next;
337     }
338     OC_LOG_V(INFO, TAG, "Resource %s not found", resourceUri);
339     return NULL;
340 }
341
342
343 OCStackResult DetermineResourceHandling (const OCServerRequest *request,
344                                          ResourceHandling *handling,
345                                          OCResource **resource)
346 {
347     if(!request || !handling || !resource)
348     {
349         return OC_STACK_INVALID_PARAM;
350     }
351
352     OC_LOG_V(INFO, TAG, "DetermineResourceHandling for %s", request->resourceUrl);
353
354     // Check if virtual resource
355     if (GetTypeOfVirtualURI(request->resourceUrl) != OC_UNKNOWN_URI)
356     {
357         OC_LOG_V (INFO, TAG, "%s is virtual", request->resourceUrl);
358         *handling = OC_RESOURCE_VIRTUAL;
359         *resource = headResource;
360         return OC_STACK_OK;
361     }
362     if (strlen((const char*)(request->resourceUrl)) == 0)
363     {
364         // Resource URL not specified
365         *handling = OC_RESOURCE_NOT_SPECIFIED;
366         return OC_STACK_NO_RESOURCE;
367     }
368     else
369     {
370         OCResource *resourcePtr = FindResourceByUri((const char*)request->resourceUrl);
371         *resource = resourcePtr;
372         if (!resourcePtr)
373         {
374             if(defaultDeviceHandler)
375             {
376                 *handling = OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER;
377                 return OC_STACK_OK;
378             }
379
380             // Resource does not exist
381             // and default device handler does not exist
382             *handling = OC_RESOURCE_NOT_SPECIFIED;
383             return OC_STACK_NO_RESOURCE;
384         }
385
386         if (IsCollectionResource (resourcePtr))
387         {
388             // Collection resource
389             if (resourcePtr->entityHandler != defaultResourceEHandler)
390             {
391                 *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER;
392                 return OC_STACK_OK;
393             }
394             else
395             {
396                 *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER;
397                 return OC_STACK_OK;
398             }
399         }
400         else
401         {
402             // Resource not a collection
403             if (resourcePtr->entityHandler != defaultResourceEHandler)
404             {
405                 *handling = OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER;
406                 return OC_STACK_OK;
407             }
408             else
409             {
410                 *handling = OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER;
411                 return OC_STACK_OK;
412             }
413         }
414     }
415 }
416
417 OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
418 {
419     OCStackResult result;
420
421     switch (ehResult)
422     {
423         case OC_EH_OK:
424             result = OC_STACK_OK;
425             break;
426         case OC_EH_SLOW:
427             result = OC_STACK_SLOW_RESOURCE;
428             break;
429         case OC_EH_ERROR:
430             result = OC_STACK_ERROR;
431             break;
432         case OC_EH_FORBIDDEN:
433             result = OC_STACK_RESOURCE_ERROR;
434             break;
435         case OC_EH_RESOURCE_CREATED:
436             result = OC_STACK_RESOURCE_CREATED;
437             break;
438         case OC_EH_RESOURCE_DELETED:
439             result = OC_STACK_RESOURCE_DELETED;
440             break;
441         case OC_EH_RESOURCE_NOT_FOUND:
442             result = OC_STACK_NO_RESOURCE;
443             break;
444         default:
445             result = OC_STACK_ERROR;
446     }
447
448     return result;
449 }
450
451 static bool resourceMatchesRTFilter(OCResource *resource, char *resourceTypeFilter)
452 {
453     if (!resource)
454     {
455         return false;
456     }
457
458     // Null or empty is analogous to no filter.
459     if (resourceTypeFilter == NULL || *resourceTypeFilter == 0)
460     {
461         return true;
462     }
463
464     OCResourceType *resourceTypePtr = resource->rsrcType;
465
466     while (resourceTypePtr)
467     {
468         if (strcmp (resourceTypePtr->resourcetypename, resourceTypeFilter) == 0)
469         {
470             return true;
471         }
472         resourceTypePtr = resourceTypePtr->next;
473     }
474
475     OC_LOG_V(INFO, TAG, "%s does not contain rt=%s.", resource->uri, resourceTypeFilter);
476     return false;
477 }
478
479 static bool resourceMatchesIFFilter(OCResource *resource, char *interfaceFilter)
480 {
481     if (!resource)
482     {
483         return false;
484     }
485
486     // Null or empty is analogous to no filter.
487     if (interfaceFilter == NULL || *interfaceFilter == 0)
488     {
489         return true;
490     }
491
492     OCResourceInterface *interfacePtr = resource->rsrcInterface;
493
494     while (interfacePtr)
495     {
496         if (strcmp (interfacePtr->name, interfaceFilter) == 0)
497         {
498             return true;
499         }
500         interfacePtr = interfacePtr->next;
501     }
502
503     OC_LOG_V(INFO, TAG, "%s does not contain if=%s.", resource->uri, interfaceFilter);
504     return false;
505 }
506
507 /*
508  * If the filters are null, they will be assumed to NOT be present
509  * and the resource will not be matched against them.
510  * Function will return true if all non null AND non empty filters passed in find a match.
511  */
512 static bool includeThisResourceInResponse(OCResource *resource,
513                                                  char *interfaceFilter,
514                                                  char *resourceTypeFilter)
515 {
516     if (!resource)
517     {
518         OC_LOG(ERROR, TAG, "Invalid resource");
519         return false;
520     }
521
522     if ( resource->resourceProperties & OC_EXPLICIT_DISCOVERABLE)
523     {
524         /*
525          * At least one valid filter should be available to
526          * include the resource in discovery response
527          */
528         if (!((interfaceFilter && *interfaceFilter ) ||
529               (resourceTypeFilter && *resourceTypeFilter)))
530         {
531             OC_LOG_V(INFO, TAG, "%s no query string for EXPLICIT_DISCOVERABLE \
532                 resource", resource->uri);
533             return false;
534         }
535     }
536     else if ( !(resource->resourceProperties & OC_ACTIVE) ||
537          !(resource->resourceProperties & OC_DISCOVERABLE))
538     {
539         OC_LOG_V(INFO, TAG, "%s not ACTIVE or DISCOVERABLE", resource->uri);
540         return false;
541     }
542
543     return resourceMatchesIFFilter(resource, interfaceFilter) &&
544            resourceMatchesRTFilter(resource, resourceTypeFilter);
545
546 }
547
548 OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCResource *resource,
549                                 OCPayload *discoveryPayload, OCEntityHandlerResult ehResult)
550 {
551     OCEntityHandlerResponse response = {0};
552
553     response.ehResult = ehResult;
554     response.payload = discoveryPayload;
555     response.persistentBufferFlag = 0;
556     response.requestHandle = (OCRequestHandle) request;
557     response.resourceHandle = (OCResourceHandle) resource;
558
559     return OCDoResponse(&response);
560 }
561
562 #ifdef WITH_RD
563 static OCStackResult checkResourceExistsAtRD(const char *interfaceType, const char *resourceType,
564      OCResource **payload, OCDevAddr *devAddr)
565 {
566     OCResourceCollectionPayload *repPayload;
567     if (!payload)
568     {
569         return OC_STACK_ERROR;
570     }
571     if (OCRDCheckPublishedResource(interfaceType, resourceType, &repPayload, devAddr) == OC_STACK_OK)
572     {
573         if (!repPayload)
574         {
575             return OC_STACK_ERROR;
576         }
577         OCResource *ptr = ((OCResource *) OICCalloc(1, sizeof(OCResource)));
578         if (!ptr)
579         {
580            return OC_STACK_NO_MEMORY;
581         }
582
583         ptr->uri = OICStrdup(repPayload->setLinks->href);
584         if (!ptr->uri)
585         {
586            return OC_STACK_NO_MEMORY;
587         }
588         OCStringLL *rt = repPayload->setLinks->rt;
589         while (rt)
590         {
591             OCResourceType *temp = (OCResourceType *) OICCalloc(1, sizeof(OCResourceType));
592             if(!temp)
593             {
594                 OICFree(ptr->uri);
595                 return OC_STACK_NO_MEMORY;
596             }
597             temp->next = NULL;
598             temp->resourcetypename = OICStrdup(rt->value);
599             if (!ptr->rsrcType)
600             {
601                 ptr->rsrcType = temp;
602             }
603             else
604             {
605                 OCResourceType *type = ptr->rsrcType;
606                 while (type->next)
607                 {
608                     type = type->next;
609                 }
610                 type->next = temp;
611             }
612             rt = rt->next;
613         }
614
615         OCStringLL *itf = repPayload->setLinks->itf;
616         while (itf)
617         {
618             OCResourceInterface *temp = (OCResourceInterface *) OICCalloc(1, sizeof(OCResourceInterface));
619             if (!temp)
620             {
621                 OICFree(ptr->uri);
622
623                 return OC_STACK_NO_MEMORY;
624             }
625             temp->next = NULL;
626             temp->name = OICStrdup(itf->value);
627             if (!ptr->rsrcInterface)
628             {
629                 ptr->rsrcInterface = temp;
630             }
631             else
632             {
633                 OCResourceInterface *type = ptr->rsrcInterface;
634                 while (type->next)
635                 {
636                     type = type->next;
637                 }
638                 type->next = temp;
639             }
640             itf = itf->next;
641         }
642
643         ptr->resourceProperties = (OCResourceProperty) repPayload->tags->bitmap;
644
645         OCFreeCollectionResource(repPayload);
646         *payload = ptr;
647         return OC_STACK_OK;
648     }
649     else
650     {
651         OC_LOG_V(ERROR, TAG, "The resource type or interface type doe not exist \
652                              on the resource directory");
653     }
654     return OC_STACK_ERROR;
655 }
656 #endif
657
658 static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource)
659 {
660     if (!request || !resource)
661     {
662         return OC_STACK_INVALID_PARAM;
663     }
664
665     OCStackResult discoveryResult = OC_STACK_ERROR;
666
667     bool bMulticast    = false;     // Was the discovery request a multicast request?
668     OCPayload* payload = NULL;
669
670     OC_LOG(INFO, TAG, "Entering HandleVirtualResource");
671
672     OCVirtualResources virtualUriInRequest = GetTypeOfVirtualURI (request->resourceUrl);
673
674     // Step 1: Generate the response to discovery request
675     if (virtualUriInRequest == OC_WELL_KNOWN_URI)
676     {
677         char *filterOne = NULL;
678         char *filterTwo = NULL;
679
680         discoveryResult = getQueryParamsForFiltering (virtualUriInRequest, request->query,
681                 &filterOne, &filterTwo);
682
683         if (discoveryResult == OC_STACK_OK)
684         {
685             payload = (OCPayload*)OCDiscoveryPayloadCreate();
686
687             if(payload)
688             {
689                 ((OCDiscoveryPayload*)payload)->sid = (uint8_t*)OICCalloc(1, UUID_SIZE);
690                 memcpy(((OCDiscoveryPayload*)payload)->sid, OCGetServerInstanceID(), UUID_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             OC_LOG_V(ERROR, TAG, "Error (%d) parsing query.", discoveryResult);
737         }
738     }
739     else if (virtualUriInRequest == OC_DEVICE_URI)
740     {
741         const OicUuid_t* deviceId = OCGetServerInstanceID();
742         if (!deviceId)
743         {
744             discoveryResult = OC_STACK_ERROR;
745         }
746         else
747         {
748             payload = (OCPayload*) OCDevicePayloadCreate((const uint8_t*) &deviceId->id, 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         OC_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 != 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             OC_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             OC_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     OC_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         OC_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     OC_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         OC_LOG(INFO, TAG, "No observation requested");
929         ehFlag = OC_REQUEST_FLAG;
930     }
931     else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER && !collectionResource)
932     {
933         OC_LOG(INFO, TAG, "Observation registration requested");
934
935         ResourceObserver *obs = GetObserverUsingToken (request->requestToken,
936                                     request->tokenLength);
937
938         if (obs)
939         {
940             OC_LOG (INFO, TAG, "Observer with this token already present");
941             OC_LOG (INFO, TAG, "Possibly re-transmitted CON OBS request");
942             OC_LOG (INFO, TAG, "Not adding observer. Not responding to client");
943             OC_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             OC_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             OC_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         OC_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             OC_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             OC_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         OC_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             OC_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             OC_LOG(INFO, TAG, "Invalid Resource Determination");
1112             return OC_STACK_ERROR;
1113         }
1114     }
1115     return ret;
1116 }
1117
1118 void DeletePlatformInfo()
1119 {
1120     OC_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         OC_LOG_V(ERROR, TAG, "Failed to save platform info. errno(%d)", res);
1199     }
1200     else
1201     {
1202         OC_LOG(INFO, TAG, "Platform info saved.");
1203     }
1204
1205     return res;
1206 }
1207
1208 void DeleteDeviceInfo()
1209 {
1210     OC_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(OCGetServerInstanceID() == NULL)
1240     {
1241         OC_LOG(INFO, TAG, "Device ID generation failed");
1242         res =  OC_STACK_ERROR;
1243         goto exit;
1244     }
1245
1246     OC_LOG(INFO, TAG, "Device initialized successfully.");
1247     return OC_STACK_OK;
1248
1249 exit:
1250     DeleteDeviceInfo();
1251     return res;
1252 }