d33849931f8755d4f0f702fde80569e6313bae24
[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 *interfaceQuery = NULL;
677         char *resourceTypeQuery = NULL;
678
679         discoveryResult = getQueryParamsForFiltering (virtualUriInRequest, request->query,
680                 &interfaceQuery, &resourceTypeQuery);
681
682         if (discoveryResult == OC_STACK_OK)
683         {
684             payload = (OCPayload *)OCDiscoveryPayloadCreate();
685
686             if (payload)
687             {
688                 ((OCDiscoveryPayload*)payload)->sid = (char *)OICCalloc(1, UUID_STRING_SIZE);
689                 VERIFY_NON_NULL(((OCDiscoveryPayload*)payload)->sid, ERROR, OC_STACK_NO_MEMORY);
690                 memcpy(((OCDiscoveryPayload*)payload)->sid, OCGetServerInstanceIDString(), UUID_STRING_SIZE);
691
692                 if (interfaceQuery && 0 == strcmp(OC_RSRVD_INTERFACE_LL, interfaceQuery))
693                 {
694                     for (; resource && discoveryResult == OC_STACK_OK; resource = resource->next)
695                     {
696                         discoveryResult = BuildVirtualResourceResponse(resource,
697                                 (OCDiscoveryPayload *)payload, &request->devAddr, false);
698                     }
699                 }
700                 else
701                 {
702                     bool foundResourceAtRD = false;
703                     for (;resource && discoveryResult == OC_STACK_OK; resource = resource->next)
704                     {
705 #ifdef WITH_RD
706                         if (strcmp(resource->uri, OC_RSRVD_RD_URI) == 0)
707                         {
708                             OCResource *resource1 = NULL;
709                             OCDevAddr devAddr;
710                             discoveryResult = checkResourceExistsAtRD(interfaceQuery,
711                                 resourceTypeQuery, &resource1, &devAddr);
712                             if (discoveryResult != OC_STACK_OK)
713                             {
714                                  break;
715                             }
716                             discoveryResult = BuildVirtualResourceResponse(resource1,
717                                 (OCDiscoveryPayload*)payload, &devAddr, true);
718                             if (payload)
719                             {
720                                 ((OCDiscoveryPayload*)payload)->baseURI = OICStrdup(devAddr.addr);
721                             }
722                             OCDiscoveryResourceDestroy(resource1);
723                             foundResourceAtRD = true;
724                         }
725 #endif
726                         if (!foundResourceAtRD && includeThisResourceInResponse(resource, interfaceQuery, resourceTypeQuery))
727                         {
728                             discoveryResult = BuildVirtualResourceResponse(resource,
729                                 (OCDiscoveryPayload*)payload, &request->devAddr, false);
730                         }
731                     }
732                     // Set discoveryResult appropriately if no 'valid' resources are available
733                     if (((OCDiscoveryPayload*)payload)->resources == NULL && !foundResourceAtRD)
734                     {
735                         discoveryResult = OC_STACK_NO_RESOURCE;
736                     }
737                 }
738             }
739             else
740             {
741                 discoveryResult = OC_STACK_NO_MEMORY;
742             }
743         }
744         else
745         {
746             OIC_LOG_V(ERROR, TAG, "Error (%d) parsing query.", discoveryResult);
747         }
748     }
749     else if (virtualUriInRequest == OC_DEVICE_URI)
750     {
751         const char* deviceId = OCGetServerInstanceIDString();
752         if (!deviceId)
753         {
754             discoveryResult = OC_STACK_ERROR;
755         }
756         else
757         {
758             payload = (OCPayload*) OCDevicePayloadCreate(deviceId, savedDeviceInfo.deviceName,
759                     OC_SPEC_VERSION, OC_DATA_MODEL_VERSION);
760             if (!payload)
761             {
762                 discoveryResult = OC_STACK_NO_MEMORY;
763             }
764             else
765             {
766                 discoveryResult = OC_STACK_OK;
767             }
768         }
769     }
770     else if (virtualUriInRequest == OC_PLATFORM_URI)
771     {
772         payload = (OCPayload*)OCPlatformPayloadCreate(&savedPlatformInfo);
773         if (!payload)
774         {
775             discoveryResult = OC_STACK_NO_MEMORY;
776         }
777         else
778         {
779             discoveryResult = OC_STACK_OK;
780         }
781     }
782 #ifdef ROUTING_GATEWAY
783     else if (OC_GATEWAY_URI == virtualUriInRequest)
784     {
785         // Received request for a gateway
786         OIC_LOG(INFO, TAG, "Request is for Gateway Virtual Request");
787         discoveryResult = RMHandleGatewayRequest(request, resource);
788
789     }
790 #endif
791
792     /**
793      * Step 2: Send the discovery response
794      *
795      * Iotivity should respond to discovery requests in below manner:
796      * 1)If query filter matching fails and discovery request is multicast,
797      *   it should NOT send any response.
798      * 2)If query filter matching fails and discovery request is unicast,
799      *   it should send an error(RESOURCE_NOT_FOUND - 404) response.
800      * 3)If Server does not have any 'DISCOVERABLE' resources and discovery
801      *   request is multicast, it should NOT send any response.
802      * 4)If Server does not have any 'DISCOVERABLE' resources and discovery
803      *   request is unicast, it should send an error(RESOURCE_NOT_FOUND - 404) response.
804      */
805
806 #ifdef WITH_PRESENCE
807     if ((virtualUriInRequest == OC_PRESENCE) &&
808         (resource->resourceProperties & OC_ACTIVE))
809     {
810         // Presence uses observer notification api to respond via SendPresenceNotification.
811         SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
812     }
813     else
814     #endif
815 #ifdef ROUTING_GATEWAY
816     // Gateway uses the RMHandleGatewayRequest to respond to the request.
817     if (OC_GATEWAY_URI != virtualUriInRequest)
818 #endif
819     {
820         if(discoveryResult == OC_STACK_OK)
821         {
822             SendNonPersistantDiscoveryResponse(request, resource, payload, OC_EH_OK);
823         }
824         else if(bMulticast == false && (request->devAddr.adapter != OC_ADAPTER_RFCOMM_BTEDR) &&
825                (request->devAddr.adapter != OC_ADAPTER_GATT_BTLE))
826         {
827             OIC_LOG_V(ERROR, TAG, "Sending a (%d) error to (%d)  \
828                 discovery request", discoveryResult, virtualUriInRequest);
829             SendNonPersistantDiscoveryResponse(request, resource, NULL,
830                 (discoveryResult == OC_STACK_NO_RESOURCE) ? OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR);
831         }
832         else
833         {
834             // Ignoring the discovery request as per RFC 7252, Section #8.2
835             OIC_LOG(INFO, TAG, "Silently ignoring the request since device does not have \
836                 any useful data to send");
837         }
838     }
839
840     OCPayloadDestroy(payload);
841
842     return OC_STACK_OK;
843 }
844
845 static OCStackResult
846 HandleDefaultDeviceEntityHandler (OCServerRequest *request)
847 {
848     if(!request)
849     {
850         return OC_STACK_INVALID_PARAM;
851     }
852
853     OCStackResult result = OC_STACK_OK;
854     OCEntityHandlerResult ehResult = OC_EH_ERROR;
855     OCEntityHandlerRequest ehRequest = {0};
856
857     OIC_LOG(INFO, TAG, "Entering HandleResourceWithDefaultDeviceEntityHandler");
858     result = FormOCEntityHandlerRequest(&ehRequest,
859                                         (OCRequestHandle) request,
860                                         request->method,
861                                         &request->devAddr,
862                                         (OCResourceHandle) NULL, request->query,
863                                         PAYLOAD_TYPE_REPRESENTATION,
864                                         request->payload,
865                                         request->payloadSize,
866                                         request->numRcvdVendorSpecificHeaderOptions,
867                                         request->rcvdVendorSpecificHeaderOptions,
868                                         (OCObserveAction)request->observationOption,
869                                         (OCObservationId)0);
870     VERIFY_SUCCESS(result, OC_STACK_OK);
871
872     // At this point we know for sure that defaultDeviceHandler exists
873     ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
874                                   (char*) request->resourceUrl, defaultDeviceHandlerCallbackParameter);
875     if(ehResult == OC_EH_SLOW)
876     {
877         OIC_LOG(INFO, TAG, "This is a slow resource");
878         request->slowFlag = 1;
879     }
880     else if(ehResult == OC_EH_ERROR)
881     {
882         FindAndDeleteServerRequest(request);
883     }
884     result = EntityHandlerCodeToOCStackCode(ehResult);
885 exit:
886     OCPayloadDestroy(ehRequest.payload);
887     return result;
888 }
889
890 static OCStackResult
891 HandleResourceWithEntityHandler (OCServerRequest *request,
892                                  OCResource *resource,
893                                  uint8_t collectionResource)
894 {
895     if(!request || ! resource)
896     {
897         return OC_STACK_INVALID_PARAM;
898     }
899
900     OCStackResult result = OC_STACK_ERROR;
901     OCEntityHandlerResult ehResult = OC_EH_ERROR;
902     OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
903     ResourceObserver *resObs = NULL;
904
905     OCEntityHandlerRequest ehRequest = {0};
906
907     OIC_LOG(INFO, TAG, "Entering HandleResourceWithEntityHandler");
908     OCPayloadType type = PAYLOAD_TYPE_REPRESENTATION;
909     // check the security resource
910     if (request && request->resourceUrl && SRMIsSecurityResourceURI(request->resourceUrl))
911     {
912         type = PAYLOAD_TYPE_SECURITY;
913
914     }
915
916     if (request && strcmp(request->resourceUrl, OC_RSRVD_RD_URI) == 0)
917     {
918         type = PAYLOAD_TYPE_RD;
919     }
920
921     result = FormOCEntityHandlerRequest(&ehRequest,
922                                         (OCRequestHandle)request,
923                                         request->method,
924                                         &request->devAddr,
925                                         (OCResourceHandle)resource,
926                                         request->query,
927                                         type,
928                                         request->payload,
929                                         request->payloadSize,
930                                         request->numRcvdVendorSpecificHeaderOptions,
931                                         request->rcvdVendorSpecificHeaderOptions,
932                                         (OCObserveAction)request->observationOption,
933                                         0);
934     VERIFY_SUCCESS(result, OC_STACK_OK);
935
936     if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
937     {
938         OIC_LOG(INFO, TAG, "No observation requested");
939         ehFlag = OC_REQUEST_FLAG;
940     }
941     else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER && !collectionResource)
942     {
943         OIC_LOG(INFO, TAG, "Observation registration requested");
944
945         ResourceObserver *obs = GetObserverUsingToken (request->requestToken,
946                                     request->tokenLength);
947
948         if (obs)
949         {
950             OIC_LOG (INFO, TAG, "Observer with this token already present");
951             OIC_LOG (INFO, TAG, "Possibly re-transmitted CON OBS request");
952             OIC_LOG (INFO, TAG, "Not adding observer. Not responding to client");
953             OIC_LOG (INFO, TAG, "The first request for this token is already ACKED.");
954
955             // server requests are usually free'd when the response is sent out
956             // for the request in ocserverrequest.c : HandleSingleResponse()
957             // Since we are making an early return and not responding, the server request
958             // needs to be deleted.
959             FindAndDeleteServerRequest (request);
960             return OC_STACK_OK;
961         }
962
963         result = GenerateObserverId(&ehRequest.obsInfo.obsId);
964         VERIFY_SUCCESS(result, OC_STACK_OK);
965
966         result = AddObserver ((const char*)(request->resourceUrl),
967                 (const char *)(request->query),
968                 ehRequest.obsInfo.obsId, request->requestToken, request->tokenLength,
969                 resource, request->qos, request->acceptFormat,
970                 &request->devAddr);
971
972         if(result == OC_STACK_OK)
973         {
974             OIC_LOG(INFO, TAG, "Added observer successfully");
975             request->observeResult = OC_STACK_OK;
976             ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
977         }
978         else
979         {
980             result = OC_STACK_OK;
981
982             // The error in observeResult for the request will be used when responding to this
983             // request by omitting the observation option/sequence number.
984             request->observeResult = OC_STACK_ERROR;
985             OIC_LOG(ERROR, TAG, "Observer Addition failed");
986             ehFlag = OC_REQUEST_FLAG;
987         }
988
989     }
990     else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER &&
991             !collectionResource)
992     {
993         OIC_LOG(INFO, TAG, "Deregistering observation requested");
994
995         resObs = GetObserverUsingToken (request->requestToken, request->tokenLength);
996
997         if (NULL == resObs)
998         {
999             // Stack does not contain this observation request
1000             // Either token is incorrect or observation list is corrupted
1001             result = OC_STACK_ERROR;
1002             goto exit;
1003         }
1004         ehRequest.obsInfo.obsId = resObs->observeId;
1005         ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
1006
1007         result = DeleteObserverUsingToken (request->requestToken, request->tokenLength);
1008
1009         if(result == OC_STACK_OK)
1010         {
1011             OIC_LOG(INFO, TAG, "Removed observer successfully");
1012             request->observeResult = OC_STACK_OK;
1013         }
1014         else
1015         {
1016             result = OC_STACK_OK;
1017             request->observeResult = OC_STACK_ERROR;
1018             OIC_LOG(ERROR, TAG, "Observer Removal failed");
1019         }
1020     }
1021     else
1022     {
1023         result = OC_STACK_ERROR;
1024         goto exit;
1025     }
1026
1027     ehResult = resource->entityHandler(ehFlag, &ehRequest, resource->entityHandlerCallbackParam);
1028     if(ehResult == OC_EH_SLOW)
1029     {
1030         OIC_LOG(INFO, TAG, "This is a slow resource");
1031         request->slowFlag = 1;
1032     }
1033     else if(ehResult == OC_EH_ERROR)
1034     {
1035         FindAndDeleteServerRequest(request);
1036     }
1037     result = EntityHandlerCodeToOCStackCode(ehResult);
1038 exit:
1039     OCPayloadDestroy(ehRequest.payload);
1040     return result;
1041 }
1042
1043 static OCStackResult
1044 HandleCollectionResourceDefaultEntityHandler (OCServerRequest *request,
1045                                               OCResource *resource)
1046 {
1047     if(!request || !resource)
1048     {
1049         return OC_STACK_INVALID_PARAM;
1050     }
1051
1052     OCStackResult result = OC_STACK_ERROR;
1053     OCEntityHandlerRequest ehRequest = {0};
1054
1055     result = FormOCEntityHandlerRequest(&ehRequest,
1056                                         (OCRequestHandle)request,
1057                                         request->method,
1058                                         &request->devAddr,
1059                                         (OCResourceHandle)resource,
1060                                         request->query,
1061                                         PAYLOAD_TYPE_REPRESENTATION,
1062                                         request->payload,
1063                                         request->payloadSize,
1064                                         request->numRcvdVendorSpecificHeaderOptions,
1065                                         request->rcvdVendorSpecificHeaderOptions,
1066                                         (OCObserveAction)request->observationOption,
1067                                         (OCObservationId)0);
1068     if(result == OC_STACK_OK)
1069     {
1070         result = DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest);
1071     }
1072
1073     OCPayloadDestroy(ehRequest.payload);
1074     return result;
1075 }
1076
1077 OCStackResult
1078 ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request)
1079 {
1080     OCStackResult ret = OC_STACK_OK;
1081
1082     switch (resHandling)
1083     {
1084         case OC_RESOURCE_VIRTUAL:
1085         {
1086             ret = HandleVirtualResource (request, resource);
1087             break;
1088         }
1089         case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER:
1090         {
1091             ret = HandleDefaultDeviceEntityHandler(request);
1092             break;
1093         }
1094         case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
1095         {
1096             OIC_LOG(INFO, TAG, "OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER");
1097             return OC_STACK_ERROR;
1098         }
1099         case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
1100         {
1101             ret = HandleResourceWithEntityHandler (request, resource, 0);
1102             break;
1103         }
1104         case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
1105         {
1106             ret = HandleResourceWithEntityHandler (request, resource, 1);
1107             break;
1108         }
1109         case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
1110         {
1111             ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
1112             break;
1113         }
1114         case OC_RESOURCE_NOT_SPECIFIED:
1115         {
1116             ret = OC_STACK_NO_RESOURCE;
1117             break;
1118         }
1119         default:
1120         {
1121             OIC_LOG(INFO, TAG, "Invalid Resource Determination");
1122             return OC_STACK_ERROR;
1123         }
1124     }
1125     return ret;
1126 }
1127
1128 void DeletePlatformInfo()
1129 {
1130     OIC_LOG(INFO, TAG, "Deleting platform info.");
1131
1132     OICFree(savedPlatformInfo.platformID);
1133     savedPlatformInfo.platformID = NULL;
1134
1135     OICFree(savedPlatformInfo.manufacturerName);
1136     savedPlatformInfo.manufacturerName = NULL;
1137
1138     OICFree(savedPlatformInfo.manufacturerUrl);
1139     savedPlatformInfo.manufacturerUrl = NULL;
1140
1141     OICFree(savedPlatformInfo.modelNumber);
1142     savedPlatformInfo.modelNumber = NULL;
1143
1144     OICFree(savedPlatformInfo.dateOfManufacture);
1145     savedPlatformInfo.dateOfManufacture = NULL;
1146
1147     OICFree(savedPlatformInfo.platformVersion);
1148     savedPlatformInfo.platformVersion = NULL;
1149
1150     OICFree(savedPlatformInfo.operatingSystemVersion);
1151     savedPlatformInfo.operatingSystemVersion = NULL;
1152
1153     OICFree(savedPlatformInfo.hardwareVersion);
1154     savedPlatformInfo.hardwareVersion = NULL;
1155
1156     OICFree(savedPlatformInfo.firmwareVersion);
1157     savedPlatformInfo.firmwareVersion = NULL;
1158
1159     OICFree(savedPlatformInfo.supportUrl);
1160     savedPlatformInfo.supportUrl = NULL;
1161
1162     OICFree(savedPlatformInfo.systemTime);
1163     savedPlatformInfo.systemTime = NULL;
1164 }
1165
1166 static OCStackResult DeepCopyPlatFormInfo(OCPlatformInfo info)
1167 {
1168     savedPlatformInfo.platformID = OICStrdup(info.platformID);
1169     savedPlatformInfo.manufacturerName = OICStrdup(info.manufacturerName);
1170     savedPlatformInfo.manufacturerUrl = OICStrdup(info.manufacturerUrl);
1171     savedPlatformInfo.modelNumber = OICStrdup(info.modelNumber);
1172     savedPlatformInfo.dateOfManufacture = OICStrdup(info.dateOfManufacture);
1173     savedPlatformInfo.platformVersion = OICStrdup(info.platformVersion);
1174     savedPlatformInfo.operatingSystemVersion = OICStrdup(info.operatingSystemVersion);
1175     savedPlatformInfo.hardwareVersion = OICStrdup(info.hardwareVersion);
1176     savedPlatformInfo.firmwareVersion = OICStrdup(info.firmwareVersion);
1177     savedPlatformInfo.supportUrl = OICStrdup(info.supportUrl);
1178     savedPlatformInfo.systemTime = OICStrdup(info.systemTime);
1179
1180     if ((!savedPlatformInfo.platformID && info.platformID)||
1181         (!savedPlatformInfo.manufacturerName && info.manufacturerName)||
1182         (!savedPlatformInfo.manufacturerUrl && info.manufacturerUrl)||
1183         (!savedPlatformInfo.modelNumber && info.modelNumber)||
1184         (!savedPlatformInfo.dateOfManufacture && info.dateOfManufacture)||
1185         (!savedPlatformInfo.platformVersion && info.platformVersion)||
1186         (!savedPlatformInfo.operatingSystemVersion && info.operatingSystemVersion)||
1187         (!savedPlatformInfo.hardwareVersion && info.hardwareVersion)||
1188         (!savedPlatformInfo.firmwareVersion && info.firmwareVersion)||
1189         (!savedPlatformInfo.supportUrl && info.supportUrl)||
1190         (!savedPlatformInfo.systemTime && info.systemTime))
1191     {
1192         DeletePlatformInfo();
1193         return OC_STACK_INVALID_PARAM;
1194     }
1195
1196     return OC_STACK_OK;
1197
1198 }
1199
1200 OCStackResult SavePlatformInfo(OCPlatformInfo info)
1201 {
1202     DeletePlatformInfo();
1203
1204     OCStackResult res = DeepCopyPlatFormInfo(info);
1205
1206     if (res != OC_STACK_OK)
1207     {
1208         OIC_LOG_V(ERROR, TAG, "Failed to save platform info. errno(%d)", res);
1209     }
1210     else
1211     {
1212         OIC_LOG(INFO, TAG, "Platform info saved.");
1213     }
1214
1215     return res;
1216 }
1217
1218 void DeleteDeviceInfo()
1219 {
1220     OIC_LOG(INFO, TAG, "Deleting device info.");
1221
1222     OICFree(savedDeviceInfo.deviceName);
1223     savedDeviceInfo.deviceName = NULL;
1224 }
1225
1226 static OCStackResult DeepCopyDeviceInfo(OCDeviceInfo info)
1227 {
1228     savedDeviceInfo.deviceName = OICStrdup(info.deviceName);
1229
1230     if(!savedDeviceInfo.deviceName && info.deviceName)
1231     {
1232         DeleteDeviceInfo();
1233         return OC_STACK_NO_MEMORY;
1234     }
1235
1236     return OC_STACK_OK;
1237 }
1238
1239 OCStackResult SaveDeviceInfo(OCDeviceInfo info)
1240 {
1241     OCStackResult res = OC_STACK_OK;
1242
1243     DeleteDeviceInfo();
1244
1245     res = DeepCopyDeviceInfo(info);
1246
1247     VERIFY_SUCCESS(res, OC_STACK_OK);
1248
1249     if (OCGetServerInstanceIDString() == NULL)
1250     {
1251         OIC_LOG(INFO, TAG, "Device ID generation failed");
1252         res =  OC_STACK_ERROR;
1253         goto exit;
1254     }
1255
1256     OIC_LOG(INFO, TAG, "Device initialized successfully.");
1257     return OC_STACK_OK;
1258
1259 exit:
1260     DeleteDeviceInfo();
1261     return res;
1262 }