Merge branch 'master' into group-manager
[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 "ocresource.h"
30 #include "ocresourcehandler.h"
31 #include "ocobserve.h"
32 #include "occollection.h"
33 #include "oic_malloc.h"
34 #include "oic_string.h"
35 #include "logger.h"
36 #include "cJSON.h"
37 #include "ocpayload.h"
38 #include "secureresourcemanager.h"
39 #include "cacommon.h"
40 #include "cainterface.h"
41 #include "rdpayload.h"
42 #include "ocpayload.h"
43
44 #ifdef WITH_RD
45 #include "rd_server.h"
46 #endif
47
48 #ifdef ROUTING_GATEWAY
49 #include "routingmanager.h"
50 #endif
51
52 /// Module Name
53 #define TAG "OIC_RI_RESOURCE"
54
55 #define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
56             {OIC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
57
58 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OIC_LOG((logLevel), \
59              TAG, #arg " is NULL"); return (retVal); } }
60
61 extern OCResource *headResource;
62 static OCPlatformInfo savedPlatformInfo = {0};
63 static OCDeviceInfo savedDeviceInfo = {0};
64
65 /**
66  * Prepares a Payload for response.
67  */
68 static OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
69                                                   OCDiscoveryPayload* payload,
70                                                   OCDevAddr *endpoint,
71                                                   bool rdResponse);
72
73 //-----------------------------------------------------------------------------
74 // Default resource entity handler function
75 //-----------------------------------------------------------------------------
76 OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag,
77         OCEntityHandlerRequest * request, void* callbackParam)
78 {
79     //TODO ("Implement me!!!!");
80     // TODO:  remove silence unused param warnings
81     (void) flag;
82     (void) request;
83     (void) callbackParam;
84     return  OC_EH_OK; // Making sure that the Default EH and the Vendor EH have matching signatures
85 }
86
87 /* This method will retrieve the port at which the secure resource is hosted */
88 static OCStackResult GetSecurePortInfo(OCDevAddr *endpoint, uint16_t *port)
89 {
90     uint16_t p = 0;
91
92     if (endpoint->adapter == OC_ADAPTER_IP)
93     {
94         if (endpoint->flags & OC_IP_USE_V6)
95         {
96             p = caglobals.ip.u6s.port;
97         }
98         else if (endpoint->flags & OC_IP_USE_V4)
99         {
100             p = caglobals.ip.u4s.port;
101         }
102     }
103
104     *port = p;
105     return OC_STACK_OK;
106 }
107
108 /*
109  * Function will extract 0, 1 or 2 filters from query.
110  * More than 2 filters or unsupported filters will result in error.
111  * If both filters are of the same supported type, the 2nd one will be picked.
112  * Resource and device filters in the SAME query are NOT validated
113  * and resources will likely not clear filters.
114  */
115 static OCStackResult ExtractFiltersFromQuery(char *query, char **filterOne, char **filterTwo)
116 {
117
118     char *key = NULL;
119     char *value = NULL;
120     char *restOfQuery = NULL;
121     int numKeyValuePairsParsed = 0;
122
123     *filterOne = NULL;
124     *filterTwo = NULL;
125
126     OIC_LOG_V(INFO, TAG, "Extracting params from %s", query);
127
128     char *keyValuePair = strtok_r (query, OC_QUERY_SEPARATOR, &restOfQuery);
129
130     while(keyValuePair)
131     {
132         if (numKeyValuePairsParsed >= 2)
133         {
134             OIC_LOG(ERROR, TAG, "More than 2 queries params in URI.");
135             return OC_STACK_INVALID_QUERY;
136         }
137
138         key = strtok_r(keyValuePair, OC_KEY_VALUE_DELIMITER, &value);
139
140         if (!key || !value)
141         {
142             return OC_STACK_INVALID_QUERY;
143         }
144         else if (strcmp (key, OC_RSRVD_INTERFACE) == 0)
145         {
146             *filterOne = value;     // if
147         }
148         else if (strcmp (key, OC_RSRVD_RESOURCE_TYPE) == 0)
149         {
150             *filterTwo = value;     // rt
151         }
152         else
153         {
154             OIC_LOG_V(ERROR, TAG, "Unsupported query key: %s", key);
155             return OC_STACK_INVALID_QUERY;
156         }
157         ++numKeyValuePairsParsed;
158
159         keyValuePair = strtok_r(NULL, OC_QUERY_SEPARATOR, &restOfQuery);
160     }
161
162     OIC_LOG_V(INFO, TAG, "Extracted params %s and %s.", *filterOne, *filterTwo);
163     return OC_STACK_OK;
164 }
165
166 static OCVirtualResources GetTypeOfVirtualURI(const char *uriInRequest)
167 {
168     if (strcmp(uriInRequest, OC_RSRVD_WELL_KNOWN_URI) == 0)
169     {
170         return OC_WELL_KNOWN_URI;
171     }
172     else if (strcmp(uriInRequest, OC_RSRVD_DEVICE_URI) == 0)
173     {
174         return OC_DEVICE_URI;
175     }
176     else if (strcmp(uriInRequest, OC_RSRVD_PLATFORM_URI) == 0)
177     {
178         return OC_PLATFORM_URI;
179     }
180     else if (strcmp(uriInRequest, OC_RSRVD_RESOURCE_TYPES_URI) == 0)
181     {
182         return OC_RESOURCE_TYPES_URI;
183     }
184 #ifdef ROUTING_GATEWAY
185     else if (0 == strcmp(uriInRequest, OC_RSRVD_GATEWAY_URI))
186     {
187         return OC_GATEWAY_URI;
188     }
189 #endif
190 #ifdef WITH_PRESENCE
191     else if (strcmp(uriInRequest, OC_RSRVD_PRESENCE_URI) == 0)
192     {
193         return OC_PRESENCE;
194     }
195 #endif //WITH_PRESENCE
196     return OC_UNKNOWN_URI;
197 }
198
199 static OCStackResult getQueryParamsForFiltering (OCVirtualResources uri, char *query,
200                                             char **filterOne, char **filterTwo)
201 {
202     if(!filterOne || !filterTwo)
203     {
204         return OC_STACK_INVALID_PARAM;
205     }
206
207     *filterOne = NULL;
208     *filterTwo = NULL;
209
210     #ifdef WITH_PRESENCE
211     if (uri == OC_PRESENCE)
212     {
213         //Nothing needs to be done, except for pass a OC_PRESENCE query through as OC_STACK_OK.
214         OIC_LOG(INFO, TAG, "OC_PRESENCE Request for virtual resource.");
215         return OC_STACK_OK;
216     }
217     #endif
218
219     OCStackResult result = OC_STACK_OK;
220
221     if (query && *query)
222     {
223         result = ExtractFiltersFromQuery(query, filterOne, filterTwo);
224     }
225
226     return result;
227 }
228
229 OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr,
230                     OCRepPayload** payload)
231 {
232     OCRepPayload *tempPayload = OCRepPayloadCreate();
233
234     if (!resourcePtr)
235     {
236         OCRepPayloadDestroy(tempPayload);
237         return OC_STACK_INVALID_PARAM;
238     }
239
240     if(!tempPayload)
241     {
242         return OC_STACK_NO_MEMORY;
243     }
244
245     OCRepPayloadSetUri(tempPayload, resourcePtr->uri);
246
247     OCResourceType *resType = resourcePtr->rsrcType;
248     while(resType)
249     {
250         OCRepPayloadAddResourceType(tempPayload, resType->resourcetypename);
251         resType = resType->next;
252     }
253
254     OCResourceInterface *resInterface = resourcePtr->rsrcInterface;
255     while(resInterface)
256     {
257         OCRepPayloadAddInterface(tempPayload, resInterface->name);
258         resInterface = resInterface->next;
259     }
260
261     OCAttribute *resAttrib = resourcePtr->rsrcAttributes;
262     while(resAttrib)
263     {
264         OCRepPayloadSetPropString(tempPayload, resAttrib->attrName,
265                                 resAttrib->attrValue);
266         resAttrib = resAttrib->next;
267     }
268
269     if(!*payload)
270     {
271         *payload = tempPayload;
272     }
273     else
274     {
275         OCRepPayloadAppend(*payload, tempPayload);
276     }
277
278     return OC_STACK_OK;
279 }
280
281 OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
282                         OCDiscoveryPayload *payload, OCDevAddr *devAddr, bool rdResponse)
283 {
284     if (!resourcePtr || !payload)
285     {
286         return OC_STACK_INVALID_PARAM;
287     }
288     uint16_t port = 0;
289     if (resourcePtr->resourceProperties & OC_SECURE)
290     {
291        if (GetSecurePortInfo(devAddr, &port) != OC_STACK_OK)
292        {
293            port = 0;
294        }
295     }
296
297     if (rdResponse)
298     {
299         port = devAddr->port;
300     }
301
302     OCDiscoveryPayloadAddResource(payload, resourcePtr, port);
303     return OC_STACK_OK;
304 }
305
306 uint8_t IsCollectionResource (OCResource *resource)
307 {
308     if(!resource)
309     {
310         return 0;
311     }
312
313     if(resource->rsrcChildResourcesHead != NULL)
314     {
315         return 1;
316     }
317
318     return 0;
319 }
320
321 OCResource *FindResourceByUri(const char* resourceUri)
322 {
323     if(!resourceUri)
324     {
325         return NULL;
326     }
327
328     OCResource * pointer = headResource;
329     while (pointer)
330     {
331         if (strcmp(resourceUri, pointer->uri) == 0)
332         {
333             return pointer;
334         }
335         pointer = pointer->next;
336     }
337     OIC_LOG_V(INFO, TAG, "Resource %s not found", resourceUri);
338     return NULL;
339 }
340
341
342 OCStackResult DetermineResourceHandling (const OCServerRequest *request,
343                                          ResourceHandling *handling,
344                                          OCResource **resource)
345 {
346     if(!request || !handling || !resource)
347     {
348         return OC_STACK_INVALID_PARAM;
349     }
350
351     OIC_LOG_V(INFO, TAG, "DetermineResourceHandling for %s", request->resourceUrl);
352
353     // Check if virtual resource
354     if (GetTypeOfVirtualURI(request->resourceUrl) != OC_UNKNOWN_URI)
355     {
356         OIC_LOG_V (INFO, TAG, "%s is virtual", request->resourceUrl);
357         *handling = OC_RESOURCE_VIRTUAL;
358         *resource = headResource;
359         return OC_STACK_OK;
360     }
361     if (strlen((const char*)(request->resourceUrl)) == 0)
362     {
363         // Resource URL not specified
364         *handling = OC_RESOURCE_NOT_SPECIFIED;
365         return OC_STACK_NO_RESOURCE;
366     }
367     else
368     {
369         OCResource *resourcePtr = FindResourceByUri((const char*)request->resourceUrl);
370         *resource = resourcePtr;
371         if (!resourcePtr)
372         {
373             if(defaultDeviceHandler)
374             {
375                 *handling = OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER;
376                 return OC_STACK_OK;
377             }
378
379             // Resource does not exist
380             // and default device handler does not exist
381             *handling = OC_RESOURCE_NOT_SPECIFIED;
382             return OC_STACK_NO_RESOURCE;
383         }
384
385         if (IsCollectionResource (resourcePtr))
386         {
387             // Collection resource
388             if (resourcePtr->entityHandler != defaultResourceEHandler)
389             {
390                 *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER;
391                 return OC_STACK_OK;
392             }
393             else
394             {
395                 *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER;
396                 return OC_STACK_OK;
397             }
398         }
399         else
400         {
401             // Resource not a collection
402             if (resourcePtr->entityHandler != defaultResourceEHandler)
403             {
404                 *handling = OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER;
405                 return OC_STACK_OK;
406             }
407             else
408             {
409                 *handling = OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER;
410                 return OC_STACK_OK;
411             }
412         }
413     }
414 }
415
416 OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
417 {
418     OCStackResult result;
419
420     switch (ehResult)
421     {
422         case OC_EH_OK:
423             result = OC_STACK_OK;
424             break;
425         case OC_EH_SLOW:
426             result = OC_STACK_SLOW_RESOURCE;
427             break;
428         case OC_EH_ERROR:
429             result = OC_STACK_ERROR;
430             break;
431         case OC_EH_FORBIDDEN:
432             result = OC_STACK_RESOURCE_ERROR;
433             break;
434         case OC_EH_RESOURCE_CREATED:
435             result = OC_STACK_RESOURCE_CREATED;
436             break;
437         case OC_EH_RESOURCE_DELETED:
438             result = OC_STACK_RESOURCE_DELETED;
439             break;
440         case OC_EH_RESOURCE_NOT_FOUND:
441             result = OC_STACK_NO_RESOURCE;
442             break;
443         default:
444             result = OC_STACK_ERROR;
445     }
446
447     return result;
448 }
449
450 static bool resourceMatchesRTFilter(OCResource *resource, char *resourceTypeFilter)
451 {
452     if (!resource)
453     {
454         return false;
455     }
456
457     // Null or empty is analogous to no filter.
458     if (resourceTypeFilter == NULL || *resourceTypeFilter == 0)
459     {
460         return true;
461     }
462
463     OCResourceType *resourceTypePtr = resource->rsrcType;
464
465     while (resourceTypePtr)
466     {
467         if (strcmp (resourceTypePtr->resourcetypename, resourceTypeFilter) == 0)
468         {
469             return true;
470         }
471         resourceTypePtr = resourceTypePtr->next;
472     }
473
474     OIC_LOG_V(INFO, TAG, "%s does not contain rt=%s.", resource->uri, resourceTypeFilter);
475     return false;
476 }
477
478 static bool resourceMatchesIFFilter(OCResource *resource, char *interfaceFilter)
479 {
480     if (!resource)
481     {
482         return false;
483     }
484
485     // Null or empty is analogous to no filter.
486     if (interfaceFilter == NULL || *interfaceFilter == 0)
487     {
488         return true;
489     }
490
491     OCResourceInterface *interfacePtr = resource->rsrcInterface;
492
493     while (interfacePtr)
494     {
495         if (strcmp (interfacePtr->name, interfaceFilter) == 0)
496         {
497             return true;
498         }
499         interfacePtr = interfacePtr->next;
500     }
501
502     OIC_LOG_V(INFO, TAG, "%s does not contain if=%s.", resource->uri, interfaceFilter);
503     return false;
504 }
505
506 /*
507  * If the filters are null, they will be assumed to NOT be present
508  * and the resource will not be matched against them.
509  * Function will return true if all non null AND non empty filters passed in find a match.
510  */
511 static bool includeThisResourceInResponse(OCResource *resource,
512                                                  char *interfaceFilter,
513                                                  char *resourceTypeFilter)
514 {
515     if (!resource)
516     {
517         OIC_LOG(ERROR, TAG, "Invalid resource");
518         return false;
519     }
520
521     if ( resource->resourceProperties & OC_EXPLICIT_DISCOVERABLE)
522     {
523         /*
524          * At least one valid filter should be available to
525          * include the resource in discovery response
526          */
527         if (!((interfaceFilter && *interfaceFilter ) ||
528               (resourceTypeFilter && *resourceTypeFilter)))
529         {
530             OIC_LOG_V(INFO, TAG, "%s no query string for EXPLICIT_DISCOVERABLE \
531                 resource", resource->uri);
532             return false;
533         }
534     }
535     else if ( !(resource->resourceProperties & OC_ACTIVE) ||
536          !(resource->resourceProperties & OC_DISCOVERABLE))
537     {
538         OIC_LOG_V(INFO, TAG, "%s not ACTIVE or DISCOVERABLE", resource->uri);
539         return false;
540     }
541
542     return resourceMatchesIFFilter(resource, interfaceFilter) &&
543            resourceMatchesRTFilter(resource, resourceTypeFilter);
544
545 }
546
547 OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCResource *resource,
548                                 OCPayload *discoveryPayload, OCEntityHandlerResult ehResult)
549 {
550     OCEntityHandlerResponse response = {0};
551
552     response.ehResult = ehResult;
553     response.payload = discoveryPayload;
554     response.persistentBufferFlag = 0;
555     response.requestHandle = (OCRequestHandle) request;
556     response.resourceHandle = (OCResourceHandle) resource;
557
558     return OCDoResponse(&response);
559 }
560
561 #ifdef WITH_RD
562 static OCStackResult checkResourceExistsAtRD(const char *interfaceType, const char *resourceType,
563      OCResource **payload, OCDevAddr *devAddr)
564 {
565     OCResourceCollectionPayload *repPayload;
566     if (!payload)
567     {
568         return OC_STACK_ERROR;
569     }
570     if (OCRDCheckPublishedResource(interfaceType, resourceType, &repPayload, devAddr) == OC_STACK_OK)
571     {
572         if (!repPayload)
573         {
574             return OC_STACK_ERROR;
575         }
576         OCResource *ptr = ((OCResource *) OICCalloc(1, sizeof(OCResource)));
577         if (!ptr)
578         {
579            return OC_STACK_NO_MEMORY;
580         }
581
582         ptr->uri = OICStrdup(repPayload->setLinks->href);
583         if (!ptr->uri)
584         {
585            return OC_STACK_NO_MEMORY;
586         }
587         OCStringLL *rt = repPayload->setLinks->rt;
588         while (rt)
589         {
590             OCResourceType *temp = (OCResourceType *) OICCalloc(1, sizeof(OCResourceType));
591             if(!temp)
592             {
593                 OICFree(ptr->uri);
594                 return OC_STACK_NO_MEMORY;
595             }
596             temp->next = NULL;
597             temp->resourcetypename = OICStrdup(rt->value);
598             if (!ptr->rsrcType)
599             {
600                 ptr->rsrcType = temp;
601             }
602             else
603             {
604                 OCResourceType *type = ptr->rsrcType;
605                 while (type->next)
606                 {
607                     type = type->next;
608                 }
609                 type->next = temp;
610             }
611             rt = rt->next;
612         }
613
614         OCStringLL *itf = repPayload->setLinks->itf;
615         while (itf)
616         {
617             OCResourceInterface *temp = (OCResourceInterface *) OICCalloc(1, sizeof(OCResourceInterface));
618             if (!temp)
619             {
620                 OICFree(ptr->uri);
621
622                 return OC_STACK_NO_MEMORY;
623             }
624             temp->next = NULL;
625             temp->name = OICStrdup(itf->value);
626             if (!ptr->rsrcInterface)
627             {
628                 ptr->rsrcInterface = temp;
629             }
630             else
631             {
632                 OCResourceInterface *type = ptr->rsrcInterface;
633                 while (type->next)
634                 {
635                     type = type->next;
636                 }
637                 type->next = temp;
638             }
639             itf = itf->next;
640         }
641
642         ptr->resourceProperties = (OCResourceProperty) repPayload->tags->bitmap;
643
644         OCFreeCollectionResource(repPayload);
645         *payload = ptr;
646         return OC_STACK_OK;
647     }
648     else
649     {
650         OIC_LOG_V(ERROR, TAG, "The resource type or interface type doe not exist \
651                              on the resource directory");
652     }
653     return OC_STACK_ERROR;
654 }
655 #endif
656
657 static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource)
658 {
659     if (!request || !resource)
660     {
661         return OC_STACK_INVALID_PARAM;
662     }
663
664     OCStackResult discoveryResult = OC_STACK_ERROR;
665
666     bool bMulticast    = false;     // Was the discovery request a multicast request?
667     OCPayload* payload = NULL;
668
669     OIC_LOG(INFO, TAG, "Entering HandleVirtualResource");
670
671     OCVirtualResources virtualUriInRequest = GetTypeOfVirtualURI (request->resourceUrl);
672
673     // Step 1: Generate the response to discovery request
674     if (virtualUriInRequest == OC_WELL_KNOWN_URI)
675     {
676         char *filterOne = NULL;
677         char *filterTwo = NULL;
678
679         discoveryResult = getQueryParamsForFiltering (virtualUriInRequest, request->query,
680                 &filterOne, &filterTwo);
681
682         if (discoveryResult == OC_STACK_OK)
683         {
684             payload = (OCPayload*)OCDiscoveryPayloadCreate();
685
686             if(payload)
687             {
688                 ((OCDiscoveryPayload*)payload)->sid = (uint8_t*)OICCalloc(1, UUID_SIZE);
689                 memcpy(((OCDiscoveryPayload*)payload)->sid, OCGetServerInstanceID(), UUID_SIZE);
690
691                 bool foundResourceAtRD = false;
692                 for(;resource && discoveryResult == OC_STACK_OK; resource = resource->next)
693                 {
694 #ifdef WITH_RD
695                     if (strcmp(resource->uri, OC_RSRVD_RD_URI) == 0)
696                     {
697                         OCResource *resource = NULL;
698                         OCDevAddr devAddr;
699                         discoveryResult = checkResourceExistsAtRD(filterOne, filterTwo,
700                                                                   &resource, &devAddr);
701                         if (discoveryResult != OC_STACK_OK)
702                         {
703                              break;
704                         }
705                         discoveryResult = BuildVirtualResourceResponse(resource,
706                                     (OCDiscoveryPayload*)payload,
707                                     &devAddr, true);
708                         if (payload)
709                         {
710                             ((OCDiscoveryPayload*)payload)->baseURI = OICStrdup(devAddr.addr);
711                         }
712                         foundResourceAtRD = true;
713                     }
714 #endif
715                     if(!foundResourceAtRD && includeThisResourceInResponse(resource, filterOne, filterTwo))
716                     {
717                         discoveryResult = BuildVirtualResourceResponse(resource,
718                                 (OCDiscoveryPayload*)payload,
719                                 &request->devAddr, false);
720                     }
721                 }
722                 // Set discoveryResult appropriately if no 'valid' resources are available
723                 if (((OCDiscoveryPayload*)payload)->resources == NULL && !foundResourceAtRD)
724                 {
725                     discoveryResult = OC_STACK_NO_RESOURCE;
726                 }
727             }
728             else
729             {
730                 discoveryResult = OC_STACK_NO_MEMORY;
731             }
732         }
733         else
734         {
735             OIC_LOG_V(ERROR, TAG, "Error (%d) parsing query.", discoveryResult);
736         }
737     }
738     else if (virtualUriInRequest == OC_DEVICE_URI)
739     {
740         const OicUuid_t* deviceId = OCGetServerInstanceID();
741         if (!deviceId)
742         {
743             discoveryResult = OC_STACK_ERROR;
744         }
745         else
746         {
747             payload = (OCPayload*) OCDevicePayloadCreate((const uint8_t*) &deviceId->id, savedDeviceInfo.deviceName,
748                     OC_SPEC_VERSION, OC_DATA_MODEL_VERSION);
749             if (!payload)
750             {
751                 discoveryResult = OC_STACK_NO_MEMORY;
752             }
753             else
754             {
755                 discoveryResult = OC_STACK_OK;
756             }
757         }
758     }
759     else if (virtualUriInRequest == OC_PLATFORM_URI)
760     {
761         payload = (OCPayload*)OCPlatformPayloadCreate(&savedPlatformInfo);
762         if (!payload)
763         {
764             discoveryResult = OC_STACK_NO_MEMORY;
765         }
766         else
767         {
768             discoveryResult = OC_STACK_OK;
769         }
770     }
771 #ifdef ROUTING_GATEWAY
772     else if (OC_GATEWAY_URI == virtualUriInRequest)
773     {
774         // Received request for a gateway
775         OIC_LOG(INFO, TAG, "Request is for Gateway Virtual Request");
776         discoveryResult = RMHandleGatewayRequest(request, resource);
777
778     }
779 #endif
780
781     /**
782      * Step 2: Send the discovery response
783      *
784      * Iotivity should respond to discovery requests in below manner:
785      * 1)If query filter matching fails and discovery request is multicast,
786      *   it should NOT send any response.
787      * 2)If query filter matching fails and discovery request is unicast,
788      *   it should send an error(RESOURCE_NOT_FOUND - 404) response.
789      * 3)If Server does not have any 'DISCOVERABLE' resources and discovery
790      *   request is multicast, it should NOT send any response.
791      * 4)If Server does not have any 'DISCOVERABLE' resources and discovery
792      *   request is unicast, it should send an error(RESOURCE_NOT_FOUND - 404) response.
793      */
794
795 #ifdef WITH_PRESENCE
796     if ((virtualUriInRequest == OC_PRESENCE) &&
797         (resource->resourceProperties & OC_ACTIVE))
798     {
799         // Presence uses observer notification api to respond via SendPresenceNotification.
800         SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
801     }
802     else
803     #endif
804 #ifdef ROUTING_GATEWAY
805     // Gateway uses the RMHandleGatewayRequest to respond to the request.
806     if (OC_GATEWAY_URI != virtualUriInRequest)
807 #endif
808     {
809         if(discoveryResult == OC_STACK_OK)
810         {
811             SendNonPersistantDiscoveryResponse(request, resource, payload, OC_EH_OK);
812         }
813         else if(bMulticast == false && (request->devAddr.adapter != OC_ADAPTER_RFCOMM_BTEDR) &&
814                (request->devAddr.adapter != OC_ADAPTER_GATT_BTLE))
815         {
816             OIC_LOG_V(ERROR, TAG, "Sending a (%d) error to (%d)  \
817                 discovery request", discoveryResult, virtualUriInRequest);
818             SendNonPersistantDiscoveryResponse(request, resource, NULL,
819                 (discoveryResult == OC_STACK_NO_RESOURCE) ? OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR);
820         }
821         else
822         {
823             // Ignoring the discovery request as per RFC 7252, Section #8.2
824             OIC_LOG(INFO, TAG, "Silently ignoring the request since device does not have \
825                 any useful data to send");
826         }
827     }
828
829     OCPayloadDestroy(payload);
830
831     return OC_STACK_OK;
832 }
833
834 static OCStackResult
835 HandleDefaultDeviceEntityHandler (OCServerRequest *request)
836 {
837     if(!request)
838     {
839         return OC_STACK_INVALID_PARAM;
840     }
841
842     OCStackResult result = OC_STACK_OK;
843     OCEntityHandlerResult ehResult = OC_EH_ERROR;
844     OCEntityHandlerRequest ehRequest = {0};
845
846     OIC_LOG(INFO, TAG, "Entering HandleResourceWithDefaultDeviceEntityHandler");
847     result = FormOCEntityHandlerRequest(&ehRequest,
848                                         (OCRequestHandle) request,
849                                         request->method,
850                                         &request->devAddr,
851                                         (OCResourceHandle) NULL, request->query,
852                                         PAYLOAD_TYPE_REPRESENTATION,
853                                         request->payload,
854                                         request->payloadSize,
855                                         request->numRcvdVendorSpecificHeaderOptions,
856                                         request->rcvdVendorSpecificHeaderOptions,
857                                         (OCObserveAction)request->observationOption,
858                                         (OCObservationId)0);
859     VERIFY_SUCCESS(result, OC_STACK_OK);
860
861     // At this point we know for sure that defaultDeviceHandler exists
862     ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
863                                   (char*) request->resourceUrl, defaultDeviceHandlerCallbackParameter);
864     if(ehResult == OC_EH_SLOW)
865     {
866         OIC_LOG(INFO, TAG, "This is a slow resource");
867         request->slowFlag = 1;
868     }
869     else if(ehResult == OC_EH_ERROR)
870     {
871         FindAndDeleteServerRequest(request);
872     }
873     result = EntityHandlerCodeToOCStackCode(ehResult);
874 exit:
875     OCPayloadDestroy(ehRequest.payload);
876     return result;
877 }
878
879 static OCStackResult
880 HandleResourceWithEntityHandler (OCServerRequest *request,
881                                  OCResource *resource,
882                                  uint8_t collectionResource)
883 {
884     if(!request || ! resource)
885     {
886         return OC_STACK_INVALID_PARAM;
887     }
888
889     OCStackResult result = OC_STACK_ERROR;
890     OCEntityHandlerResult ehResult = OC_EH_ERROR;
891     OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
892     ResourceObserver *resObs = NULL;
893
894     OCEntityHandlerRequest ehRequest = {0};
895
896     OIC_LOG(INFO, TAG, "Entering HandleResourceWithEntityHandler");
897     OCPayloadType type = PAYLOAD_TYPE_REPRESENTATION;
898     // check the security resource
899     if (request && request->resourceUrl && SRMIsSecurityResourceURI(request->resourceUrl))
900     {
901         type = PAYLOAD_TYPE_SECURITY;
902
903     }
904
905     if (request && strcmp(request->resourceUrl, OC_RSRVD_RD_URI) == 0)
906     {
907         type = PAYLOAD_TYPE_RD;
908     }
909
910     result = FormOCEntityHandlerRequest(&ehRequest,
911                                         (OCRequestHandle)request,
912                                         request->method,
913                                         &request->devAddr,
914                                         (OCResourceHandle)resource,
915                                         request->query,
916                                         type,
917                                         request->payload,
918                                         request->payloadSize,
919                                         request->numRcvdVendorSpecificHeaderOptions,
920                                         request->rcvdVendorSpecificHeaderOptions,
921                                         (OCObserveAction)request->observationOption,
922                                         0);
923     VERIFY_SUCCESS(result, OC_STACK_OK);
924
925     if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
926     {
927         OIC_LOG(INFO, TAG, "No observation requested");
928         ehFlag = OC_REQUEST_FLAG;
929     }
930     else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER && !collectionResource)
931     {
932         OIC_LOG(INFO, TAG, "Observation registration requested");
933
934         ResourceObserver *obs = GetObserverUsingToken (request->requestToken,
935                                     request->tokenLength);
936
937         if (obs)
938         {
939             OIC_LOG (INFO, TAG, "Observer with this token already present");
940             OIC_LOG (INFO, TAG, "Possibly re-transmitted CON OBS request");
941             OIC_LOG (INFO, TAG, "Not adding observer. Not responding to client");
942             OIC_LOG (INFO, TAG, "The first request for this token is already ACKED.");
943
944             // server requests are usually free'd when the response is sent out
945             // for the request in ocserverrequest.c : HandleSingleResponse()
946             // Since we are making an early return and not responding, the server request
947             // needs to be deleted.
948             FindAndDeleteServerRequest (request);
949             return OC_STACK_OK;
950         }
951
952         result = GenerateObserverId(&ehRequest.obsInfo.obsId);
953         VERIFY_SUCCESS(result, OC_STACK_OK);
954
955         result = AddObserver ((const char*)(request->resourceUrl),
956                 (const char *)(request->query),
957                 ehRequest.obsInfo.obsId, request->requestToken, request->tokenLength,
958                 resource, request->qos, request->acceptFormat,
959                 &request->devAddr);
960
961         if(result == OC_STACK_OK)
962         {
963             OIC_LOG(INFO, TAG, "Added observer successfully");
964             request->observeResult = OC_STACK_OK;
965             ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
966         }
967         else
968         {
969             result = OC_STACK_OK;
970
971             // The error in observeResult for the request will be used when responding to this
972             // request by omitting the observation option/sequence number.
973             request->observeResult = OC_STACK_ERROR;
974             OIC_LOG(ERROR, TAG, "Observer Addition failed");
975             ehFlag = OC_REQUEST_FLAG;
976         }
977
978     }
979     else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER &&
980             !collectionResource)
981     {
982         OIC_LOG(INFO, TAG, "Deregistering observation requested");
983
984         resObs = GetObserverUsingToken (request->requestToken, request->tokenLength);
985
986         if (NULL == resObs)
987         {
988             // Stack does not contain this observation request
989             // Either token is incorrect or observation list is corrupted
990             result = OC_STACK_ERROR;
991             goto exit;
992         }
993         ehRequest.obsInfo.obsId = resObs->observeId;
994         ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
995
996         result = DeleteObserverUsingToken (request->requestToken, request->tokenLength);
997
998         if(result == OC_STACK_OK)
999         {
1000             OIC_LOG(INFO, TAG, "Removed observer successfully");
1001             request->observeResult = OC_STACK_OK;
1002         }
1003         else
1004         {
1005             result = OC_STACK_OK;
1006             request->observeResult = OC_STACK_ERROR;
1007             OIC_LOG(ERROR, TAG, "Observer Removal failed");
1008         }
1009     }
1010     else
1011     {
1012         result = OC_STACK_ERROR;
1013         goto exit;
1014     }
1015
1016     ehResult = resource->entityHandler(ehFlag, &ehRequest, resource->entityHandlerCallbackParam);
1017     if(ehResult == OC_EH_SLOW)
1018     {
1019         OIC_LOG(INFO, TAG, "This is a slow resource");
1020         request->slowFlag = 1;
1021     }
1022     else if(ehResult == OC_EH_ERROR)
1023     {
1024         FindAndDeleteServerRequest(request);
1025     }
1026     result = EntityHandlerCodeToOCStackCode(ehResult);
1027 exit:
1028     OCPayloadDestroy(ehRequest.payload);
1029     return result;
1030 }
1031
1032 static OCStackResult
1033 HandleCollectionResourceDefaultEntityHandler (OCServerRequest *request,
1034                                               OCResource *resource)
1035 {
1036     if(!request || !resource)
1037     {
1038         return OC_STACK_INVALID_PARAM;
1039     }
1040
1041     OCStackResult result = OC_STACK_ERROR;
1042     OCEntityHandlerRequest ehRequest = {0};
1043
1044     result = FormOCEntityHandlerRequest(&ehRequest,
1045                                         (OCRequestHandle)request,
1046                                         request->method,
1047                                         &request->devAddr,
1048                                         (OCResourceHandle)resource,
1049                                         request->query,
1050                                         PAYLOAD_TYPE_REPRESENTATION,
1051                                         request->payload,
1052                                         request->payloadSize,
1053                                         request->numRcvdVendorSpecificHeaderOptions,
1054                                         request->rcvdVendorSpecificHeaderOptions,
1055                                         (OCObserveAction)request->observationOption,
1056                                         (OCObservationId)0);
1057     if(result == OC_STACK_OK)
1058     {
1059         result = DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest);
1060     }
1061
1062     OCPayloadDestroy(ehRequest.payload);
1063     return result;
1064 }
1065
1066 OCStackResult
1067 ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request)
1068 {
1069     OCStackResult ret = OC_STACK_OK;
1070
1071     switch (resHandling)
1072     {
1073         case OC_RESOURCE_VIRTUAL:
1074         {
1075             ret = HandleVirtualResource (request, resource);
1076             break;
1077         }
1078         case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER:
1079         {
1080             ret = HandleDefaultDeviceEntityHandler(request);
1081             break;
1082         }
1083         case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
1084         {
1085             OIC_LOG(INFO, TAG, "OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER");
1086             return OC_STACK_ERROR;
1087         }
1088         case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
1089         {
1090             ret = HandleResourceWithEntityHandler (request, resource, 0);
1091             break;
1092         }
1093         case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
1094         {
1095             ret = HandleResourceWithEntityHandler (request, resource, 1);
1096             break;
1097         }
1098         case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
1099         {
1100             ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
1101             break;
1102         }
1103         case OC_RESOURCE_NOT_SPECIFIED:
1104         {
1105             ret = OC_STACK_NO_RESOURCE;
1106             break;
1107         }
1108         default:
1109         {
1110             OIC_LOG(INFO, TAG, "Invalid Resource Determination");
1111             return OC_STACK_ERROR;
1112         }
1113     }
1114     return ret;
1115 }
1116
1117 void DeletePlatformInfo()
1118 {
1119     OIC_LOG(INFO, TAG, "Deleting platform info.");
1120
1121     OICFree(savedPlatformInfo.platformID);
1122     savedPlatformInfo.platformID = NULL;
1123
1124     OICFree(savedPlatformInfo.manufacturerName);
1125     savedPlatformInfo.manufacturerName = NULL;
1126
1127     OICFree(savedPlatformInfo.manufacturerUrl);
1128     savedPlatformInfo.manufacturerUrl = NULL;
1129
1130     OICFree(savedPlatformInfo.modelNumber);
1131     savedPlatformInfo.modelNumber = NULL;
1132
1133     OICFree(savedPlatformInfo.dateOfManufacture);
1134     savedPlatformInfo.dateOfManufacture = NULL;
1135
1136     OICFree(savedPlatformInfo.platformVersion);
1137     savedPlatformInfo.platformVersion = NULL;
1138
1139     OICFree(savedPlatformInfo.operatingSystemVersion);
1140     savedPlatformInfo.operatingSystemVersion = NULL;
1141
1142     OICFree(savedPlatformInfo.hardwareVersion);
1143     savedPlatformInfo.hardwareVersion = NULL;
1144
1145     OICFree(savedPlatformInfo.firmwareVersion);
1146     savedPlatformInfo.firmwareVersion = NULL;
1147
1148     OICFree(savedPlatformInfo.supportUrl);
1149     savedPlatformInfo.supportUrl = NULL;
1150
1151     OICFree(savedPlatformInfo.systemTime);
1152     savedPlatformInfo.systemTime = NULL;
1153 }
1154
1155 static OCStackResult DeepCopyPlatFormInfo(OCPlatformInfo info)
1156 {
1157     savedPlatformInfo.platformID = OICStrdup(info.platformID);
1158     savedPlatformInfo.manufacturerName = OICStrdup(info.manufacturerName);
1159     savedPlatformInfo.manufacturerUrl = OICStrdup(info.manufacturerUrl);
1160     savedPlatformInfo.modelNumber = OICStrdup(info.modelNumber);
1161     savedPlatformInfo.dateOfManufacture = OICStrdup(info.dateOfManufacture);
1162     savedPlatformInfo.platformVersion = OICStrdup(info.platformVersion);
1163     savedPlatformInfo.operatingSystemVersion = OICStrdup(info.operatingSystemVersion);
1164     savedPlatformInfo.hardwareVersion = OICStrdup(info.hardwareVersion);
1165     savedPlatformInfo.firmwareVersion = OICStrdup(info.firmwareVersion);
1166     savedPlatformInfo.supportUrl = OICStrdup(info.supportUrl);
1167     savedPlatformInfo.systemTime = OICStrdup(info.systemTime);
1168
1169     if ((!savedPlatformInfo.platformID && info.platformID)||
1170         (!savedPlatformInfo.manufacturerName && info.manufacturerName)||
1171         (!savedPlatformInfo.manufacturerUrl && info.manufacturerUrl)||
1172         (!savedPlatformInfo.modelNumber && info.modelNumber)||
1173         (!savedPlatformInfo.dateOfManufacture && info.dateOfManufacture)||
1174         (!savedPlatformInfo.platformVersion && info.platformVersion)||
1175         (!savedPlatformInfo.operatingSystemVersion && info.operatingSystemVersion)||
1176         (!savedPlatformInfo.hardwareVersion && info.hardwareVersion)||
1177         (!savedPlatformInfo.firmwareVersion && info.firmwareVersion)||
1178         (!savedPlatformInfo.supportUrl && info.supportUrl)||
1179         (!savedPlatformInfo.systemTime && info.systemTime))
1180     {
1181         DeletePlatformInfo();
1182         return OC_STACK_INVALID_PARAM;
1183     }
1184
1185     return OC_STACK_OK;
1186
1187 }
1188
1189 OCStackResult SavePlatformInfo(OCPlatformInfo info)
1190 {
1191     DeletePlatformInfo();
1192
1193     OCStackResult res = DeepCopyPlatFormInfo(info);
1194
1195     if (res != OC_STACK_OK)
1196     {
1197         OIC_LOG_V(ERROR, TAG, "Failed to save platform info. errno(%d)", res);
1198     }
1199     else
1200     {
1201         OIC_LOG(INFO, TAG, "Platform info saved.");
1202     }
1203
1204     return res;
1205 }
1206
1207 void DeleteDeviceInfo()
1208 {
1209     OIC_LOG(INFO, TAG, "Deleting device info.");
1210
1211     OICFree(savedDeviceInfo.deviceName);
1212     savedDeviceInfo.deviceName = NULL;
1213 }
1214
1215 static OCStackResult DeepCopyDeviceInfo(OCDeviceInfo info)
1216 {
1217     savedDeviceInfo.deviceName = OICStrdup(info.deviceName);
1218
1219     if(!savedDeviceInfo.deviceName && info.deviceName)
1220     {
1221         DeleteDeviceInfo();
1222         return OC_STACK_NO_MEMORY;
1223     }
1224
1225     return OC_STACK_OK;
1226 }
1227
1228 OCStackResult SaveDeviceInfo(OCDeviceInfo info)
1229 {
1230     OCStackResult res = OC_STACK_OK;
1231
1232     DeleteDeviceInfo();
1233
1234     res = DeepCopyDeviceInfo(info);
1235
1236     VERIFY_SUCCESS(res, OC_STACK_OK);
1237
1238     if(OCGetServerInstanceID() == NULL)
1239     {
1240         OIC_LOG(INFO, TAG, "Device ID generation failed");
1241         res =  OC_STACK_ERROR;
1242         goto exit;
1243     }
1244
1245     OIC_LOG(INFO, TAG, "Device initialized successfully.");
1246     return OC_STACK_OK;
1247
1248 exit:
1249     DeleteDeviceInfo();
1250     return res;
1251 }