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