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