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