Removed duplicate code in ocresource.c::HandleVirtualResource.
[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 "ocstack.h"
30 #include "ocstackconfig.h"
31 #include "ocstackinternal.h"
32 #include "ocresourcehandler.h"
33 #include "ocobserve.h"
34 #include "occollection.h"
35 #include "ocmalloc.h"
36 #include "logger.h"
37 #include "cJSON.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 cJSON *savedDeviceInfo = NULL;
53
54 static const char * VIRTUAL_RSRCS[] =
55 {
56        "/oc/core",
57        "/oc/core/d",
58        "/oc/core/types/d",
59        #ifdef WITH_PRESENCE
60        "/oc/presence"
61        #endif
62 };
63
64 //-----------------------------------------------------------------------------
65 // Default resource entity handler function
66 //-----------------------------------------------------------------------------
67 OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag,
68         OCEntityHandlerRequest * request)
69 {
70     //TODO ("Implement me!!!!");
71     // TODO:  remove silence unused param warnings
72     (void) flag;
73     (void) request;
74     return  OC_EH_OK; // Making sure that the Default EH and the Vendor EH have matching signatures
75 }
76
77 /* This method will retrieve the port at which the secure resource is hosted */
78 static OCStackResult GetSecurePortInfo(CAConnectivityType_t connType, uint16_t *port)
79 {
80     CALocalConnectivity_t* info = NULL;
81     uint32_t size = 0;
82     OCStackResult ret = OC_STACK_ERROR;
83
84     CAResult_t caResult = CAGetNetworkInformation(&info, &size);
85     if ((caResult == CA_STATUS_OK) && info && size)
86     {
87         while (size--)
88         {
89             if (info[size].isSecured && info[size].type == connType)
90             {
91                 if (info[size].type == CA_ETHERNET ||
92                     info[size].type == CA_WIFI)
93                 {
94                     *port = info[size].addressInfo.IP.port;
95                     ret = OC_STACK_OK;
96                     break;
97                 }
98             }
99         }
100     }
101
102     OCFree(info);
103     return ret;
104 }
105
106 static OCStackResult ValidateUrlQuery (char *url, char *query,
107                                 uint8_t *filterOn, char **filterValue)
108 {
109     if(!filterOn || !filterValue)
110     {
111         return OC_STACK_INVALID_PARAM;
112     }
113
114     char *filterParam = NULL;
115
116     OC_LOG(INFO, TAG, PCF("Entering ValidateUrlQuery"));
117     if (!url)
118     {
119         return OC_STACK_INVALID_URI;
120     }
121
122     if (strcmp ((char *)url, GetVirtualResourceUri(OC_WELL_KNOWN_URI)) == 0 ||
123                 strcmp ((char *)url, GetVirtualResourceUri(OC_DEVICE_URI)) == 0)
124     {
125         *filterOn = STACK_RES_DISCOVERY_NOFILTER;
126         if (query && *query)
127         {
128             char* strTokPtr = NULL;
129             filterParam = strtok_r((char *)query, "=", &strTokPtr);
130             *filterValue = strtok_r(NULL, " ", &strTokPtr);
131
132             if (!(*filterValue) || ! filterParam)
133             {
134                 return OC_STACK_INVALID_QUERY;
135             }
136             else if (strcmp (filterParam, OC_RSRVD_INTERFACE) == 0)
137             {
138                 // Resource discovery with interface filter
139                 *filterOn = STACK_RES_DISCOVERY_IF_FILTER;
140             }
141             else if (strcmp (filterParam, OC_RSRVD_RESOURCE_TYPE) == 0)
142             {
143                 // Resource discovery with resource type filter
144                 *filterOn = STACK_RES_DISCOVERY_RT_FILTER;
145             }
146             else if (strcmp (filterParam, OC_RSRVD_DEVICE_ID) == 0)
147             {
148                 //Device ID filter
149                 *filterOn = STACK_DEVICE_DISCOVERY_DI_FILTER;
150             }
151             else if (strcmp (filterParam, OC_RSRVD_DEVICE_NAME) == 0)
152             {
153                 //Device Name filter
154                 *filterOn = STACK_DEVICE_DISCOVERY_DN_FILTER;
155             }
156             else
157             {
158                 // Other filter types not supported
159                 return OC_STACK_INVALID_QUERY;
160             }
161         }
162     }
163     #ifdef WITH_PRESENCE
164     else if (strcmp((char *)url, GetVirtualResourceUri(OC_PRESENCE)) == 0)
165     {
166         //Nothing needs to be done, except for pass a OC_PRESENCE query through as OC_STACK_OK.
167         OC_LOG(INFO, TAG, PCF("OC_PRESENCE Request"));
168         *filterOn = STACK_RES_DISCOVERY_NOFILTER;
169     }
170     #endif
171     else
172     {
173         // Other URIs not yet supported
174         return OC_STACK_INVALID_URI;
175     }
176     OC_LOG(INFO, TAG, PCF("Exiting ValidateUrlQuery"));
177     return OC_STACK_OK;
178 }
179
180
181 OCStackResult
182 BuildVirtualResourceResponse(const OCResource *resourcePtr, uint8_t filterOn,
183                        const char *filterValue, char *out, uint16_t *remaining,
184                        CAConnectivityType_t connType )
185 {
186     if(!resourcePtr || !out  || !remaining)
187     {
188         return OC_STACK_INVALID_PARAM;
189     }
190
191     OCResourceType *resourceTypePtr = NULL;
192     OCResourceInterface *interfacePtr = NULL;
193     cJSON *resObj = NULL;
194     cJSON *propObj = NULL;
195     cJSON *rtArray = NULL;
196     char *jsonStr = NULL;
197     uint8_t encodeRes = 0;
198     OCStackResult ret = OC_STACK_OK;
199     uint16_t jsonLen = 0;
200
201     OC_LOG(INFO, TAG, PCF("Entering BuildVirtualResourceResponse"));
202     resObj = cJSON_CreateObject();
203
204     if (resourcePtr)
205     {
206         encodeRes = 0;
207         if ((filterOn == STACK_RES_DISCOVERY_RT_FILTER) && filterValue)
208         {
209             resourceTypePtr = resourcePtr->rsrcType;
210             while (resourceTypePtr)
211             {
212                 if (strcmp (resourceTypePtr->resourcetypename, filterValue) == 0)
213                 {
214                     encodeRes = 1;
215                     break;
216                 }
217                 resourceTypePtr = resourceTypePtr->next;
218             }
219         }
220         else if ((filterOn == STACK_RES_DISCOVERY_IF_FILTER) && filterValue)
221         {
222             interfacePtr = resourcePtr->rsrcInterface;
223             while (interfacePtr)
224             {
225                 if (strcmp (interfacePtr->name, filterValue) == 0)
226                 {
227                     encodeRes = 1;
228                     break;
229                 }
230                 interfacePtr = interfacePtr->next;
231             }
232         }
233         else if (filterOn == STACK_RES_DISCOVERY_NOFILTER)
234         {
235             encodeRes = 1;
236         }
237         else
238         {
239             //TODO: Unsupported query filter
240             return OC_STACK_INVALID_QUERY;
241         }
242
243         if (encodeRes)
244         {
245             // Add URIs
246             cJSON_AddItemToObject (resObj, OC_RSRVD_HREF, cJSON_CreateString(resourcePtr->uri));
247
248             // Add server instance id
249             cJSON_AddItemToObject (resObj,
250                                    OC_RSRVD_SERVER_INSTANCE_ID,
251                                    cJSON_CreateString(OCGetServerInstanceIDString()));
252
253             cJSON_AddItemToObject (resObj, OC_RSRVD_PROPERTY, propObj = cJSON_CreateObject());
254             // Add resource types
255             cJSON_AddItemToObject (propObj, OC_RSRVD_RESOURCE_TYPE, rtArray = cJSON_CreateArray());
256             resourceTypePtr = resourcePtr->rsrcType;
257             while (resourceTypePtr)
258             {
259                 cJSON_AddItemToArray (rtArray,
260                                       cJSON_CreateString(resourceTypePtr->resourcetypename));
261                 resourceTypePtr = resourceTypePtr->next;
262             }
263             // Add interface types
264             cJSON_AddItemToObject (propObj, OC_RSRVD_INTERFACE, rtArray = cJSON_CreateArray());
265             interfacePtr = resourcePtr->rsrcInterface;
266             while (interfacePtr)
267             {
268                 cJSON_AddItemToArray (rtArray, cJSON_CreateString(interfacePtr->name));
269                 interfacePtr = interfacePtr->next;
270             }
271             // If resource is observable, set observability flag.
272             // Resources that are not observable will not have the flag.
273             if (resourcePtr->resourceProperties & OC_OBSERVABLE)
274             {
275                 cJSON_AddItemToObject (propObj, OC_RSRVD_OBSERVABLE,
276                                        cJSON_CreateNumber(OC_RESOURCE_OBSERVABLE));
277             }
278             // Set secure flag for secure resources
279             if (resourcePtr->resourceProperties & OC_SECURE)
280             {
281                 cJSON_AddNumberToObject (propObj, OC_RSRVD_SECURE, OC_RESOURCE_SECURE);
282                 //Set the IP port also as secure resources are hosted on a different port
283                 uint16_t port = 0;
284                 if (GetSecurePortInfo (connType, &port) == OC_STACK_OK)
285                 {
286                     cJSON_AddNumberToObject (propObj, OC_RSRVD_HOSTING_PORT, port);
287                 }
288             }
289
290         }
291     }
292     jsonStr = cJSON_PrintUnformatted (resObj);
293
294     jsonLen = strlen(jsonStr);
295     if (jsonLen < *remaining)
296     {
297         strcpy(out, jsonStr);
298         *remaining = *remaining - jsonLen;
299     }
300     else
301     {
302         ret = OC_STACK_ERROR;
303     }
304     cJSON_Delete (resObj);
305     OCFree (jsonStr);
306
307     OC_LOG(INFO, TAG, PCF("Exiting BuildVirtualResourceResponse"));
308     return ret;
309 }
310
311 OCStackResult BuildVirtualResourceResponseForDevice(uint8_t filterOn, char *filterValue,
312                                                     char *out, uint16_t *remaining)
313 {
314     if(!out || !remaining)
315     {
316         return OC_STACK_INVALID_PARAM;
317     }
318
319     OCStackResult ret = OC_STACK_ERROR;
320
321     if (savedDeviceInfo != NULL)
322     {
323         char *jsonStr = NULL;
324         uint16_t jsonLen = 0;
325         cJSON *repObj = cJSON_GetObjectItem(savedDeviceInfo, OC_RSRVD_REPRESENTATION);
326
327         OC_LOG(INFO, TAG, PCF("Entering BuildVirtualResourceResponseForDevice"));
328
329         if ((filterOn == STACK_DEVICE_DISCOVERY_DI_FILTER) && filterValue)
330         {
331             if((cJSON_GetObjectItem(repObj,OC_RSRVD_DEVICE_ID) != NULL) &&
332                     strcmp(cJSON_GetObjectItem(repObj,OC_RSRVD_DEVICE_ID)->valuestring, filterValue)
333                     == 0)
334             {
335                 ret = OC_STACK_OK;
336             }
337         }
338         else if ((filterOn == STACK_DEVICE_DISCOVERY_DN_FILTER) && filterValue)
339         {
340             if((cJSON_GetObjectItem(repObj,OC_RSRVD_DEVICE_NAME) != NULL) &&
341                     strcmp(cJSON_GetObjectItem(repObj,OC_RSRVD_DEVICE_NAME)->valuestring,
342                         filterValue) == 0)
343             {
344                 ret = OC_STACK_OK;
345             }
346         }
347         else if (filterOn == STACK_RES_DISCOVERY_NOFILTER)
348         {
349             ret = OC_STACK_OK;
350         }
351         else
352         {
353             ret = OC_STACK_INVALID_QUERY;
354         }
355
356         if (ret == OC_STACK_OK)
357         {
358             jsonStr = cJSON_PrintUnformatted (savedDeviceInfo);
359
360             if(jsonStr)
361             {
362                 jsonLen = strlen(jsonStr);
363
364                 if (jsonLen < *remaining)
365                 {
366                     strncpy(out, jsonStr, (jsonLen + 1));
367                     *remaining = *remaining - jsonLen;
368                     ret = OC_STACK_OK;
369                 }
370                 else
371                 {
372                     ret = OC_STACK_ERROR;
373                 }
374
375                 OCFree(jsonStr);
376             }
377             else
378             {
379                 ret = OC_STACK_ERROR;
380             }
381         }
382         else
383         {
384             ret = OC_STACK_INVALID_DEVICE_INFO;
385         }
386     }
387     else
388     {
389         //error so that stack won't respond with empty payload
390         ret = OC_STACK_INVALID_DEVICE_INFO;
391     }
392
393     OC_LOG(INFO, TAG, PCF("Exiting BuildVirtualResourceResponseForDevice"));
394     return ret;
395 }
396
397 const char * GetVirtualResourceUri( OCVirtualResources resource)
398 {
399     if (resource < OC_MAX_VIRTUAL_RESOURCES)
400     {
401         return VIRTUAL_RSRCS[resource];
402     }
403
404     return NULL;
405 }
406
407 bool IsVirtualResource(const char* resourceUri)
408 {
409     if(!resourceUri)
410     {
411         return false;
412     }
413
414     for (int i = 0; i < OC_MAX_VIRTUAL_RESOURCES; i++)
415     {
416         if (strcmp(resourceUri, GetVirtualResourceUri((OCVirtualResources)i)) == 0)
417         {
418             return true;
419         }
420     }
421     return false;
422 }
423
424 uint8_t IsCollectionResource (OCResource *resource)
425 {
426     if(!resource)
427     {
428         return 0;
429     }
430
431     for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
432     {
433         if (resource->rsrcResources[i])
434         {
435             return 1;
436         }
437     }
438     return 0;
439 }
440
441 OCResource *FindResourceByUri(const char* resourceUri)
442 {
443     if(!resourceUri)
444     {
445         return NULL;
446     }
447
448     OCResource * pointer = headResource;
449     while (pointer)
450     {
451         if (strcmp(resourceUri, pointer->uri) == 0)
452         {
453             return pointer;
454         }
455         pointer = pointer->next;
456     }
457     OC_LOG(INFO, TAG, PCF("Resource not found"));
458     return NULL;
459 }
460
461
462 OCStackResult DetermineResourceHandling (const OCServerRequest *request,
463                                          ResourceHandling *handling,
464                                          OCResource **resource)
465 {
466     if(!request || !handling || !resource)
467     {
468         return OC_STACK_INVALID_PARAM;
469     }
470
471     OC_LOG(INFO, TAG, PCF("Entering DetermineResourceHandling"));
472
473     // Check if virtual resource
474     if (IsVirtualResource((const char*)request->resourceUrl))
475     {
476         *handling = OC_RESOURCE_VIRTUAL;
477         *resource = headResource;
478         return OC_STACK_OK;
479     }
480     if (NULL == request->resourceUrl || (strlen((const char*)(request->resourceUrl)) == 0))
481     {
482         // Resource URL not specified
483         *handling = OC_RESOURCE_NOT_SPECIFIED;
484         return OC_STACK_NO_RESOURCE;
485     }
486     else
487     {
488         OCResource *resourcePtr = NULL;
489         resourcePtr = FindResourceByUri((const char*)request->resourceUrl);
490         *resource = resourcePtr;
491         if (!resourcePtr)
492         {
493             if(defaultDeviceHandler)
494             {
495                 *handling = OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER;
496                 return OC_STACK_OK;
497             }
498
499             // Resource does not exist
500             // and default device handler does not exist
501             *handling = OC_RESOURCE_NOT_SPECIFIED;
502             return OC_STACK_NO_RESOURCE;
503         }
504
505         // secure resource will entertain only authorized requests
506         if ((resourcePtr->resourceProperties & OC_SECURE) && (request->secured == 0))
507         {
508             OC_LOG(ERROR, TAG, PCF("Un-authorized request. Ignoring"));
509             return OC_STACK_RESOURCE_ERROR;
510         }
511
512         if (IsCollectionResource (resourcePtr))
513         {
514             // Collection resource
515             if (resourcePtr->entityHandler != defaultResourceEHandler)
516             {
517                 *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER;
518                 return OC_STACK_OK;
519             }
520             else
521             {
522                 *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER;
523                 return OC_STACK_OK;
524             }
525         }
526         else
527         {
528             // Resource not a collection
529             if (resourcePtr->entityHandler != defaultResourceEHandler)
530             {
531                 *handling = OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER;
532                 return OC_STACK_OK;
533             }
534             else
535             {
536                 *handling = OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER;
537                 return OC_STACK_OK;
538             }
539         }
540     }
541 }
542
543 OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
544 {
545     OCStackResult result;
546
547     switch (ehResult)
548     {
549         case OC_EH_OK:
550             result = OC_STACK_OK;
551             break;
552         case OC_EH_SLOW:
553             result = OC_STACK_SLOW_RESOURCE;
554             break;
555         case OC_EH_ERROR:
556             result = OC_STACK_ERROR;
557             break;
558         case OC_EH_FORBIDDEN:
559             result = OC_STACK_RESOURCE_ERROR;
560             break;
561         case OC_EH_RESOURCE_CREATED:
562             result = OC_STACK_RESOURCE_CREATED;
563             break;
564         case OC_EH_RESOURCE_DELETED:
565             result = OC_STACK_RESOURCE_DELETED;
566             break;
567         case OC_EH_RESOURCE_NOT_FOUND:
568             result = OC_STACK_NO_RESOURCE;
569             break;
570         default:
571             result = OC_STACK_ERROR;
572     }
573
574     return result;
575 }
576
577 static OCStackResult
578 HandleVirtualResource (OCServerRequest *request, OCResource* resource)
579 {
580     if(!request || !resource)
581     {
582         return OC_STACK_INVALID_PARAM;
583     }
584
585     OCStackResult result = OC_STACK_ERROR;
586     char *filterValue = NULL;
587     uint8_t filterOn = 0;
588     uint16_t remaining = 0;
589     char * ptr = NULL;
590     uint8_t firstLoopDone = 0;
591     char discoveryResBuf[MAX_RESPONSE_LENGTH] = {};
592
593     OC_LOG(INFO, TAG, PCF("Entering HandleVirtualResource"));
594
595     result = ValidateUrlQuery (request->resourceUrl,
596             request->query, &filterOn,
597             &filterValue);
598
599     if (result == OC_STACK_OK)
600     {
601         if (strcmp ((char *)request->resourceUrl, GetVirtualResourceUri(OC_WELL_KNOWN_URI)) == 0)
602         {
603             ptr = discoveryResBuf;
604             remaining = MAX_RESPONSE_LENGTH;
605
606             // Check if valid resource and enough space in buffer for atleast
607             // the null character.
608             while(resource && (remaining > 1))
609             {
610                 if((resource->resourceProperties & OC_ACTIVE)
611                         && (resource->resourceProperties & OC_DISCOVERABLE))
612                 {
613                     // if there is data on the buffer, we have already added a response,
614                     // so we need to add a comma before we do anything
615                     if(firstLoopDone
616                             && remaining >= (sizeof(OC_JSON_SEPARATOR)+1))
617                     {
618                         *ptr = OC_JSON_SEPARATOR;
619                         ptr++;
620                         remaining--;
621                     }
622                     firstLoopDone = 1;
623                     result = BuildVirtualResourceResponse(resource, filterOn, filterValue,
624                             (char*)ptr, &remaining, request->connectivityType );
625
626                     if (result != OC_STACK_OK)
627                     {
628                         // if this failed, we need to remove the comma added above.
629                         if(!firstLoopDone)
630                         {
631                             ptr--;
632                             *ptr = '\0';
633                             remaining++;
634                         }
635                         break;
636                     }
637                     ptr += strlen((char *)ptr);
638                 }
639                 resource = resource->next;
640             }
641
642             if(strlen((const char *)discoveryResBuf) > 0)
643             {
644                 OCEntityHandlerResponse response = {};
645
646                 response.ehResult = OC_EH_OK;
647                 response.payload = discoveryResBuf;
648                 response.payloadSize = strlen((const char *)discoveryResBuf) + 1;
649                 response.persistentBufferFlag = 0;
650                 response.requestHandle = (OCRequestHandle) request;
651                 response.resourceHandle = (OCResourceHandle) resource;
652
653                 result = OCDoResponse(&response);
654             }
655         }
656         else if (strcmp ((char *)request->resourceUrl, GetVirtualResourceUri(OC_DEVICE_URI)) == 0)
657         {
658             remaining = MAX_RESPONSE_LENGTH;
659             ptr = discoveryResBuf;
660
661             result = BuildVirtualResourceResponseForDevice(filterOn, filterValue,
662                     (char*)ptr, &remaining);
663
664             if(result == OC_STACK_OK)
665             {
666                 ptr += strlen((char*)ptr);
667             }
668
669             if(remaining < MAX_RESPONSE_LENGTH)
670             {
671                 OCEntityHandlerResponse response = {0};
672
673                 response.ehResult = OC_EH_OK;
674                 response.payload = discoveryResBuf;
675                 response.payloadSize = strlen((const char *)discoveryResBuf) + 1;
676                 response.persistentBufferFlag = 0;
677                 response.requestHandle = (OCRequestHandle) request;
678                 response.resourceHandle = (OCResourceHandle) resource;
679
680                 result = OCDoResponse(&response);
681             }
682         }
683         #ifdef WITH_PRESENCE
684         else
685         {
686             if(resource->resourceProperties & OC_ACTIVE){
687                 SendPresenceNotification(NULL);
688             }
689         }
690         #endif
691     }
692     result = OC_STACK_OK;
693     return result;
694 }
695
696 static OCStackResult
697 HandleDefaultDeviceEntityHandler (OCServerRequest *request)
698 {
699     if(!request)
700     {
701         return OC_STACK_INVALID_PARAM;
702     }
703
704     OCStackResult result = OC_STACK_OK;
705     OCEntityHandlerResult ehResult = OC_EH_ERROR;
706     OCEntityHandlerRequest ehRequest = {};
707
708     OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithDefaultDeviceEntityHandler"));
709     result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
710             request->method, (OCResourceHandle) NULL, request->query,
711             request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
712             request->rcvdVendorSpecificHeaderOptions,
713             (OCObserveAction)request->observationOption, (OCObservationId)0);
714     VERIFY_SUCCESS(result, OC_STACK_OK);
715
716     // At this point we know for sure that defaultDeviceHandler exists
717     ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
718                                   (char*) request->resourceUrl);
719     if(ehResult == OC_EH_SLOW)
720     {
721         OC_LOG(INFO, TAG, PCF("This is a slow resource"));
722         request->slowFlag = 1;
723     }
724     else if(ehResult == OC_EH_ERROR)
725     {
726         FindAndDeleteServerRequest(request);
727     }
728     result = EntityHandlerCodeToOCStackCode(ehResult);
729 exit:
730     return result;
731 }
732
733 static OCStackResult
734 HandleResourceWithEntityHandler (OCServerRequest *request,
735                                  OCResource *resource,
736                                  uint8_t collectionResource)
737 {
738     if(!request || ! resource)
739     {
740         return OC_STACK_INVALID_PARAM;
741     }
742
743     OCStackResult result = OC_STACK_ERROR;
744     OCEntityHandlerResult ehResult = OC_EH_ERROR;
745     OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
746     ResourceObserver *resObs = NULL;
747
748     OCEntityHandlerRequest ehRequest = {};
749
750     OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithEntityHandler"));
751     result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
752             request->method, (OCResourceHandle) resource, request->query,
753             request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
754             request->rcvdVendorSpecificHeaderOptions,
755             (OCObserveAction)request->observationOption, 0);
756     VERIFY_SUCCESS(result, OC_STACK_OK);
757
758     if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
759     {
760         OC_LOG(INFO, TAG, PCF("No observation requested"));
761         ehFlag = OC_REQUEST_FLAG;
762     }
763     else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER &&
764             !collectionResource)
765     {
766         OC_LOG(INFO, TAG, PCF("Registering observation requested"));
767         result = GenerateObserverId(&ehRequest.obsInfo.obsId);
768         VERIFY_SUCCESS(result, OC_STACK_OK);
769
770         result = AddObserver ((const char*)(request->resourceUrl),
771                 (const char *)(request->query),
772                 ehRequest.obsInfo.obsId, request->requestToken, request->tokenLength,
773                 resource, request->qos,
774                 &request->addressInfo, request->connectivityType);
775
776         if(result == OC_STACK_OK)
777         {
778             OC_LOG(INFO, TAG, PCF("Added observer successfully"));
779             request->observeResult = OC_STACK_OK;
780             ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
781         }
782         else
783         {
784             result = OC_STACK_OK;
785             // The error in observeResult for the request will be
786             // used when responding to this request by omitting
787             // the observation option/sequence number.
788             request->observeResult = OC_STACK_ERROR;
789             OC_LOG(ERROR, TAG, PCF("Observer Addition failed"));
790             ehFlag = OC_REQUEST_FLAG;
791         }
792
793     }
794     else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER &&
795             !collectionResource)
796     {
797         OC_LOG(INFO, TAG, PCF("Deregistering observation requested"));
798
799         resObs = GetObserverUsingToken (request->requestToken, request->tokenLength);
800
801         if (NULL == resObs)
802         {
803             // Stack does not contain this observation request
804             // Either token is incorrect or observation list is corrupted
805             result = OC_STACK_ERROR;
806             goto exit;
807         }
808         ehRequest.obsInfo.obsId = resObs->observeId;
809         ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
810
811         result = DeleteObserverUsingToken (request->requestToken, request->tokenLength);
812
813         if(result == OC_STACK_OK)
814         {
815             OC_LOG(INFO, TAG, PCF("Removed observer successfully"));
816             request->observeResult = OC_STACK_OK;
817         }
818         else
819         {
820             result = OC_STACK_OK;
821             request->observeResult = OC_STACK_ERROR;
822             OC_LOG(ERROR, TAG, PCF("Observer Removal failed"));
823         }
824     }
825     else
826     {
827         result = OC_STACK_ERROR;
828         goto exit;
829     }
830
831     ehResult = resource->entityHandler(ehFlag, &ehRequest);
832     if(ehResult == OC_EH_SLOW)
833     {
834         OC_LOG(INFO, TAG, PCF("This is a slow resource"));
835         request->slowFlag = 1;
836     }
837     else if(ehResult == OC_EH_ERROR)
838     {
839         FindAndDeleteServerRequest(request);
840     }
841     result = EntityHandlerCodeToOCStackCode(ehResult);
842 exit:
843     return result;
844 }
845
846 static OCStackResult
847 HandleCollectionResourceDefaultEntityHandler (OCServerRequest *request,
848                                               OCResource *resource)
849 {
850     if(!request || !resource)
851     {
852         return OC_STACK_INVALID_PARAM;
853     }
854
855     OCStackResult result = OC_STACK_ERROR;
856     OCEntityHandlerRequest ehRequest = {};
857
858     result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
859             request->method, (OCResourceHandle) resource, request->query,
860             request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
861             request->rcvdVendorSpecificHeaderOptions,
862             (OCObserveAction)request->observationOption, (OCObservationId) 0);
863     if(result != OC_STACK_OK)
864     {
865         return result;
866     }
867
868     return (DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest));
869 }
870
871 OCStackResult
872 ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request)
873 {
874     OCStackResult ret = OC_STACK_OK;
875
876     switch (resHandling)
877     {
878         case OC_RESOURCE_VIRTUAL:
879         {
880             ret = HandleVirtualResource (request, resource);
881             break;
882         }
883         case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER:
884         {
885             ret = HandleDefaultDeviceEntityHandler(request);
886             break;
887         }
888         case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
889         {
890             OC_LOG(INFO, TAG, PCF("OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER"));
891             return OC_STACK_ERROR;
892         }
893         case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
894         {
895             ret = HandleResourceWithEntityHandler (request, resource, 0);
896             break;
897         }
898         case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
899         {
900             ret = HandleResourceWithEntityHandler (request, resource, 1);
901             break;
902         }
903         case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
904         {
905             ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
906             break;
907         }
908         case OC_RESOURCE_NOT_SPECIFIED:
909         {
910             ret = OC_STACK_NO_RESOURCE;
911             break;
912         }
913         default:
914         {
915             OC_LOG(INFO, TAG, PCF("Invalid Resource Determination"));
916             return OC_STACK_ERROR;
917         }
918     }
919     return ret;
920 }
921
922 void DeleteDeviceInfo()
923 {
924     if(savedDeviceInfo)
925     {
926         cJSON_Delete(savedDeviceInfo);
927     }
928 }
929
930 OCStackResult SaveDeviceInfo(OCDeviceInfo deviceInfo)
931 {
932     DeleteDeviceInfo();
933
934     savedDeviceInfo = cJSON_CreateObject();
935     cJSON *repObj = NULL;
936
937     cJSON_AddItemToObject (savedDeviceInfo, OC_RSRVD_HREF,
938             cJSON_CreateString(GetVirtualResourceUri(OC_DEVICE_URI)));
939
940     cJSON_AddItemToObject (savedDeviceInfo, OC_RSRVD_REPRESENTATION, repObj = cJSON_CreateObject());
941
942     if (deviceInfo.contentType)
943     {
944         cJSON_AddItemToObject (repObj, OC_RSRVD_CONTENT_TYPE,
945                 cJSON_CreateString(deviceInfo.contentType));
946     }
947
948     if (deviceInfo.dateOfManufacture)
949     {
950         cJSON_AddItemToObject (repObj, OC_RSRVD_MFG_DATE,
951                 cJSON_CreateString(deviceInfo.dateOfManufacture));
952     }
953
954     if (deviceInfo.deviceName)
955     {
956         cJSON_AddItemToObject (repObj, OC_RSRVD_DEVICE_NAME,
957                 cJSON_CreateString(deviceInfo.deviceName));
958     }
959
960     if (deviceInfo.deviceUUID)
961     {
962         cJSON_AddItemToObject (repObj, OC_RSRVD_DEVICE_ID,
963                 cJSON_CreateString(deviceInfo.deviceUUID));
964     }
965
966     if (deviceInfo.firmwareVersion)
967     {
968         cJSON_AddItemToObject (repObj, OC_RSRVD_FW_VERSION,
969                 cJSON_CreateString(deviceInfo.firmwareVersion));
970     }
971
972     if (deviceInfo.hostName)
973     {
974         cJSON_AddItemToObject (repObj, OC_RSRVD_HOST_NAME,
975                 cJSON_CreateString(deviceInfo.hostName));
976     }
977
978     if (deviceInfo.manufacturerName)
979     {
980         if(strlen(deviceInfo.manufacturerName) > MAX_MANUFACTURER_NAME_LENGTH)
981         {
982             DeleteDeviceInfo();
983             return OC_STACK_INVALID_PARAM;
984         }
985
986         cJSON_AddItemToObject (repObj, OC_RSRVD_MFG_NAME,
987                 cJSON_CreateString(deviceInfo.manufacturerName));
988     }
989
990     if (deviceInfo.manufacturerUrl)
991     {
992         if(strlen(deviceInfo.manufacturerUrl) > MAX_MANUFACTURER_URL_LENGTH)
993         {
994             DeleteDeviceInfo();
995             return OC_STACK_INVALID_PARAM;
996         }
997
998         cJSON_AddItemToObject (repObj, OC_RSRVD_MFG_URL,
999                 cJSON_CreateString(deviceInfo.manufacturerUrl));
1000     }
1001
1002     if (deviceInfo.modelNumber)
1003     {
1004         cJSON_AddItemToObject (repObj, OC_RSRVD_MODEL_NUM,
1005                 cJSON_CreateString(deviceInfo.modelNumber));
1006     }
1007
1008     if (deviceInfo.platformVersion)
1009     {
1010         cJSON_AddItemToObject (repObj, OC_RSRVD_PLATFORM_VERSION,
1011                 cJSON_CreateString(deviceInfo.platformVersion));
1012     }
1013
1014     if (deviceInfo.supportUrl)
1015     {
1016         cJSON_AddItemToObject (repObj, OC_RSRVD_SUPPORT_URL,
1017                 cJSON_CreateString(deviceInfo.supportUrl));
1018     }
1019
1020     if (deviceInfo.version)
1021     {
1022         cJSON_AddItemToObject (repObj, OC_RSRVD_VERSION,
1023                 cJSON_CreateString(deviceInfo.version));
1024     }
1025
1026     return OC_STACK_OK;
1027 }