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