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     for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
314     {
315         if (resource->rsrcResources[i])
316         {
317             return 1;
318         }
319     }
320     return 0;
321 }
322
323 OCResource *FindResourceByUri(const char* resourceUri)
324 {
325     if(!resourceUri)
326     {
327         return NULL;
328     }
329
330     OCResource * pointer = headResource;
331     while (pointer)
332     {
333         if (strcmp(resourceUri, pointer->uri) == 0)
334         {
335             return pointer;
336         }
337         pointer = pointer->next;
338     }
339     OIC_LOG_V(INFO, TAG, "Resource %s not found", resourceUri);
340     return NULL;
341 }
342
343
344 OCStackResult DetermineResourceHandling (const OCServerRequest *request,
345                                          ResourceHandling *handling,
346                                          OCResource **resource)
347 {
348     if(!request || !handling || !resource)
349     {
350         return OC_STACK_INVALID_PARAM;
351     }
352
353     OIC_LOG_V(INFO, TAG, "DetermineResourceHandling for %s", request->resourceUrl);
354
355     // Check if virtual resource
356     if (GetTypeOfVirtualURI(request->resourceUrl) != OC_UNKNOWN_URI)
357     {
358         OIC_LOG_V (INFO, TAG, "%s is virtual", request->resourceUrl);
359         *handling = OC_RESOURCE_VIRTUAL;
360         *resource = headResource;
361         return OC_STACK_OK;
362     }
363     if (strlen((const char*)(request->resourceUrl)) == 0)
364     {
365         // Resource URL not specified
366         *handling = OC_RESOURCE_NOT_SPECIFIED;
367         return OC_STACK_NO_RESOURCE;
368     }
369     else
370     {
371         OCResource *resourcePtr = FindResourceByUri((const char*)request->resourceUrl);
372         *resource = resourcePtr;
373         if (!resourcePtr)
374         {
375             if(defaultDeviceHandler)
376             {
377                 *handling = OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER;
378                 return OC_STACK_OK;
379             }
380
381             // Resource does not exist
382             // and default device handler does not exist
383             *handling = OC_RESOURCE_NOT_SPECIFIED;
384             return OC_STACK_NO_RESOURCE;
385         }
386
387         if (IsCollectionResource (resourcePtr))
388         {
389             // Collection resource
390             if (resourcePtr->entityHandler != defaultResourceEHandler)
391             {
392                 *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER;
393                 return OC_STACK_OK;
394             }
395             else
396             {
397                 *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER;
398                 return OC_STACK_OK;
399             }
400         }
401         else
402         {
403             // Resource not a collection
404             if (resourcePtr->entityHandler != defaultResourceEHandler)
405             {
406                 *handling = OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER;
407                 return OC_STACK_OK;
408             }
409             else
410             {
411                 *handling = OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER;
412                 return OC_STACK_OK;
413             }
414         }
415     }
416 }
417
418 OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
419 {
420     OCStackResult result;
421
422     switch (ehResult)
423     {
424         case OC_EH_OK:
425             result = OC_STACK_OK;
426             break;
427         case OC_EH_SLOW:
428             result = OC_STACK_SLOW_RESOURCE;
429             break;
430         case OC_EH_ERROR:
431             result = OC_STACK_ERROR;
432             break;
433         case OC_EH_FORBIDDEN:
434             result = OC_STACK_RESOURCE_ERROR;
435             break;
436         case OC_EH_RESOURCE_CREATED:
437             result = OC_STACK_RESOURCE_CREATED;
438             break;
439         case OC_EH_RESOURCE_DELETED:
440             result = OC_STACK_RESOURCE_DELETED;
441             break;
442         case OC_EH_RESOURCE_NOT_FOUND:
443             result = OC_STACK_NO_RESOURCE;
444             break;
445         default:
446             result = OC_STACK_ERROR;
447     }
448
449     return result;
450 }
451
452 static bool resourceMatchesRTFilter(OCResource *resource, char *resourceTypeFilter)
453 {
454     if (!resource)
455     {
456         return false;
457     }
458
459     // Null or empty is analogous to no filter.
460     if (resourceTypeFilter == NULL || *resourceTypeFilter == 0)
461     {
462         return true;
463     }
464
465     OCResourceType *resourceTypePtr = resource->rsrcType;
466
467     while (resourceTypePtr)
468     {
469         if (strcmp (resourceTypePtr->resourcetypename, resourceTypeFilter) == 0)
470         {
471             return true;
472         }
473         resourceTypePtr = resourceTypePtr->next;
474     }
475
476     OIC_LOG_V(INFO, TAG, "%s does not contain rt=%s.", resource->uri, resourceTypeFilter);
477     return false;
478 }
479
480 static bool resourceMatchesIFFilter(OCResource *resource, char *interfaceFilter)
481 {
482     if (!resource)
483     {
484         return false;
485     }
486
487     // Null or empty is analogous to no filter.
488     if (interfaceFilter == NULL || *interfaceFilter == 0)
489     {
490         return true;
491     }
492
493     OCResourceInterface *interfacePtr = resource->rsrcInterface;
494
495     while (interfacePtr)
496     {
497         if (strcmp (interfacePtr->name, interfaceFilter) == 0)
498         {
499             return true;
500         }
501         interfacePtr = interfacePtr->next;
502     }
503
504     OIC_LOG_V(INFO, TAG, "%s does not contain if=%s.", resource->uri, interfaceFilter);
505     return false;
506 }
507
508 /*
509  * If the filters are null, they will be assumed to NOT be present
510  * and the resource will not be matched against them.
511  * Function will return true if all non null AND non empty filters passed in find a match.
512  */
513 static bool includeThisResourceInResponse(OCResource *resource,
514                                                  char *interfaceFilter,
515                                                  char *resourceTypeFilter)
516 {
517     if (!resource)
518     {
519         OIC_LOG(ERROR, TAG, "Invalid resource");
520         return false;
521     }
522
523     if ( resource->resourceProperties & OC_EXPLICIT_DISCOVERABLE)
524     {
525         /*
526          * At least one valid filter should be available to
527          * include the resource in discovery response
528          */
529         if (!((interfaceFilter && *interfaceFilter ) ||
530               (resourceTypeFilter && *resourceTypeFilter)))
531         {
532             OIC_LOG_V(INFO, TAG, "%s no query string for EXPLICIT_DISCOVERABLE \
533                 resource", resource->uri);
534             return false;
535         }
536     }
537     else if ( !(resource->resourceProperties & OC_ACTIVE) ||
538          !(resource->resourceProperties & OC_DISCOVERABLE))
539     {
540         OIC_LOG_V(INFO, TAG, "%s not ACTIVE or DISCOVERABLE", resource->uri);
541         return false;
542     }
543
544     return resourceMatchesIFFilter(resource, interfaceFilter) &&
545            resourceMatchesRTFilter(resource, resourceTypeFilter);
546
547 }
548
549 OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCResource *resource,
550                                 OCPayload *discoveryPayload, OCEntityHandlerResult ehResult)
551 {
552     OCEntityHandlerResponse response = {0};
553
554     response.ehResult = ehResult;
555     response.payload = discoveryPayload;
556     response.persistentBufferFlag = 0;
557     response.requestHandle = (OCRequestHandle) request;
558     response.resourceHandle = (OCResourceHandle) resource;
559
560     return OCDoResponse(&response);
561 }
562
563 #ifdef WITH_RD
564 static OCStackResult checkResourceExistsAtRD(const char *interfaceType, const char *resourceType,
565      OCResource **payload, OCDevAddr *devAddr)
566 {
567     OCResourceCollectionPayload *repPayload;
568     if (!payload)
569     {
570         return OC_STACK_ERROR;
571     }
572     if (OCRDCheckPublishedResource(interfaceType, resourceType, &repPayload, devAddr) == OC_STACK_OK)
573     {
574         if (!repPayload)
575         {
576             return OC_STACK_ERROR;
577         }
578         OCResource *ptr = ((OCResource *) OICCalloc(1, sizeof(OCResource)));
579         if (!ptr)
580         {
581            return OC_STACK_NO_MEMORY;
582         }
583
584         ptr->uri = OICStrdup(repPayload->setLinks->href);
585         if (!ptr->uri)
586         {
587            return OC_STACK_NO_MEMORY;
588         }
589         OCStringLL *rt = repPayload->setLinks->rt;
590         while (rt)
591         {
592             OCResourceType *temp = (OCResourceType *) OICCalloc(1, sizeof(OCResourceType));
593             if(!temp)
594             {
595                 OICFree(ptr->uri);
596                 return OC_STACK_NO_MEMORY;
597             }
598             temp->next = NULL;
599             temp->resourcetypename = OICStrdup(rt->value);
600             if (!ptr->rsrcType)
601             {
602                 ptr->rsrcType = temp;
603             }
604             else
605             {
606                 OCResourceType *type = ptr->rsrcType;
607                 while (type->next)
608                 {
609                     type = type->next;
610                 }
611                 type->next = temp;
612             }
613             rt = rt->next;
614         }
615
616         OCStringLL *itf = repPayload->setLinks->itf;
617         while (itf)
618         {
619             OCResourceInterface *temp = (OCResourceInterface *) OICCalloc(1, sizeof(OCResourceInterface));
620             if (!temp)
621             {
622                 OICFree(ptr->uri);
623
624                 return OC_STACK_NO_MEMORY;
625             }
626             temp->next = NULL;
627             temp->name = OICStrdup(itf->value);
628             if (!ptr->rsrcInterface)
629             {
630                 ptr->rsrcInterface = temp;
631             }
632             else
633             {
634                 OCResourceInterface *type = ptr->rsrcInterface;
635                 while (type->next)
636                 {
637                     type = type->next;
638                 }
639                 type->next = temp;
640             }
641             itf = itf->next;
642         }
643
644         ptr->resourceProperties = (OCResourceProperty) repPayload->tags->bitmap;
645
646         OCFreeCollectionResource(repPayload);
647         *payload = ptr;
648         return OC_STACK_OK;
649     }
650     else
651     {
652         OIC_LOG_V(ERROR, TAG, "The resource type or interface type doe not exist \
653                              on the resource directory");
654     }
655     return OC_STACK_ERROR;
656 }
657 #endif
658
659 static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource)
660 {
661     if (!request || !resource)
662     {
663         return OC_STACK_INVALID_PARAM;
664     }
665
666     OCStackResult discoveryResult = OC_STACK_ERROR;
667
668     bool bMulticast    = false;     // Was the discovery request a multicast request?
669     OCPayload* payload = NULL;
670
671     OIC_LOG(INFO, TAG, "Entering HandleVirtualResource");
672
673     OCVirtualResources virtualUriInRequest = GetTypeOfVirtualURI (request->resourceUrl);
674
675     // Step 1: Generate the response to discovery request
676     if (virtualUriInRequest == OC_WELL_KNOWN_URI)
677     {
678         char *filterOne = NULL;
679         char *filterTwo = NULL;
680
681         discoveryResult = getQueryParamsForFiltering (virtualUriInRequest, request->query,
682                 &filterOne, &filterTwo);
683
684         if (discoveryResult == OC_STACK_OK)
685         {
686             payload = (OCPayload*)OCDiscoveryPayloadCreate();
687
688             if(payload)
689             {
690                 ((OCDiscoveryPayload*)payload)->sid = (uint8_t*)OICCalloc(1, UUID_SIZE);
691                 memcpy(((OCDiscoveryPayload*)payload)->sid, OCGetServerInstanceID(), UUID_SIZE);
692
693                 bool foundResourceAtRD = false;
694                 for(;resource && discoveryResult == OC_STACK_OK; resource = resource->next)
695                 {
696 #ifdef WITH_RD
697                     if (strcmp(resource->uri, OC_RSRVD_RD_URI) == 0)
698                     {
699                         OCResource *resource = NULL;
700                         OCDevAddr devAddr;
701                         discoveryResult = checkResourceExistsAtRD(filterOne, filterTwo,
702                                                                   &resource, &devAddr);
703                         if (discoveryResult != OC_STACK_OK)
704                         {
705                              break;
706                         }
707                         discoveryResult = BuildVirtualResourceResponse(resource,
708                                     (OCDiscoveryPayload*)payload,
709                                     &devAddr, true);
710                         if (payload)
711                         {
712                             ((OCDiscoveryPayload*)payload)->baseURI = OICStrdup(devAddr.addr);
713                         }
714                         foundResourceAtRD = true;
715                     }
716 #endif
717                     if(!foundResourceAtRD && includeThisResourceInResponse(resource, filterOne, filterTwo))
718                     {
719                         discoveryResult = BuildVirtualResourceResponse(resource,
720                                 (OCDiscoveryPayload*)payload,
721                                 &request->devAddr, false);
722                     }
723                 }
724                 // Set discoveryResult appropriately if no 'valid' resources are available
725                 if (((OCDiscoveryPayload*)payload)->resources == NULL && !foundResourceAtRD)
726                 {
727                     discoveryResult = OC_STACK_NO_RESOURCE;
728                 }
729             }
730             else
731             {
732                 discoveryResult = OC_STACK_NO_MEMORY;
733             }
734         }
735         else
736         {
737             OIC_LOG_V(ERROR, TAG, "Error (%d) parsing query.", discoveryResult);
738         }
739     }
740     else if (virtualUriInRequest == OC_DEVICE_URI)
741     {
742         const OicUuid_t* deviceId = OCGetServerInstanceID();
743         if (!deviceId)
744         {
745             discoveryResult = OC_STACK_ERROR;
746         }
747         else
748         {
749             payload = (OCPayload*) OCDevicePayloadCreate((const uint8_t*) &deviceId->id, savedDeviceInfo.deviceName,
750                     OC_SPEC_VERSION, OC_DATA_MODEL_VERSION);
751             if (!payload)
752             {
753                 discoveryResult = OC_STACK_NO_MEMORY;
754             }
755             else
756             {
757                 discoveryResult = OC_STACK_OK;
758             }
759         }
760     }
761     else if (virtualUriInRequest == OC_PLATFORM_URI)
762     {
763         payload = (OCPayload*)OCPlatformPayloadCreate(&savedPlatformInfo);
764         if (!payload)
765         {
766             discoveryResult = OC_STACK_NO_MEMORY;
767         }
768         else
769         {
770             discoveryResult = OC_STACK_OK;
771         }
772     }
773 #ifdef ROUTING_GATEWAY
774     else if (OC_GATEWAY_URI == virtualUriInRequest)
775     {
776         // Received request for a gateway
777         OIC_LOG(INFO, TAG, "Request is for Gateway Virtual Request");
778         discoveryResult = RMHandleGatewayRequest(request, resource);
779
780     }
781 #endif
782
783     /**
784      * Step 2: Send the discovery response
785      *
786      * Iotivity should respond to discovery requests in below manner:
787      * 1)If query filter matching fails and discovery request is multicast,
788      *   it should NOT send any response.
789      * 2)If query filter matching fails and discovery request is unicast,
790      *   it should send an error(RESOURCE_NOT_FOUND - 404) response.
791      * 3)If Server does not have any 'DISCOVERABLE' resources and discovery
792      *   request is multicast, it should NOT send any response.
793      * 4)If Server does not have any 'DISCOVERABLE' resources and discovery
794      *   request is unicast, it should send an error(RESOURCE_NOT_FOUND - 404) response.
795      */
796
797 #ifdef WITH_PRESENCE
798     if ((virtualUriInRequest == OC_PRESENCE) &&
799         (resource->resourceProperties & OC_ACTIVE))
800     {
801         // Presence uses observer notification api to respond via SendPresenceNotification.
802         SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
803     }
804     else
805     #endif
806 #ifdef ROUTING_GATEWAY
807     // Gateway uses the RMHandleGatewayRequest to respond to the request.
808     if (OC_GATEWAY_URI != virtualUriInRequest)
809 #endif
810     {
811         if(discoveryResult == OC_STACK_OK)
812         {
813             SendNonPersistantDiscoveryResponse(request, resource, payload, OC_EH_OK);
814         }
815         else if(bMulticast == false && (request->devAddr.adapter != OC_ADAPTER_RFCOMM_BTEDR) &&
816                (request->devAddr.adapter != OC_ADAPTER_GATT_BTLE))
817         {
818             OIC_LOG_V(ERROR, TAG, "Sending a (%d) error to (%d)  \
819                 discovery request", discoveryResult, virtualUriInRequest);
820             SendNonPersistantDiscoveryResponse(request, resource, NULL,
821                 (discoveryResult == OC_STACK_NO_RESOURCE) ? OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR);
822         }
823         else
824         {
825             // Ignoring the discovery request as per RFC 7252, Section #8.2
826             OIC_LOG(INFO, TAG, "Silently ignoring the request since device does not have \
827                 any useful data to send");
828         }
829     }
830
831     OCPayloadDestroy(payload);
832
833     return OC_STACK_OK;
834 }
835
836 static OCStackResult
837 HandleDefaultDeviceEntityHandler (OCServerRequest *request)
838 {
839     if(!request)
840     {
841         return OC_STACK_INVALID_PARAM;
842     }
843
844     OCStackResult result = OC_STACK_OK;
845     OCEntityHandlerResult ehResult = OC_EH_ERROR;
846     OCEntityHandlerRequest ehRequest = {0};
847
848     OIC_LOG(INFO, TAG, "Entering HandleResourceWithDefaultDeviceEntityHandler");
849     result = FormOCEntityHandlerRequest(&ehRequest,
850                                         (OCRequestHandle) request,
851                                         request->method,
852                                         &request->devAddr,
853                                         (OCResourceHandle) NULL, request->query,
854                                         PAYLOAD_TYPE_REPRESENTATION,
855                                         request->payload,
856                                         request->payloadSize,
857                                         request->numRcvdVendorSpecificHeaderOptions,
858                                         request->rcvdVendorSpecificHeaderOptions,
859                                         (OCObserveAction)request->observationOption,
860                                         (OCObservationId)0);
861     VERIFY_SUCCESS(result, OC_STACK_OK);
862
863     // At this point we know for sure that defaultDeviceHandler exists
864     ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
865                                   (char*) request->resourceUrl, defaultDeviceHandlerCallbackParameter);
866     if(ehResult == OC_EH_SLOW)
867     {
868         OIC_LOG(INFO, TAG, "This is a slow resource");
869         request->slowFlag = 1;
870     }
871     else if(ehResult == OC_EH_ERROR)
872     {
873         FindAndDeleteServerRequest(request);
874     }
875     result = EntityHandlerCodeToOCStackCode(ehResult);
876 exit:
877     OCPayloadDestroy(ehRequest.payload);
878     return result;
879 }
880
881 static OCStackResult
882 HandleResourceWithEntityHandler (OCServerRequest *request,
883                                  OCResource *resource,
884                                  uint8_t collectionResource)
885 {
886     if(!request || ! resource)
887     {
888         return OC_STACK_INVALID_PARAM;
889     }
890
891     OCStackResult result = OC_STACK_ERROR;
892     OCEntityHandlerResult ehResult = OC_EH_ERROR;
893     OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
894     ResourceObserver *resObs = NULL;
895
896     OCEntityHandlerRequest ehRequest = {0};
897
898     OIC_LOG(INFO, TAG, "Entering HandleResourceWithEntityHandler");
899     OCPayloadType type = PAYLOAD_TYPE_REPRESENTATION;
900     // check the security resource
901     if (request && request->resourceUrl && SRMIsSecurityResourceURI(request->resourceUrl))
902     {
903         type = PAYLOAD_TYPE_SECURITY;
904
905     }
906
907     if (request && strcmp(request->resourceUrl, OC_RSRVD_RD_URI) == 0)
908     {
909         type = PAYLOAD_TYPE_RD;
910     }
911
912     result = FormOCEntityHandlerRequest(&ehRequest,
913                                         (OCRequestHandle)request,
914                                         request->method,
915                                         &request->devAddr,
916                                         (OCResourceHandle)resource,
917                                         request->query,
918                                         type,
919                                         request->payload,
920                                         request->payloadSize,
921                                         request->numRcvdVendorSpecificHeaderOptions,
922                                         request->rcvdVendorSpecificHeaderOptions,
923                                         (OCObserveAction)request->observationOption,
924                                         0);
925     VERIFY_SUCCESS(result, OC_STACK_OK);
926
927     if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
928     {
929         OIC_LOG(INFO, TAG, "No observation requested");
930         ehFlag = OC_REQUEST_FLAG;
931     }
932     else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER && !collectionResource)
933     {
934         OIC_LOG(INFO, TAG, "Observation registration requested");
935
936         ResourceObserver *obs = GetObserverUsingToken (request->requestToken,
937                                     request->tokenLength);
938
939         if (obs)
940         {
941             OIC_LOG (INFO, TAG, "Observer with this token already present");
942             OIC_LOG (INFO, TAG, "Possibly re-transmitted CON OBS request");
943             OIC_LOG (INFO, TAG, "Not adding observer. Not responding to client");
944             OIC_LOG (INFO, TAG, "The first request for this token is already ACKED.");
945
946             // server requests are usually free'd when the response is sent out
947             // for the request in ocserverrequest.c : HandleSingleResponse()
948             // Since we are making an early return and not responding, the server request
949             // needs to be deleted.
950             FindAndDeleteServerRequest (request);
951             return OC_STACK_OK;
952         }
953
954         result = GenerateObserverId(&ehRequest.obsInfo.obsId);
955         VERIFY_SUCCESS(result, OC_STACK_OK);
956
957         result = AddObserver ((const char*)(request->resourceUrl),
958                 (const char *)(request->query),
959                 ehRequest.obsInfo.obsId, request->requestToken, request->tokenLength,
960                 resource, request->qos, request->acceptFormat,
961                 &request->devAddr);
962
963         if(result == OC_STACK_OK)
964         {
965             OIC_LOG(INFO, TAG, "Added observer successfully");
966             request->observeResult = OC_STACK_OK;
967             ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
968         }
969         else
970         {
971             result = OC_STACK_OK;
972
973             // The error in observeResult for the request will be used when responding to this
974             // request by omitting the observation option/sequence number.
975             request->observeResult = OC_STACK_ERROR;
976             OIC_LOG(ERROR, TAG, "Observer Addition failed");
977             ehFlag = OC_REQUEST_FLAG;
978         }
979
980     }
981     else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER &&
982             !collectionResource)
983     {
984         OIC_LOG(INFO, TAG, "Deregistering observation requested");
985
986         resObs = GetObserverUsingToken (request->requestToken, request->tokenLength);
987
988         if (NULL == resObs)
989         {
990             // Stack does not contain this observation request
991             // Either token is incorrect or observation list is corrupted
992             result = OC_STACK_ERROR;
993             goto exit;
994         }
995         ehRequest.obsInfo.obsId = resObs->observeId;
996         ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
997
998         result = DeleteObserverUsingToken (request->requestToken, request->tokenLength);
999
1000         if(result == OC_STACK_OK)
1001         {
1002             OIC_LOG(INFO, TAG, "Removed observer successfully");
1003             request->observeResult = OC_STACK_OK;
1004         }
1005         else
1006         {
1007             result = OC_STACK_OK;
1008             request->observeResult = OC_STACK_ERROR;
1009             OIC_LOG(ERROR, TAG, "Observer Removal failed");
1010         }
1011     }
1012     else
1013     {
1014         result = OC_STACK_ERROR;
1015         goto exit;
1016     }
1017
1018     ehResult = resource->entityHandler(ehFlag, &ehRequest, resource->entityHandlerCallbackParam);
1019     if(ehResult == OC_EH_SLOW)
1020     {
1021         OIC_LOG(INFO, TAG, "This is a slow resource");
1022         request->slowFlag = 1;
1023     }
1024     else if(ehResult == OC_EH_ERROR)
1025     {
1026         FindAndDeleteServerRequest(request);
1027     }
1028     result = EntityHandlerCodeToOCStackCode(ehResult);
1029 exit:
1030     OCPayloadDestroy(ehRequest.payload);
1031     return result;
1032 }
1033
1034 static OCStackResult
1035 HandleCollectionResourceDefaultEntityHandler (OCServerRequest *request,
1036                                               OCResource *resource)
1037 {
1038     if(!request || !resource)
1039     {
1040         return OC_STACK_INVALID_PARAM;
1041     }
1042
1043     OCStackResult result = OC_STACK_ERROR;
1044     OCEntityHandlerRequest ehRequest = {0};
1045
1046     result = FormOCEntityHandlerRequest(&ehRequest,
1047                                         (OCRequestHandle)request,
1048                                         request->method,
1049                                         &request->devAddr,
1050                                         (OCResourceHandle)resource,
1051                                         request->query,
1052                                         PAYLOAD_TYPE_REPRESENTATION,
1053                                         request->payload,
1054                                         request->payloadSize,
1055                                         request->numRcvdVendorSpecificHeaderOptions,
1056                                         request->rcvdVendorSpecificHeaderOptions,
1057                                         (OCObserveAction)request->observationOption,
1058                                         (OCObservationId)0);
1059     if(result == OC_STACK_OK)
1060     {
1061         result = DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest);
1062     }
1063
1064     OCPayloadDestroy(ehRequest.payload);
1065     return result;
1066 }
1067
1068 OCStackResult
1069 ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request)
1070 {
1071     OCStackResult ret = OC_STACK_OK;
1072
1073     switch (resHandling)
1074     {
1075         case OC_RESOURCE_VIRTUAL:
1076         {
1077             ret = HandleVirtualResource (request, resource);
1078             break;
1079         }
1080         case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER:
1081         {
1082             ret = HandleDefaultDeviceEntityHandler(request);
1083             break;
1084         }
1085         case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
1086         {
1087             OIC_LOG(INFO, TAG, "OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER");
1088             return OC_STACK_ERROR;
1089         }
1090         case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
1091         {
1092             ret = HandleResourceWithEntityHandler (request, resource, 0);
1093             break;
1094         }
1095         case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
1096         {
1097             ret = HandleResourceWithEntityHandler (request, resource, 1);
1098             break;
1099         }
1100         case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
1101         {
1102             ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
1103             break;
1104         }
1105         case OC_RESOURCE_NOT_SPECIFIED:
1106         {
1107             ret = OC_STACK_NO_RESOURCE;
1108             break;
1109         }
1110         default:
1111         {
1112             OIC_LOG(INFO, TAG, "Invalid Resource Determination");
1113             return OC_STACK_ERROR;
1114         }
1115     }
1116     return ret;
1117 }
1118
1119 void DeletePlatformInfo()
1120 {
1121     OIC_LOG(INFO, TAG, "Deleting platform info.");
1122
1123     OICFree(savedPlatformInfo.platformID);
1124     savedPlatformInfo.platformID = NULL;
1125
1126     OICFree(savedPlatformInfo.manufacturerName);
1127     savedPlatformInfo.manufacturerName = NULL;
1128
1129     OICFree(savedPlatformInfo.manufacturerUrl);
1130     savedPlatformInfo.manufacturerUrl = NULL;
1131
1132     OICFree(savedPlatformInfo.modelNumber);
1133     savedPlatformInfo.modelNumber = NULL;
1134
1135     OICFree(savedPlatformInfo.dateOfManufacture);
1136     savedPlatformInfo.dateOfManufacture = NULL;
1137
1138     OICFree(savedPlatformInfo.platformVersion);
1139     savedPlatformInfo.platformVersion = NULL;
1140
1141     OICFree(savedPlatformInfo.operatingSystemVersion);
1142     savedPlatformInfo.operatingSystemVersion = NULL;
1143
1144     OICFree(savedPlatformInfo.hardwareVersion);
1145     savedPlatformInfo.hardwareVersion = NULL;
1146
1147     OICFree(savedPlatformInfo.firmwareVersion);
1148     savedPlatformInfo.firmwareVersion = NULL;
1149
1150     OICFree(savedPlatformInfo.supportUrl);
1151     savedPlatformInfo.supportUrl = NULL;
1152
1153     OICFree(savedPlatformInfo.systemTime);
1154     savedPlatformInfo.systemTime = NULL;
1155 }
1156
1157 static OCStackResult DeepCopyPlatFormInfo(OCPlatformInfo info)
1158 {
1159     savedPlatformInfo.platformID = OICStrdup(info.platformID);
1160     savedPlatformInfo.manufacturerName = OICStrdup(info.manufacturerName);
1161     savedPlatformInfo.manufacturerUrl = OICStrdup(info.manufacturerUrl);
1162     savedPlatformInfo.modelNumber = OICStrdup(info.modelNumber);
1163     savedPlatformInfo.dateOfManufacture = OICStrdup(info.dateOfManufacture);
1164     savedPlatformInfo.platformVersion = OICStrdup(info.platformVersion);
1165     savedPlatformInfo.operatingSystemVersion = OICStrdup(info.operatingSystemVersion);
1166     savedPlatformInfo.hardwareVersion = OICStrdup(info.hardwareVersion);
1167     savedPlatformInfo.firmwareVersion = OICStrdup(info.firmwareVersion);
1168     savedPlatformInfo.supportUrl = OICStrdup(info.supportUrl);
1169     savedPlatformInfo.systemTime = OICStrdup(info.systemTime);
1170
1171     if ((!savedPlatformInfo.platformID && info.platformID)||
1172         (!savedPlatformInfo.manufacturerName && info.manufacturerName)||
1173         (!savedPlatformInfo.manufacturerUrl && info.manufacturerUrl)||
1174         (!savedPlatformInfo.modelNumber && info.modelNumber)||
1175         (!savedPlatformInfo.dateOfManufacture && info.dateOfManufacture)||
1176         (!savedPlatformInfo.platformVersion && info.platformVersion)||
1177         (!savedPlatformInfo.operatingSystemVersion && info.operatingSystemVersion)||
1178         (!savedPlatformInfo.hardwareVersion && info.hardwareVersion)||
1179         (!savedPlatformInfo.firmwareVersion && info.firmwareVersion)||
1180         (!savedPlatformInfo.supportUrl && info.supportUrl)||
1181         (!savedPlatformInfo.systemTime && info.systemTime))
1182     {
1183         DeletePlatformInfo();
1184         return OC_STACK_INVALID_PARAM;
1185     }
1186
1187     return OC_STACK_OK;
1188
1189 }
1190
1191 OCStackResult SavePlatformInfo(OCPlatformInfo info)
1192 {
1193     DeletePlatformInfo();
1194
1195     OCStackResult res = DeepCopyPlatFormInfo(info);
1196
1197     if (res != OC_STACK_OK)
1198     {
1199         OIC_LOG_V(ERROR, TAG, "Failed to save platform info. errno(%d)", res);
1200     }
1201     else
1202     {
1203         OIC_LOG(INFO, TAG, "Platform info saved.");
1204     }
1205
1206     return res;
1207 }
1208
1209 void DeleteDeviceInfo()
1210 {
1211     OIC_LOG(INFO, TAG, "Deleting device info.");
1212
1213     OICFree(savedDeviceInfo.deviceName);
1214     savedDeviceInfo.deviceName = NULL;
1215 }
1216
1217 static OCStackResult DeepCopyDeviceInfo(OCDeviceInfo info)
1218 {
1219     savedDeviceInfo.deviceName = OICStrdup(info.deviceName);
1220
1221     if(!savedDeviceInfo.deviceName && info.deviceName)
1222     {
1223         DeleteDeviceInfo();
1224         return OC_STACK_NO_MEMORY;
1225     }
1226
1227     return OC_STACK_OK;
1228 }
1229
1230 OCStackResult SaveDeviceInfo(OCDeviceInfo info)
1231 {
1232     OCStackResult res = OC_STACK_OK;
1233
1234     DeleteDeviceInfo();
1235
1236     res = DeepCopyDeviceInfo(info);
1237
1238     VERIFY_SUCCESS(res, OC_STACK_OK);
1239
1240     if(OCGetServerInstanceID() == NULL)
1241     {
1242         OIC_LOG(INFO, TAG, "Device ID generation failed");
1243         res =  OC_STACK_ERROR;
1244         goto exit;
1245     }
1246
1247     OIC_LOG(INFO, TAG, "Device initialized successfully.");
1248     return OC_STACK_OK;
1249
1250 exit:
1251     DeleteDeviceInfo();
1252     return res;
1253 }