CBOR rebase onto master for merge/review
[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 "ocresource.h"
29 #include <string.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
39 #include "cacommon.h"
40 #include "cainterface.h"
41
42
43 /// Module Name
44 #define TAG PCF("ocresource")
45 #define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
46             {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
47
48 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
49              TAG, PCF(#arg " is NULL")); return (retVal); } }
50
51 extern OCResource *headResource;
52 static OCPlatformInfo savedPlatformInfo = {};
53 static OCDeviceInfo savedDeviceInfo = {};
54
55 static const char * VIRTUAL_RSRCS[] =
56 {
57     "/oic/res",
58     "/oic/d",
59     "/oic/p",
60     "/oic/res/types/d",
61     #ifdef WITH_PRESENCE
62     "/oic/ad"
63     #endif
64 };
65
66 //-----------------------------------------------------------------------------
67 // Default resource entity handler function
68 //-----------------------------------------------------------------------------
69 OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag,
70         OCEntityHandlerRequest * request, void* callbackParam)
71 {
72     //TODO ("Implement me!!!!");
73     // TODO:  remove silence unused param warnings
74     (void) flag;
75     (void) request;
76     (void) callbackParam;
77     return  OC_EH_OK; // Making sure that the Default EH and the Vendor EH have matching signatures
78 }
79
80 /* This method will retrieve the port at which the secure resource is hosted */
81 static OCStackResult GetSecurePortInfo(CATransportAdapter_t connType, uint16_t *port)
82 {
83     CAEndpoint_t* info = NULL;
84     uint32_t size = 0;
85     OCStackResult ret = OC_STACK_ERROR;
86
87     CAResult_t caResult = CAGetNetworkInformation(&info, &size);
88     if ((caResult == CA_STATUS_OK) && info && size)
89     {
90         while (size--)
91         {
92             if ((info[size].flags & CA_SECURE) && info[size].adapter == connType)
93             {
94                 if (info[size].adapter == CA_ADAPTER_IP)
95                 {
96                     *port = info[size].port;
97                     ret = OC_STACK_OK;
98                     break;
99                 }
100             }
101         }
102     }
103
104     OICFree(info);
105     return ret;
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     OC_LOG_V(INFO, TAG, PCF("Received query %s for param extraction"), query);
127
128     char *keyValuePair = strtok_r (query, OC_QUERY_SEPARATOR, &restOfQuery);
129
130     while(keyValuePair)
131     {
132         if (numKeyValuePairsParsed >= 2)
133         {
134             OC_LOG(ERROR, TAG, PCF("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             OC_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     OC_LOG_V(INFO, TAG, "Extracted params %s and %s.", *filterOne, *filterTwo);
163     return OC_STACK_OK;
164 }
165
166 static OCVirtualResources GetTypeOfVirtualURI(char *uriInRequest)
167 {
168     if (strcmp (uriInRequest, GetVirtualResourceUri(OC_WELL_KNOWN_URI)) == 0)
169     {
170         return OC_WELL_KNOWN_URI;
171     }
172     else if (strcmp (uriInRequest, GetVirtualResourceUri(OC_DEVICE_URI)) == 0)
173     {
174         return OC_DEVICE_URI;
175     }
176     else if (strcmp (uriInRequest, GetVirtualResourceUri(OC_PLATFORM_URI)) == 0)
177     {
178         return OC_PLATFORM_URI;
179     }
180
181     #ifdef WITH_PRESENCE
182     else
183     {
184         return OC_PRESENCE;
185     }
186     #endif
187 }
188
189 static OCStackResult getQueryParamsForFiltering (OCVirtualResources uri, char *query,
190                                             char **filterOne, char **filterTwo)
191 {
192     if(!filterOne || !filterTwo)
193     {
194         return OC_STACK_INVALID_PARAM;
195     }
196
197     *filterOne = NULL;
198     *filterTwo = NULL;
199
200     #ifdef WITH_PRESENCE
201     if (uri == OC_PRESENCE)
202     {
203         //Nothing needs to be done, except for pass a OC_PRESENCE query through as OC_STACK_OK.
204         OC_LOG(INFO, TAG, PCF("OC_PRESENCE Request for virtual resource."));
205         return OC_STACK_OK;
206     }
207     #endif
208
209     OCStackResult result = OC_STACK_OK;
210
211     if (query && *query)
212     {
213         result = ExtractFiltersFromQuery(query, filterOne, filterTwo);
214     }
215
216     return result;
217 }
218
219 OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
220                         OCDiscoveryPayload* payload, CATransportAdapter_t adapter )
221 {
222     if (!resourcePtr || !payload)
223     {
224         return OC_STACK_INVALID_PARAM;
225     }
226     uint16_t port = 0;
227     if (resourcePtr->resourceProperties & OC_SECURE)
228     {
229        if(GetSecurePortInfo (adapter, &port) != OC_STACK_OK)
230        {
231            port = 0;
232        }
233     }
234
235     OCDiscoveryPayloadAddResource(payload, resourcePtr, port);
236     return OC_STACK_OK;
237 }
238 const char * GetVirtualResourceUri( OCVirtualResources resource)
239 {
240     if (resource < OC_MAX_VIRTUAL_RESOURCES)
241     {
242         return VIRTUAL_RSRCS[resource];
243     }
244
245     return NULL;
246 }
247
248 bool IsVirtualResource(const char* resourceUri)
249 {
250     if(!resourceUri)
251     {
252         return false;
253     }
254
255     for (int i = 0; i < OC_MAX_VIRTUAL_RESOURCES; i++)
256     {
257         if (strcmp(resourceUri, GetVirtualResourceUri((OCVirtualResources)i)) == 0)
258         {
259             return true;
260         }
261     }
262     return false;
263 }
264
265 uint8_t IsCollectionResource (OCResource *resource)
266 {
267     if(!resource)
268     {
269         return 0;
270     }
271
272     for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
273     {
274         if (resource->rsrcResources[i])
275         {
276             return 1;
277         }
278     }
279     return 0;
280 }
281
282 OCResource *FindResourceByUri(const char* resourceUri)
283 {
284     if(!resourceUri)
285     {
286         return NULL;
287     }
288
289     OCResource * pointer = headResource;
290     while (pointer)
291     {
292         if (strcmp(resourceUri, pointer->uri) == 0)
293         {
294             return pointer;
295         }
296         pointer = pointer->next;
297     }
298     OC_LOG(INFO, TAG, PCF("Resource not found"));
299     return NULL;
300 }
301
302
303 OCStackResult DetermineResourceHandling (const OCServerRequest *request,
304                                          ResourceHandling *handling,
305                                          OCResource **resource)
306 {
307     if(!request || !handling || !resource)
308     {
309         return OC_STACK_INVALID_PARAM;
310     }
311
312     OC_LOG(INFO, TAG, PCF("Entering DetermineResourceHandling"));
313
314     const OCDevAddr *devAddr = &request->devAddr;
315
316     // Check if virtual resource
317     if (IsVirtualResource((const char*)request->resourceUrl))
318     {
319         *handling = OC_RESOURCE_VIRTUAL;
320         *resource = headResource;
321         return OC_STACK_OK;
322     }
323     if (strlen((const char*)(request->resourceUrl)) == 0)
324     {
325         // Resource URL not specified
326         *handling = OC_RESOURCE_NOT_SPECIFIED;
327         return OC_STACK_NO_RESOURCE;
328     }
329     else
330     {
331         OCResource *resourcePtr = NULL;
332         resourcePtr = FindResourceByUri((const char*)request->resourceUrl);
333         *resource = resourcePtr;
334         if (!resourcePtr)
335         {
336             if(defaultDeviceHandler)
337             {
338                 *handling = OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER;
339                 return OC_STACK_OK;
340             }
341
342             // Resource does not exist
343             // and default device handler does not exist
344             *handling = OC_RESOURCE_NOT_SPECIFIED;
345             return OC_STACK_NO_RESOURCE;
346         }
347
348         // secure resource will entertain only authorized requests
349         if ((resourcePtr->resourceProperties & OC_SECURE) && ((devAddr->flags & OC_FLAG_SECURE) == 0))
350         {
351             OC_LOG(ERROR, TAG, PCF("Un-authorized request. Ignoring"));
352             return OC_STACK_RESOURCE_ERROR;
353         }
354
355         if (IsCollectionResource (resourcePtr))
356         {
357             // Collection resource
358             if (resourcePtr->entityHandler != defaultResourceEHandler)
359             {
360                 *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER;
361                 return OC_STACK_OK;
362             }
363             else
364             {
365                 *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER;
366                 return OC_STACK_OK;
367             }
368         }
369         else
370         {
371             // Resource not a collection
372             if (resourcePtr->entityHandler != defaultResourceEHandler)
373             {
374                 *handling = OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER;
375                 return OC_STACK_OK;
376             }
377             else
378             {
379                 *handling = OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER;
380                 return OC_STACK_OK;
381             }
382         }
383     }
384 }
385
386 OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
387 {
388     OCStackResult result;
389
390     switch (ehResult)
391     {
392         case OC_EH_OK:
393             result = OC_STACK_OK;
394             break;
395         case OC_EH_SLOW:
396             result = OC_STACK_SLOW_RESOURCE;
397             break;
398         case OC_EH_ERROR:
399             result = OC_STACK_ERROR;
400             break;
401         case OC_EH_FORBIDDEN:
402             result = OC_STACK_RESOURCE_ERROR;
403             break;
404         case OC_EH_RESOURCE_CREATED:
405             result = OC_STACK_RESOURCE_CREATED;
406             break;
407         case OC_EH_RESOURCE_DELETED:
408             result = OC_STACK_RESOURCE_DELETED;
409             break;
410         case OC_EH_RESOURCE_NOT_FOUND:
411             result = OC_STACK_NO_RESOURCE;
412             break;
413         default:
414             result = OC_STACK_ERROR;
415     }
416
417     return result;
418 }
419
420 static bool resourceMatchesRTFilter(OCResource *resource, char *resourceTypeFilter)
421 {
422     if (!resource)
423     {
424         return false;
425     }
426
427     // Null or empty is analogous to no filter.
428     if (resourceTypeFilter == NULL || *resourceTypeFilter == 0)
429     {
430         return true;
431     }
432
433     OCResourceType *resourceTypePtr = resource->rsrcType;
434
435     while (resourceTypePtr)
436     {
437         if (strcmp (resourceTypePtr->resourcetypename, resourceTypeFilter) == 0)
438         {
439             return true;
440         }
441         resourceTypePtr = resourceTypePtr->next;
442     }
443
444     OC_LOG_V(INFO, TAG, PCF("%s does not contain rt=%s."), resource->uri, resourceTypeFilter);
445     return false;
446 }
447
448 static bool resourceMatchesIFFilter(OCResource *resource, char *interfaceFilter)
449 {
450     if (!resource)
451     {
452         return false;
453     }
454
455     // Null or empty is analogous to no filter.
456     if (interfaceFilter == NULL || *interfaceFilter == 0)
457     {
458         return true;
459     }
460
461     OCResourceInterface *interfacePtr = resource->rsrcInterface;
462
463     while (interfacePtr)
464     {
465         if (strcmp (interfacePtr->name, interfaceFilter) == 0)
466         {
467             return true;
468         }
469         interfacePtr = interfacePtr->next;
470     }
471
472     OC_LOG_V(INFO, TAG, PCF("%s does not contain if=%s."), resource->uri, interfaceFilter);
473     return false;
474 }
475
476 /*
477  * If the filters are null, they will be assumed to NOT be present
478  * and the resource will not be matched against them.
479  * Function will return true if all non null AND non empty filters passed in find a match.
480  */
481 static bool includeThisResourceInResponse(OCResource *resource,
482                                                  char *interfaceFilter,
483                                                  char *resourceTypeFilter)
484 {
485     if (!resource)
486     {
487         OC_LOG(ERROR, TAG, PCF("Invalid resource"));
488         return false;
489     }
490
491     if ( !(resource->resourceProperties & OC_ACTIVE) ||
492          !(resource->resourceProperties & OC_DISCOVERABLE))
493     {
494         OC_LOG_V(INFO, TAG, PCF("%s not ACTIVE or DISCOVERABLE"), resource->uri);
495         return false;
496     }
497
498     return resourceMatchesIFFilter(resource, interfaceFilter) &&
499            resourceMatchesRTFilter(resource, resourceTypeFilter);
500
501 }
502
503 OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCResource *resource,
504                                 OCPayload *discoveryPayload)
505 {
506     OCEntityHandlerResponse response = {};
507
508     response.ehResult = OC_EH_OK;
509     response.payload = discoveryPayload;
510     response.persistentBufferFlag = 0;
511     response.requestHandle = (OCRequestHandle) request;
512     response.resourceHandle = (OCResourceHandle) resource;
513
514     return OCDoResponse(&response);
515 }
516
517 static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource)
518 {
519     if (!request || !resource)
520     {
521         return OC_STACK_INVALID_PARAM;
522     }
523
524     OCStackResult discoveryResult = OC_STACK_ERROR;
525     OCPayload* payload = NULL;
526     char *filterOne = NULL;
527     char *filterTwo = NULL;
528
529     OC_LOG(INFO, TAG, PCF("Entering HandleVirtualResource"));
530
531     OCVirtualResources virtualUriInRequest = GetTypeOfVirtualURI (request->resourceUrl);
532
533
534     if (virtualUriInRequest == OC_WELL_KNOWN_URI)
535     {
536         discoveryResult = getQueryParamsForFiltering (virtualUriInRequest, request->query,
537                                                             &filterOne, &filterTwo);
538         if (discoveryResult != OC_STACK_OK)
539         {
540             OC_LOG_V(ERROR, TAG, "Error (%d) validating query.\n", discoveryResult);
541             return discoveryResult;
542         }
543         payload = (OCPayload*)OCDiscoveryPayloadCreate();
544
545         if(!payload)
546         {
547             return OC_STACK_NO_MEMORY;
548         }
549
550
551         for(;resource && discoveryResult == OC_STACK_OK; resource = resource->next)
552         {
553             if(includeThisResourceInResponse(resource, filterOne, filterTwo))
554             {
555                 discoveryResult = BuildVirtualResourceResponse(resource,
556                     (OCDiscoveryPayload*)payload,
557                     (CATransportAdapter_t)request->devAddr.adapter);
558             }
559         }
560     }
561     else if (virtualUriInRequest == OC_DEVICE_URI)
562     {
563             payload = (OCPayload*)OCDevicePayloadCreate(GetVirtualResourceUri(OC_DEVICE_URI),
564                         OCGetServerInstanceID(), savedDeviceInfo.deviceName,
565                         OC_SPEC_VERSION, OC_DATA_MODEL_VERSION);
566             if (!payload)
567             {
568                 discoveryResult = OC_STACK_NO_MEMORY;
569             }
570     }
571     else if (virtualUriInRequest == OC_PLATFORM_URI)
572     {
573             OCPlatformPayload* payload = OCPlatformPayloadCreate(
574                     GetVirtualResourceUri(OC_PLATFORM_URI),
575                     &savedPlatformInfo);
576             if (!payload)
577             {
578                 discoveryResult = OC_STACK_NO_MEMORY;
579             }
580     }
581
582     #ifdef WITH_PRESENCE
583     else
584     {
585         if(resource->resourceProperties & OC_ACTIVE)
586         {
587             discoveryResult = SendPresenceNotification(resource->rsrcType,
588                                                 OC_PRESENCE_TRIGGER_CHANGE);
589         }
590     }
591     #endif
592
593     // Presence uses observer notification api to respond via SendPresenceNotification.
594     if (virtualUriInRequest != OC_PRESENCE)
595     {
596         if(discoveryResult == OC_STACK_OK)
597         {
598             discoveryResult = SendNonPersistantDiscoveryResponse(request, resource,
599                                                         payload);
600             OCPayloadDestroy(payload);
601         }
602         else
603         {
604             OC_LOG_V(ERROR, TAG, "Error (%d) building (%d)  discovery response. "\
605                         "Not responding to request.", discoveryResult, virtualUriInRequest);
606         }
607     }
608
609     return discoveryResult;
610 }
611
612 static OCStackResult
613 HandleDefaultDeviceEntityHandler (OCServerRequest *request)
614 {
615     if(!request)
616     {
617         return OC_STACK_INVALID_PARAM;
618     }
619
620     OCStackResult result = OC_STACK_OK;
621     OCEntityHandlerResult ehResult = OC_EH_ERROR;
622     OCEntityHandlerRequest ehRequest = {};
623
624     OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithDefaultDeviceEntityHandler"));
625     result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
626             request->method, (OCResourceHandle) NULL, request->query,
627             request->payload, request->payloadSize,
628             request->numRcvdVendorSpecificHeaderOptions,
629             request->rcvdVendorSpecificHeaderOptions,
630             (OCObserveAction)request->observationOption, (OCObservationId)0);
631     VERIFY_SUCCESS(result, OC_STACK_OK);
632
633     // At this point we know for sure that defaultDeviceHandler exists
634     ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
635                                   (char*) request->resourceUrl, defaultDeviceHandlerCallbackParameter);
636     if(ehResult == OC_EH_SLOW)
637     {
638         OC_LOG(INFO, TAG, PCF("This is a slow resource"));
639         request->slowFlag = 1;
640     }
641     else if(ehResult == OC_EH_ERROR)
642     {
643         FindAndDeleteServerRequest(request);
644     }
645     result = EntityHandlerCodeToOCStackCode(ehResult);
646 exit:
647     return result;
648 }
649
650 static OCStackResult
651 HandleResourceWithEntityHandler (OCServerRequest *request,
652                                  OCResource *resource,
653                                  uint8_t collectionResource)
654 {
655     if(!request || ! resource)
656     {
657         return OC_STACK_INVALID_PARAM;
658     }
659
660     OCStackResult result = OC_STACK_ERROR;
661     OCEntityHandlerResult ehResult = OC_EH_ERROR;
662     OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
663     ResourceObserver *resObs = NULL;
664
665     OCEntityHandlerRequest ehRequest = {};
666
667     OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithEntityHandler"));
668
669     result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
670             request->method, (OCResourceHandle) resource, request->query,
671             request->payload, request->payloadSize, request->numRcvdVendorSpecificHeaderOptions,
672             request->rcvdVendorSpecificHeaderOptions,
673             (OCObserveAction)request->observationOption, 0);
674     VERIFY_SUCCESS(result, OC_STACK_OK);
675
676     if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
677     {
678         OC_LOG(INFO, TAG, PCF("No observation requested"));
679         ehFlag = OC_REQUEST_FLAG;
680     }
681     else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER && !collectionResource)
682     {
683         OC_LOG(INFO, TAG, PCF("Observation registration requested"));
684
685         result = GenerateObserverId(&ehRequest.obsInfo.obsId);
686         VERIFY_SUCCESS(result, OC_STACK_OK);
687
688         result = AddObserver ((const char*)(request->resourceUrl),
689                 (const char *)(request->query),
690                 ehRequest.obsInfo.obsId, request->requestToken, request->tokenLength,
691                 resource, request->qos,
692                 &request->devAddr);
693
694         if(result == OC_STACK_OK)
695         {
696             OC_LOG(INFO, TAG, PCF("Added observer successfully"));
697             request->observeResult = OC_STACK_OK;
698             ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
699         }
700         else
701         {
702             result = OC_STACK_OK;
703
704             // The error in observeResult for the request will be used when responding to this
705             // request by omitting the observation option/sequence number.
706             request->observeResult = OC_STACK_ERROR;
707             OC_LOG(ERROR, TAG, PCF("Observer Addition failed"));
708             ehFlag = OC_REQUEST_FLAG;
709         }
710
711     }
712     else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER &&
713             !collectionResource)
714     {
715         OC_LOG(INFO, TAG, PCF("Deregistering observation requested"));
716
717         resObs = GetObserverUsingToken (request->requestToken, request->tokenLength);
718
719         if (NULL == resObs)
720         {
721             // Stack does not contain this observation request
722             // Either token is incorrect or observation list is corrupted
723             result = OC_STACK_ERROR;
724             goto exit;
725         }
726         ehRequest.obsInfo.obsId = resObs->observeId;
727         ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
728
729         result = DeleteObserverUsingToken (request->requestToken, request->tokenLength);
730
731         if(result == OC_STACK_OK)
732         {
733             OC_LOG(INFO, TAG, PCF("Removed observer successfully"));
734             request->observeResult = OC_STACK_OK;
735         }
736         else
737         {
738             result = OC_STACK_OK;
739             request->observeResult = OC_STACK_ERROR;
740             OC_LOG(ERROR, TAG, PCF("Observer Removal failed"));
741         }
742     }
743     else
744     {
745         result = OC_STACK_ERROR;
746         goto exit;
747     }
748
749     ehResult = resource->entityHandler(ehFlag, &ehRequest, resource->entityHandlerCallbackParam);
750     if(ehResult == OC_EH_SLOW)
751     {
752         OC_LOG(INFO, TAG, PCF("This is a slow resource"));
753         request->slowFlag = 1;
754     }
755     else if(ehResult == OC_EH_ERROR)
756     {
757         FindAndDeleteServerRequest(request);
758     }
759     result = EntityHandlerCodeToOCStackCode(ehResult);
760 exit:
761     return result;
762 }
763
764 static OCStackResult
765 HandleCollectionResourceDefaultEntityHandler (OCServerRequest *request,
766                                               OCResource *resource)
767 {
768     if(!request || !resource)
769     {
770         return OC_STACK_INVALID_PARAM;
771     }
772
773     OCStackResult result = OC_STACK_ERROR;
774     OCEntityHandlerRequest ehRequest = {};
775
776     result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
777             request->method, (OCResourceHandle) resource, request->query,
778             request->payload, request->payloadSize, request->numRcvdVendorSpecificHeaderOptions,
779             request->rcvdVendorSpecificHeaderOptions,
780             (OCObserveAction)request->observationOption, (OCObservationId) 0);
781     if(result != OC_STACK_OK)
782     {
783         return result;
784     }
785
786     return (DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest));
787 }
788
789 OCStackResult
790 ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request)
791 {
792     OCStackResult ret = OC_STACK_OK;
793
794     switch (resHandling)
795     {
796         case OC_RESOURCE_VIRTUAL:
797         {
798             ret = HandleVirtualResource (request, resource);
799             break;
800         }
801         case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER:
802         {
803             ret = HandleDefaultDeviceEntityHandler(request);
804             break;
805         }
806         case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
807         {
808             OC_LOG(INFO, TAG, PCF("OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER"));
809             return OC_STACK_ERROR;
810         }
811         case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
812         {
813             ret = HandleResourceWithEntityHandler (request, resource, 0);
814             break;
815         }
816         case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
817         {
818             ret = HandleResourceWithEntityHandler (request, resource, 1);
819             break;
820         }
821         case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
822         {
823             ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
824             break;
825         }
826         case OC_RESOURCE_NOT_SPECIFIED:
827         {
828             ret = OC_STACK_NO_RESOURCE;
829             break;
830         }
831         default:
832         {
833             OC_LOG(INFO, TAG, PCF("Invalid Resource Determination"));
834             return OC_STACK_ERROR;
835         }
836     }
837     return ret;
838 }
839
840 void DeletePlatformInfo()
841 {
842     OC_LOG(INFO, TAG, PCF("Deleting platform info."));
843
844     OICFree(savedPlatformInfo.platformID);
845     savedPlatformInfo.platformID = NULL;
846
847     OICFree(savedPlatformInfo.manufacturerName);
848     savedPlatformInfo.manufacturerName = NULL;
849
850     OICFree(savedPlatformInfo.manufacturerUrl);
851     savedPlatformInfo.manufacturerUrl = NULL;
852
853     OICFree(savedPlatformInfo.modelNumber);
854     savedPlatformInfo.modelNumber = NULL;
855
856     OICFree(savedPlatformInfo.dateOfManufacture);
857     savedPlatformInfo.dateOfManufacture = NULL;
858
859     OICFree(savedPlatformInfo.platformVersion);
860     savedPlatformInfo.platformVersion = NULL;
861
862     OICFree(savedPlatformInfo.operatingSystemVersion);
863     savedPlatformInfo.operatingSystemVersion = NULL;
864
865     OICFree(savedPlatformInfo.hardwareVersion);
866     savedPlatformInfo.hardwareVersion = NULL;
867
868     OICFree(savedPlatformInfo.firmwareVersion);
869     savedPlatformInfo.firmwareVersion = NULL;
870
871     OICFree(savedPlatformInfo.supportUrl);
872     savedPlatformInfo.supportUrl = NULL;
873
874     OICFree(savedPlatformInfo.systemTime);
875     savedPlatformInfo.systemTime = NULL;
876 }
877
878 static OCStackResult DeepCopyPlatFormInfo(OCPlatformInfo info)
879 {
880     savedPlatformInfo.platformID = OICStrdup(info.platformID);
881     savedPlatformInfo.manufacturerName = OICStrdup(info.manufacturerName);
882     savedPlatformInfo.manufacturerUrl = OICStrdup(info.manufacturerUrl);
883     savedPlatformInfo.modelNumber = OICStrdup(info.modelNumber);
884     savedPlatformInfo.dateOfManufacture = OICStrdup(info.dateOfManufacture);
885     savedPlatformInfo.platformVersion = OICStrdup(info.platformVersion);
886     savedPlatformInfo.operatingSystemVersion = OICStrdup(info.operatingSystemVersion);
887     savedPlatformInfo.hardwareVersion = OICStrdup(info.hardwareVersion);
888     savedPlatformInfo.firmwareVersion = OICStrdup(info.firmwareVersion);
889     savedPlatformInfo.supportUrl = OICStrdup(info.supportUrl);
890     savedPlatformInfo.systemTime = OICStrdup(info.systemTime);
891
892     if ((!savedPlatformInfo.platformID && info.platformID)||
893         (!savedPlatformInfo.manufacturerName && info.manufacturerName)||
894         (!savedPlatformInfo.manufacturerUrl && info.manufacturerUrl)||
895         (!savedPlatformInfo.modelNumber && info.modelNumber)||
896         (!savedPlatformInfo.dateOfManufacture && info.dateOfManufacture)||
897         (!savedPlatformInfo.platformVersion && info.platformVersion)||
898         (!savedPlatformInfo.operatingSystemVersion && info.operatingSystemVersion)||
899         (!savedPlatformInfo.hardwareVersion && info.hardwareVersion)||
900         (!savedPlatformInfo.firmwareVersion && info.firmwareVersion)||
901         (!savedPlatformInfo.supportUrl && info.supportUrl)||
902         (!savedPlatformInfo.systemTime && info.systemTime))
903     {
904         DeletePlatformInfo();
905         return OC_STACK_INVALID_PARAM;
906     }
907
908     return OC_STACK_OK;
909
910 }
911
912 OCStackResult SavePlatformInfo(OCPlatformInfo info)
913 {
914     DeletePlatformInfo();
915
916     OCStackResult res = DeepCopyPlatFormInfo(info);
917
918     if (res != OC_STACK_OK)
919     {
920         OC_LOG_V(ERROR, TAG, PCF("Failed to save platform info. errno(%d)"), res);
921     }
922     else
923     {
924         OC_LOG(ERROR, TAG, PCF("Platform info saved."));
925     }
926
927     return res;
928 }
929
930 void DeleteDeviceInfo()
931 {
932     OC_LOG(INFO, TAG, PCF("Deleting device info."));
933
934     OICFree(savedDeviceInfo.deviceName);
935     savedDeviceInfo.deviceName = NULL;
936 }
937
938 static OCStackResult DeepCopyDeviceInfo(OCDeviceInfo info)
939 {
940     savedDeviceInfo.deviceName = OICStrdup(info.deviceName);
941
942     if(!savedDeviceInfo.deviceName && info.deviceName)
943     {
944         DeleteDeviceInfo();
945         return OC_STACK_NO_MEMORY;
946     }
947
948     return OC_STACK_OK;
949 }
950
951 OCStackResult SaveDeviceInfo(OCDeviceInfo info)
952 {
953     OCStackResult res = OC_STACK_OK;
954
955     DeleteDeviceInfo();
956
957     res = DeepCopyDeviceInfo(info);
958
959     VERIFY_SUCCESS(res, OC_STACK_OK);
960
961     if(OCGetServerInstanceID() == NULL)
962     {
963         OC_LOG(INFO, TAG, PCF("Device ID generation failed"));
964         res =  OC_STACK_ERROR;
965         goto exit;
966     }
967
968     OC_LOG(INFO, TAG, PCF("Device initialized successfully."));
969     return OC_STACK_OK;
970
971     exit:
972         DeleteDeviceInfo();
973         return res;
974
975 }