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