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