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