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