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 static char* GetJSONStringFromPlatformInfo(OCPlatformInfo info)
108 {
109     cJSON *rootObj = cJSON_CreateObject();
110
111     if (!rootObj)
112     {
113         return NULL;
114     }
115
116     cJSON *repObj = NULL;
117     char *jsonEncodedInfo = NULL;
118
119     cJSON_AddItemToObject (rootObj, OC_RSRVD_HREF,
120             cJSON_CreateString(GetVirtualResourceUri(OC_PLATFORM_URI)));
121
122     cJSON_AddItemToObject (rootObj, OC_RSRVD_REPRESENTATION, repObj = cJSON_CreateObject());
123
124     if (!repObj)
125     {
126         return NULL;
127     }
128     if (info.platformID)
129     {
130         cJSON_AddItemToObject (repObj, OC_RSRVD_PLATFORM_ID,
131                 cJSON_CreateString(info.platformID));
132     }
133
134     if (info.manufacturerName)
135     {
136         cJSON_AddItemToObject (repObj, OC_RSRVD_MFG_NAME,
137                 cJSON_CreateString(info.manufacturerName));
138     }
139
140     if (info.manufacturerUrl)
141     {
142         cJSON_AddItemToObject (repObj, OC_RSRVD_MFG_URL,
143                 cJSON_CreateString(info.manufacturerUrl));
144     }
145
146     if (info.modelNumber)
147     {
148         cJSON_AddItemToObject (repObj, OC_RSRVD_MODEL_NUM,
149                 cJSON_CreateString(info.modelNumber));
150     }
151
152     if (info.dateOfManufacture)
153     {
154         cJSON_AddItemToObject (repObj, OC_RSRVD_MFG_DATE,
155                 cJSON_CreateString(info.dateOfManufacture));
156     }
157
158     if (info.platformVersion)
159     {
160         cJSON_AddItemToObject (repObj, OC_RSRVD_PLATFORM_VERSION,
161                 cJSON_CreateString(info.platformVersion));
162     }
163
164     if (info.operatingSystemVersion)
165     {
166         cJSON_AddItemToObject (repObj, OC_RSRVD_OS_VERSION,
167                 cJSON_CreateString(info.operatingSystemVersion));
168     }
169
170     if (info.hardwareVersion)
171     {
172         cJSON_AddItemToObject (repObj, OC_RSRVD_HARDWARE_VERSION,
173                 cJSON_CreateString(info.hardwareVersion));
174     }
175
176     if (info.firmwareVersion)
177     {
178         cJSON_AddItemToObject (repObj, OC_RSRVD_FIRMWARE_VERSION,
179                 cJSON_CreateString(info.firmwareVersion));
180     }
181
182     if (info.supportUrl)
183     {
184         cJSON_AddItemToObject (repObj, OC_RSRVD_SUPPORT_URL,
185                 cJSON_CreateString(info.supportUrl));
186     }
187
188     if (info.systemTime)
189     {
190         cJSON_AddItemToObject (repObj, OC_RSRVD_SYSTEM_TIME,
191                 cJSON_CreateString(info.systemTime));
192     }
193
194     jsonEncodedInfo = cJSON_PrintUnformatted (rootObj);
195
196     cJSON_Delete(rootObj);
197
198     return jsonEncodedInfo;
199 }
200
201 static char* GetJSONStringFromDeviceInfo(OCDeviceInfo info)
202 {
203     cJSON *rootObj = cJSON_CreateObject();
204
205     if (!rootObj)
206     {
207         return NULL;
208     }
209
210     cJSON *repObj = NULL;
211     char *jsonEncodedInfo = NULL;
212
213     cJSON_AddItemToObject (rootObj, OC_RSRVD_HREF,
214             cJSON_CreateString(GetVirtualResourceUri(OC_DEVICE_URI)));
215
216     cJSON_AddItemToObject (rootObj, OC_RSRVD_REPRESENTATION, repObj = cJSON_CreateObject());
217
218     if (!repObj)
219     {
220         return NULL;
221     }
222
223     cJSON_AddItemToObject (repObj, OC_RSRVD_DEVICE_ID,
224                     cJSON_CreateString(OCGetServerInstanceIDString()));
225
226     if (info.deviceName)
227     {
228         cJSON_AddItemToObject (repObj, OC_RSRVD_DEVICE_NAME,
229                         cJSON_CreateString(info.deviceName));
230     }
231
232     cJSON_AddItemToObject (repObj, OC_RSRVD_SPEC_VERSION,
233                         cJSON_CreateString(OC_SPEC_VERSION));
234
235     cJSON_AddItemToObject (repObj, OC_RSRVD_DATA_MODEL_VERSION,
236                         cJSON_CreateString(OC_DATA_MODEL_VERSION));
237
238     jsonEncodedInfo = cJSON_PrintUnformatted (rootObj);
239
240     cJSON_Delete(rootObj);
241
242     return jsonEncodedInfo;
243 }
244
245 static OCStackResult ValidateUrlQuery (char *url, char *query,
246                                 uint8_t *filterOn, char **filterValue)
247 {
248     if(!filterOn || !filterValue)
249     {
250         return OC_STACK_INVALID_PARAM;
251     }
252
253     char *filterParam = NULL;
254
255     OC_LOG(INFO, TAG, PCF("Entering ValidateUrlQuery"));
256     if (!url)
257     {
258         return OC_STACK_INVALID_URI;
259     }
260
261     if (strcmp ((char *)url, GetVirtualResourceUri(OC_WELL_KNOWN_URI)) == 0 ||
262                 strcmp ((char *)url, GetVirtualResourceUri(OC_DEVICE_URI)) == 0 ||
263                 strcmp((char *)url, GetVirtualResourceUri(OC_PLATFORM_URI)) == 0)
264     {
265         *filterOn = STACK_RES_DISCOVERY_NOFILTER;
266         if (query && *query)
267         {
268             char* strTokPtr = NULL;
269             filterParam = strtok_r((char *)query, "=", &strTokPtr);
270             *filterValue = strtok_r(NULL, " ", &strTokPtr);
271
272             if (!(*filterValue) || ! filterParam)
273             {
274                 return OC_STACK_INVALID_QUERY;
275             }
276             else if (strcmp (filterParam, OC_RSRVD_INTERFACE) == 0)
277             {
278                 // Resource discovery with interface filter
279                 *filterOn = STACK_RES_DISCOVERY_IF_FILTER;
280             }
281             else if (strcmp (filterParam, OC_RSRVD_RESOURCE_TYPE) == 0)
282             {
283                 // Resource discovery with resource type filter
284                 *filterOn = STACK_RES_DISCOVERY_RT_FILTER;
285             }
286             else if (strcmp (filterParam, OC_RSRVD_DEVICE_ID) == 0)
287             {
288                 //Device ID filter
289                 *filterOn = STACK_DEVICE_DISCOVERY_DI_FILTER;
290             }
291             else if (strcmp (filterParam, OC_RSRVD_DEVICE_NAME) == 0)
292             {
293                 //Device Name filter
294                 *filterOn = STACK_DEVICE_DISCOVERY_DN_FILTER;
295             }
296             else
297             {
298                 // Other filter types not supported
299                 return OC_STACK_INVALID_QUERY;
300             }
301         }
302     }
303     #ifdef WITH_PRESENCE
304     else if (strcmp((char *)url, GetVirtualResourceUri(OC_PRESENCE)) == 0)
305     {
306         //Nothing needs to be done, except for pass a OC_PRESENCE query through as OC_STACK_OK.
307         OC_LOG(INFO, TAG, PCF("OC_PRESENCE Request"));
308         *filterOn = STACK_RES_DISCOVERY_NOFILTER;
309     }
310     #endif
311     else
312     {
313         // Other URIs not yet supported
314         return OC_STACK_INVALID_URI;
315     }
316     OC_LOG(INFO, TAG, PCF("Exiting ValidateUrlQuery"));
317     return OC_STACK_OK;
318 }
319
320
321 OCStackResult
322 BuildVirtualResourceResponse(const OCResource *resourcePtr, uint8_t filterOn,
323                        const char *filterValue, char *out, uint16_t *remaining,
324                        CATransportAdapter_t adapter)
325 {
326     if(!resourcePtr || !out  || !remaining)
327     {
328         return OC_STACK_INVALID_PARAM;
329     }
330
331     OCResourceType *resourceTypePtr = NULL;
332     OCResourceInterface *interfacePtr = NULL;
333     cJSON *resObj = NULL;
334     cJSON *propObj = NULL;
335     cJSON *policyObj = NULL;
336     cJSON *rtArray = NULL;
337     char *jsonStr = NULL;
338     uint8_t encodeRes = 0;
339     OCStackResult ret = OC_STACK_OK;
340     uint16_t jsonLen = 0;
341
342     OC_LOG(INFO, TAG, PCF("Entering BuildVirtualResourceResponse"));
343     resObj = cJSON_CreateObject();
344
345     if (resourcePtr)
346     {
347         encodeRes = 0;
348         if ((filterOn == STACK_RES_DISCOVERY_RT_FILTER) && filterValue)
349         {
350             resourceTypePtr = resourcePtr->rsrcType;
351             while (resourceTypePtr)
352             {
353                 if (strcmp (resourceTypePtr->resourcetypename, filterValue) == 0)
354                 {
355                     encodeRes = 1;
356                     break;
357                 }
358                 resourceTypePtr = resourceTypePtr->next;
359             }
360         }
361         else if ((filterOn == STACK_RES_DISCOVERY_IF_FILTER) && filterValue)
362         {
363             interfacePtr = resourcePtr->rsrcInterface;
364             while (interfacePtr)
365             {
366                 if (strcmp (interfacePtr->name, filterValue) == 0)
367                 {
368                     encodeRes = 1;
369                     break;
370                 }
371                 interfacePtr = interfacePtr->next;
372             }
373         }
374         else if (filterOn == STACK_RES_DISCOVERY_NOFILTER)
375         {
376             encodeRes = 1;
377         }
378         else
379         {
380             //TODO: Unsupported query filter
381             return OC_STACK_INVALID_QUERY;
382         }
383
384         if (encodeRes)
385         {
386             // Add URIs
387             cJSON_AddItemToObject(resObj, OC_RSRVD_HREF, cJSON_CreateString(resourcePtr->uri));
388
389             // Add server instance id
390             cJSON_AddItemToObject(resObj,
391                                    OC_RSRVD_SERVER_INSTANCE_ID,
392                                    cJSON_CreateString(OCGetServerInstanceIDString()));
393
394
395             cJSON_AddItemToObject (resObj, OC_RSRVD_PROPERTY, propObj = cJSON_CreateObject());
396             // Add resource types
397             cJSON_AddItemToObject(propObj, OC_RSRVD_RESOURCE_TYPE, rtArray = cJSON_CreateArray());
398             resourceTypePtr = resourcePtr->rsrcType;
399             while (resourceTypePtr)
400             {
401                 cJSON_AddItemToArray(rtArray,
402                                       cJSON_CreateString(resourceTypePtr->resourcetypename));
403                 resourceTypePtr = resourceTypePtr->next;
404             }
405             // Add interface types
406             cJSON_AddItemToObject(propObj, OC_RSRVD_INTERFACE, rtArray = cJSON_CreateArray());
407             interfacePtr = resourcePtr->rsrcInterface;
408             while (interfacePtr)
409             {
410                 cJSON_AddItemToArray(rtArray, cJSON_CreateString(interfacePtr->name));
411                 interfacePtr = interfacePtr->next;
412             }
413
414             //Add Policy
415             cJSON_AddItemToObject(propObj, OC_RSRVD_POLICY, policyObj = cJSON_CreateObject());
416
417             if (policyObj)
418             {
419                 // Policy Property Bitmap
420                 // If resource is discoverable, set discoverability flag.
421                 // Resources that are not discoverable will not have the flag.
422                 cJSON_AddNumberToObject(policyObj, OC_RSRVD_BITMAP,
423                                  resourcePtr->resourceProperties & (OC_OBSERVABLE|OC_DISCOVERABLE));
424
425                 // Set secure flag for secure resources
426                 if (resourcePtr->resourceProperties & OC_SECURE)
427                 {
428                     cJSON_AddNumberToObject(policyObj, OC_RSRVD_SECURE, OC_RESOURCE_SECURE);
429                     //Set the IP port also as secure resources are hosted on a different port
430                     uint16_t port = 0;
431                     if (GetSecurePortInfo(adapter, &port) == OC_STACK_OK)
432                     {
433                         cJSON_AddNumberToObject(policyObj, OC_RSRVD_HOSTING_PORT, port);
434                     }
435                 }
436             }
437             else
438             {
439                 cJSON_Delete(resObj);
440                 return OC_STACK_NO_MEMORY;
441             }
442         }
443     }
444     jsonStr = cJSON_PrintUnformatted (resObj);
445
446     if(!jsonStr)
447     {
448         cJSON_Delete(resObj);
449         return OC_STACK_NO_MEMORY;
450     }
451
452     jsonLen = strlen(jsonStr);
453     if (jsonLen < *remaining)
454     {
455         OICStrcpy(out, *remaining, jsonStr);
456         *remaining = *remaining - jsonLen;
457     }
458     else
459     {
460         ret = OC_STACK_ERROR;
461     }
462     cJSON_Delete (resObj);
463     OICFree (jsonStr);
464
465     OC_LOG(INFO, TAG, PCF("Exiting BuildVirtualResourceResponse"));
466     return ret;
467 }
468
469 OCStackResult BuildVirtualResourceResponseForDevice(uint8_t filterOn, char *filterValue,
470                                                     char *out, uint16_t *remaining)
471 {
472     if(!out || !remaining)
473     {
474         return OC_STACK_INVALID_PARAM;
475     }
476
477     OCStackResult ret = OC_STACK_ERROR;
478     char *jsonStr = NULL;
479     uint16_t jsonLen = 0;
480
481     jsonStr = GetJSONStringFromDeviceInfo(savedDeviceInfo);
482
483     if(jsonStr)
484     {
485         jsonLen = strlen(jsonStr);
486
487         if (jsonLen < *remaining)
488         {
489             OICStrcpy(out, *remaining, jsonStr);
490             *remaining = *remaining - jsonLen;
491             ret = OC_STACK_OK;
492         }
493         else
494         {
495             ret = OC_STACK_ERROR;
496         }
497
498         OICFree(jsonStr);
499     }
500     else
501     {
502         OC_LOG(ERROR, TAG, PCF("Error encoding save device info."));
503         ret = OC_STACK_ERROR;
504     }
505     return ret;
506 }
507
508 OCStackResult BuildVirtualResourceResponseForPlatform(char *out, uint16_t *remaining)
509 {
510     OCStackResult ret = OC_STACK_OK;
511
512     char *jsonStr = GetJSONStringFromPlatformInfo(savedPlatformInfo);
513
514     if(jsonStr)
515     {
516         size_t jsonLen = strlen(jsonStr);
517
518         if (jsonLen < *remaining)
519         {
520             OICStrcpy(out, *remaining, jsonStr);
521             *remaining = *remaining - jsonLen;
522             ret = OC_STACK_OK;
523         }
524         else
525         {
526             OC_LOG_V(ERROR, TAG, PCF("Platform info string too big. len: %u"), jsonLen);
527             ret = OC_STACK_ERROR;
528         }
529         OICFree(jsonStr);
530     }
531     else
532     {
533         OC_LOG(ERROR, TAG, PCF("Error encoding save platform info."));
534         ret = OC_STACK_ERROR;
535     }
536
537
538     return ret;
539
540 }
541 const char * GetVirtualResourceUri( OCVirtualResources resource)
542 {
543     if (resource < OC_MAX_VIRTUAL_RESOURCES)
544     {
545         return VIRTUAL_RSRCS[resource];
546     }
547
548     return NULL;
549 }
550
551 bool IsVirtualResource(const char* resourceUri)
552 {
553     if(!resourceUri)
554     {
555         return false;
556     }
557
558     for (int i = 0; i < OC_MAX_VIRTUAL_RESOURCES; i++)
559     {
560         if (strcmp(resourceUri, GetVirtualResourceUri((OCVirtualResources)i)) == 0)
561         {
562             return true;
563         }
564     }
565     return false;
566 }
567
568 uint8_t IsCollectionResource (OCResource *resource)
569 {
570     if(!resource)
571     {
572         return 0;
573     }
574
575     for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
576     {
577         if (resource->rsrcResources[i])
578         {
579             return 1;
580         }
581     }
582     return 0;
583 }
584
585 OCResource *FindResourceByUri(const char* resourceUri)
586 {
587     if(!resourceUri)
588     {
589         return NULL;
590     }
591
592     OCResource * pointer = headResource;
593     while (pointer)
594     {
595         if (strcmp(resourceUri, pointer->uri) == 0)
596         {
597             return pointer;
598         }
599         pointer = pointer->next;
600     }
601     OC_LOG(INFO, TAG, PCF("Resource not found"));
602     return NULL;
603 }
604
605
606 OCStackResult DetermineResourceHandling (const OCServerRequest *request,
607                                          ResourceHandling *handling,
608                                          OCResource **resource)
609 {
610     if(!request || !handling || !resource)
611     {
612         return OC_STACK_INVALID_PARAM;
613     }
614
615     OC_LOG(INFO, TAG, PCF("Entering DetermineResourceHandling"));
616
617     const OCDevAddr *devAddr = &request->devAddr;
618
619     // Check if virtual resource
620     if (IsVirtualResource((const char*)request->resourceUrl))
621     {
622         *handling = OC_RESOURCE_VIRTUAL;
623         *resource = headResource;
624         return OC_STACK_OK;
625     }
626     if (strlen((const char*)(request->resourceUrl)) == 0)
627     {
628         // Resource URL not specified
629         *handling = OC_RESOURCE_NOT_SPECIFIED;
630         return OC_STACK_NO_RESOURCE;
631     }
632     else
633     {
634         OCResource *resourcePtr = NULL;
635         resourcePtr = FindResourceByUri((const char*)request->resourceUrl);
636         *resource = resourcePtr;
637         if (!resourcePtr)
638         {
639             if(defaultDeviceHandler)
640             {
641                 *handling = OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER;
642                 return OC_STACK_OK;
643             }
644
645             // Resource does not exist
646             // and default device handler does not exist
647             *handling = OC_RESOURCE_NOT_SPECIFIED;
648             return OC_STACK_NO_RESOURCE;
649         }
650
651         // secure resource will entertain only authorized requests
652         if ((resourcePtr->resourceProperties & OC_SECURE) && ((devAddr->flags & OC_FLAG_SECURE) == 0))
653         {
654             OC_LOG(ERROR, TAG, PCF("Un-authorized request. Ignoring"));
655             return OC_STACK_RESOURCE_ERROR;
656         }
657
658         if (IsCollectionResource (resourcePtr))
659         {
660             // Collection resource
661             if (resourcePtr->entityHandler != defaultResourceEHandler)
662             {
663                 *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER;
664                 return OC_STACK_OK;
665             }
666             else
667             {
668                 *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER;
669                 return OC_STACK_OK;
670             }
671         }
672         else
673         {
674             // Resource not a collection
675             if (resourcePtr->entityHandler != defaultResourceEHandler)
676             {
677                 *handling = OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER;
678                 return OC_STACK_OK;
679             }
680             else
681             {
682                 *handling = OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER;
683                 return OC_STACK_OK;
684             }
685         }
686     }
687 }
688
689 OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
690 {
691     OCStackResult result;
692
693     switch (ehResult)
694     {
695         case OC_EH_OK:
696             result = OC_STACK_OK;
697             break;
698         case OC_EH_SLOW:
699             result = OC_STACK_SLOW_RESOURCE;
700             break;
701         case OC_EH_ERROR:
702             result = OC_STACK_ERROR;
703             break;
704         case OC_EH_FORBIDDEN:
705             result = OC_STACK_RESOURCE_ERROR;
706             break;
707         case OC_EH_RESOURCE_CREATED:
708             result = OC_STACK_RESOURCE_CREATED;
709             break;
710         case OC_EH_RESOURCE_DELETED:
711             result = OC_STACK_RESOURCE_DELETED;
712             break;
713         case OC_EH_RESOURCE_NOT_FOUND:
714             result = OC_STACK_NO_RESOURCE;
715             break;
716         default:
717             result = OC_STACK_ERROR;
718     }
719
720     return result;
721 }
722
723 static OCStackResult
724 HandleVirtualResource(OCServerRequest *request, OCResource *resource)
725 {
726     if (!request || !resource)
727     {
728         return OC_STACK_INVALID_PARAM;
729     }
730
731     OCStackResult result = OC_STACK_ERROR;
732     char *filterValue = NULL;
733     uint8_t filterOn = 0;
734     uint16_t remaining = 0;
735     char * ptr = NULL;
736     uint8_t firstLoopDone = 0;
737     char discoveryResBuf[MAX_RESPONSE_LENGTH] = {};
738
739     OC_LOG(INFO, TAG, PCF("Entering HandleVirtualResource"));
740
741     result = ValidateUrlQuery (request->resourceUrl,
742             request->query, &filterOn,
743             &filterValue);
744
745     if (result == OC_STACK_OK)
746     {
747         if (strcmp ((char *)request->resourceUrl, GetVirtualResourceUri(OC_WELL_KNOWN_URI)) == 0)
748         {
749             ptr = discoveryResBuf;
750             remaining = MAX_RESPONSE_LENGTH;
751
752             // Check if valid resource and enough space in buffer for atleast
753             // the null character.
754             while(resource && (remaining > 1))
755             {
756                 if((resource->resourceProperties & OC_ACTIVE)
757                         && (resource->resourceProperties & OC_DISCOVERABLE))
758                 {
759                     // if there is data on the buffer, we have already added a response,
760                     // so we need to add a comma before we do anything
761                     if(firstLoopDone
762                             && remaining >= (sizeof(OC_JSON_SEPARATOR)+1))
763                     {
764                         *ptr = OC_JSON_SEPARATOR;
765                         ptr++;
766                         remaining--;
767                     }
768                     firstLoopDone = 1;
769                     result = BuildVirtualResourceResponse(resource, filterOn,
770                                 filterValue, (char*)ptr, &remaining,
771                                 (CATransportAdapter_t)request->devAddr.adapter);
772
773                     if (result != OC_STACK_OK)
774                     {
775                         // if this failed, we need to remove the comma added above.
776                         if(firstLoopDone)
777                         {
778                             ptr--;
779                             *ptr = '\0';
780                             remaining++;
781                         }
782                         break;
783                     }
784                     ptr += strlen((char *)ptr);
785                 }
786                 resource = resource->next;
787             }
788
789             if(strlen((const char *)discoveryResBuf) > 0)
790             {
791                 OCEntityHandlerResponse response = {};
792
793                 response.ehResult = OC_EH_OK;
794                 response.payload = discoveryResBuf;
795                 response.payloadSize = strlen((const char *)discoveryResBuf) + 1;
796                 response.persistentBufferFlag = 0;
797                 response.requestHandle = (OCRequestHandle) request;
798                 response.resourceHandle = (OCResourceHandle) resource;
799
800                 result = OCDoResponse(&response);
801             }
802         }
803         else if (strcmp ((char *)request->resourceUrl, GetVirtualResourceUri(OC_DEVICE_URI)) == 0)
804         {
805             remaining = MAX_RESPONSE_LENGTH;
806             ptr = discoveryResBuf;
807
808             result = BuildVirtualResourceResponseForDevice(filterOn, filterValue,
809                     (char*)ptr, &remaining);
810
811             if(result == OC_STACK_OK)
812             {
813                 ptr += strlen((char*)ptr);
814             }
815
816             if(remaining < MAX_RESPONSE_LENGTH)
817             {
818                 OCEntityHandlerResponse response = {0};
819
820                 response.ehResult = OC_EH_OK;
821                 response.payload = discoveryResBuf;
822                 response.payloadSize = strlen((const char *)discoveryResBuf) + 1;
823                 response.persistentBufferFlag = 0;
824                 response.requestHandle = (OCRequestHandle) request;
825                 response.resourceHandle = (OCResourceHandle) resource;
826
827                 result = OCDoResponse(&response);
828             }
829         }
830         else if (strcmp ((char *)request->resourceUrl, GetVirtualResourceUri(OC_PLATFORM_URI)) == 0)
831         {
832             remaining = MAX_RESPONSE_LENGTH;
833             ptr = discoveryResBuf;
834
835             result = BuildVirtualResourceResponseForPlatform((char*)ptr, &remaining);
836
837             if(result == OC_STACK_OK)
838             {
839                 ptr += strlen((char*)ptr);
840             }
841
842             if(remaining < MAX_RESPONSE_LENGTH)
843             {
844                 OCEntityHandlerResponse response = {0};
845
846                 response.ehResult = OC_EH_OK;
847                 response.payload = discoveryResBuf;
848                 response.payloadSize = strlen((const char *)discoveryResBuf) + 1;
849                 response.persistentBufferFlag = 0;
850                 response.requestHandle = (OCRequestHandle) request;
851                 response.resourceHandle = (OCResourceHandle) resource;
852
853                 result = OCDoResponse(&response);
854             }
855         }
856         #ifdef WITH_PRESENCE
857         else
858         {
859             if(resource->resourceProperties & OC_ACTIVE){
860                 SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE);
861             }
862         }
863         #endif
864     }
865     result = OC_STACK_OK;
866     return result;
867 }
868
869 static OCStackResult
870 HandleDefaultDeviceEntityHandler (OCServerRequest *request)
871 {
872     if(!request)
873     {
874         return OC_STACK_INVALID_PARAM;
875     }
876
877     OCStackResult result = OC_STACK_OK;
878     OCEntityHandlerResult ehResult = OC_EH_ERROR;
879     OCEntityHandlerRequest ehRequest = {};
880
881     OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithDefaultDeviceEntityHandler"));
882     result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
883             request->method, (OCResourceHandle) NULL, request->query,
884             request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
885             request->rcvdVendorSpecificHeaderOptions,
886             (OCObserveAction)request->observationOption, (OCObservationId)0);
887     VERIFY_SUCCESS(result, OC_STACK_OK);
888
889     // At this point we know for sure that defaultDeviceHandler exists
890     ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
891                                   (char*) request->resourceUrl, defaultDeviceHandlerCallbackParameter);
892     if(ehResult == OC_EH_SLOW)
893     {
894         OC_LOG(INFO, TAG, PCF("This is a slow resource"));
895         request->slowFlag = 1;
896     }
897     else if(ehResult == OC_EH_ERROR)
898     {
899         FindAndDeleteServerRequest(request);
900     }
901     result = EntityHandlerCodeToOCStackCode(ehResult);
902 exit:
903     return result;
904 }
905
906 static OCStackResult
907 HandleResourceWithEntityHandler (OCServerRequest *request,
908                                  OCResource *resource,
909                                  uint8_t collectionResource)
910 {
911     if(!request || ! resource)
912     {
913         return OC_STACK_INVALID_PARAM;
914     }
915
916     OCStackResult result = OC_STACK_ERROR;
917     OCEntityHandlerResult ehResult = OC_EH_ERROR;
918     OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
919     ResourceObserver *resObs = NULL;
920
921     OCEntityHandlerRequest ehRequest = {};
922
923     OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithEntityHandler"));
924     result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
925             request->method, (OCResourceHandle) resource, request->query,
926             request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
927             request->rcvdVendorSpecificHeaderOptions,
928             (OCObserveAction)request->observationOption, 0);
929     VERIFY_SUCCESS(result, OC_STACK_OK);
930
931     if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
932     {
933         OC_LOG(INFO, TAG, PCF("No observation requested"));
934         ehFlag = OC_REQUEST_FLAG;
935     }
936     else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER &&
937             !collectionResource)
938     {
939         OC_LOG(INFO, TAG, PCF("Registering observation requested"));
940         result = GenerateObserverId(&ehRequest.obsInfo.obsId);
941         VERIFY_SUCCESS(result, OC_STACK_OK);
942
943         result = AddObserver ((const char*)(request->resourceUrl),
944                 (const char *)(request->query),
945                 ehRequest.obsInfo.obsId, request->requestToken, request->tokenLength,
946                 resource, request->qos,
947                 &request->devAddr);
948
949         if(result == OC_STACK_OK)
950         {
951             OC_LOG(INFO, TAG, PCF("Added observer successfully"));
952             request->observeResult = OC_STACK_OK;
953             ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
954         }
955         else
956         {
957             result = OC_STACK_OK;
958             // The error in observeResult for the request will be
959             // used when responding to this request by omitting
960             // the observation option/sequence number.
961             request->observeResult = OC_STACK_ERROR;
962             OC_LOG(ERROR, TAG, PCF("Observer Addition failed"));
963             ehFlag = OC_REQUEST_FLAG;
964         }
965
966     }
967     else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER &&
968             !collectionResource)
969     {
970         OC_LOG(INFO, TAG, PCF("Deregistering observation requested"));
971
972         resObs = GetObserverUsingToken (request->requestToken, request->tokenLength);
973
974         if (NULL == resObs)
975         {
976             // Stack does not contain this observation request
977             // Either token is incorrect or observation list is corrupted
978             result = OC_STACK_ERROR;
979             goto exit;
980         }
981         ehRequest.obsInfo.obsId = resObs->observeId;
982         ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
983
984         result = DeleteObserverUsingToken (request->requestToken, request->tokenLength);
985
986         if(result == OC_STACK_OK)
987         {
988             OC_LOG(INFO, TAG, PCF("Removed observer successfully"));
989             request->observeResult = OC_STACK_OK;
990         }
991         else
992         {
993             result = OC_STACK_OK;
994             request->observeResult = OC_STACK_ERROR;
995             OC_LOG(ERROR, TAG, PCF("Observer Removal failed"));
996         }
997     }
998     else
999     {
1000         result = OC_STACK_ERROR;
1001         goto exit;
1002     }
1003
1004     ehResult = resource->entityHandler(ehFlag, &ehRequest, resource->entityHandlerCallbackParam);
1005     if(ehResult == OC_EH_SLOW)
1006     {
1007         OC_LOG(INFO, TAG, PCF("This is a slow resource"));
1008         request->slowFlag = 1;
1009     }
1010     else if(ehResult == OC_EH_ERROR)
1011     {
1012         FindAndDeleteServerRequest(request);
1013     }
1014     result = EntityHandlerCodeToOCStackCode(ehResult);
1015 exit:
1016     return result;
1017 }
1018
1019 static OCStackResult
1020 HandleCollectionResourceDefaultEntityHandler (OCServerRequest *request,
1021                                               OCResource *resource)
1022 {
1023     if(!request || !resource)
1024     {
1025         return OC_STACK_INVALID_PARAM;
1026     }
1027
1028     OCStackResult result = OC_STACK_ERROR;
1029     OCEntityHandlerRequest ehRequest = {};
1030
1031     result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
1032             request->method, (OCResourceHandle) resource, request->query,
1033             request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
1034             request->rcvdVendorSpecificHeaderOptions,
1035             (OCObserveAction)request->observationOption, (OCObservationId) 0);
1036     if(result != OC_STACK_OK)
1037     {
1038         return result;
1039     }
1040
1041     return (DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest));
1042 }
1043
1044 OCStackResult
1045 ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request)
1046 {
1047     OCStackResult ret = OC_STACK_OK;
1048
1049     switch (resHandling)
1050     {
1051         case OC_RESOURCE_VIRTUAL:
1052         {
1053             ret = HandleVirtualResource (request, resource);
1054             break;
1055         }
1056         case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER:
1057         {
1058             ret = HandleDefaultDeviceEntityHandler(request);
1059             break;
1060         }
1061         case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
1062         {
1063             OC_LOG(INFO, TAG, PCF("OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER"));
1064             return OC_STACK_ERROR;
1065         }
1066         case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
1067         {
1068             ret = HandleResourceWithEntityHandler (request, resource, 0);
1069             break;
1070         }
1071         case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
1072         {
1073             ret = HandleResourceWithEntityHandler (request, resource, 1);
1074             break;
1075         }
1076         case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
1077         {
1078             ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
1079             break;
1080         }
1081         case OC_RESOURCE_NOT_SPECIFIED:
1082         {
1083             ret = OC_STACK_NO_RESOURCE;
1084             break;
1085         }
1086         default:
1087         {
1088             OC_LOG(INFO, TAG, PCF("Invalid Resource Determination"));
1089             return OC_STACK_ERROR;
1090         }
1091     }
1092     return ret;
1093 }
1094
1095 void DeletePlatformInfo()
1096 {
1097     OC_LOG(INFO, TAG, PCF("Deleting platform info."));
1098
1099     OICFree(savedPlatformInfo.platformID);
1100     savedPlatformInfo.platformID = NULL;
1101
1102     OICFree(savedPlatformInfo.manufacturerName);
1103     savedPlatformInfo.manufacturerName = NULL;
1104
1105     OICFree(savedPlatformInfo.manufacturerUrl);
1106     savedPlatformInfo.manufacturerUrl = NULL;
1107
1108     OICFree(savedPlatformInfo.modelNumber);
1109     savedPlatformInfo.modelNumber = NULL;
1110
1111     OICFree(savedPlatformInfo.dateOfManufacture);
1112     savedPlatformInfo.dateOfManufacture = NULL;
1113
1114     OICFree(savedPlatformInfo.platformVersion);
1115     savedPlatformInfo.platformVersion = NULL;
1116
1117     OICFree(savedPlatformInfo.operatingSystemVersion);
1118     savedPlatformInfo.operatingSystemVersion = NULL;
1119
1120     OICFree(savedPlatformInfo.hardwareVersion);
1121     savedPlatformInfo.hardwareVersion = NULL;
1122
1123     OICFree(savedPlatformInfo.firmwareVersion);
1124     savedPlatformInfo.firmwareVersion = NULL;
1125
1126     OICFree(savedPlatformInfo.supportUrl);
1127     savedPlatformInfo.supportUrl = NULL;
1128
1129     OICFree(savedPlatformInfo.systemTime);
1130     savedPlatformInfo.systemTime = NULL;
1131 }
1132
1133 static OCStackResult DeepCopyPlatFormInfo(OCPlatformInfo info)
1134 {
1135     savedPlatformInfo.platformID = OICStrdup(info.platformID);
1136     savedPlatformInfo.manufacturerName = OICStrdup(info.manufacturerName);
1137     savedPlatformInfo.manufacturerUrl = OICStrdup(info.manufacturerUrl);
1138     savedPlatformInfo.modelNumber = OICStrdup(info.modelNumber);
1139     savedPlatformInfo.dateOfManufacture = OICStrdup(info.dateOfManufacture);
1140     savedPlatformInfo.platformVersion = OICStrdup(info.platformVersion);
1141     savedPlatformInfo.operatingSystemVersion = OICStrdup(info.operatingSystemVersion);
1142     savedPlatformInfo.hardwareVersion = OICStrdup(info.hardwareVersion);
1143     savedPlatformInfo.firmwareVersion = OICStrdup(info.firmwareVersion);
1144     savedPlatformInfo.supportUrl = OICStrdup(info.supportUrl);
1145     savedPlatformInfo.systemTime = OICStrdup(info.systemTime);
1146
1147     if ((!savedPlatformInfo.platformID && info.platformID)||
1148         (!savedPlatformInfo.manufacturerName && info.manufacturerName)||
1149         (!savedPlatformInfo.manufacturerUrl && info.manufacturerUrl)||
1150         (!savedPlatformInfo.modelNumber && info.modelNumber)||
1151         (!savedPlatformInfo.dateOfManufacture && info.dateOfManufacture)||
1152         (!savedPlatformInfo.platformVersion && info.platformVersion)||
1153         (!savedPlatformInfo.operatingSystemVersion && info.operatingSystemVersion)||
1154         (!savedPlatformInfo.hardwareVersion && info.hardwareVersion)||
1155         (!savedPlatformInfo.firmwareVersion && info.firmwareVersion)||
1156         (!savedPlatformInfo.supportUrl && info.supportUrl)||
1157         (!savedPlatformInfo.systemTime && info.systemTime))
1158     {
1159         DeletePlatformInfo();
1160         return OC_STACK_INVALID_PARAM;
1161     }
1162
1163     return OC_STACK_OK;
1164
1165 }
1166
1167 OCStackResult SavePlatformInfo(OCPlatformInfo info)
1168 {
1169     DeletePlatformInfo();
1170
1171     OCStackResult res = DeepCopyPlatFormInfo(info);
1172
1173     if (res != OC_STACK_OK)
1174     {
1175         OC_LOG_V(ERROR, TAG, PCF("Failed to save platform info. errno(%d)"), res);
1176     }
1177     else
1178     {
1179         OC_LOG(ERROR, TAG, PCF("Platform info saved."));
1180     }
1181
1182     return res;
1183 }
1184
1185 void DeleteDeviceInfo()
1186 {
1187     OC_LOG(INFO, TAG, PCF("Deleting device info."));
1188
1189     OICFree(savedDeviceInfo.deviceName);
1190     savedDeviceInfo.deviceName = NULL;
1191 }
1192
1193 static OCStackResult DeepCopyDeviceInfo(OCDeviceInfo info)
1194 {
1195     savedDeviceInfo.deviceName = OICStrdup(info.deviceName);
1196
1197     if(!savedDeviceInfo.deviceName && info.deviceName)
1198     {
1199         DeleteDeviceInfo();
1200         return OC_STACK_NO_MEMORY;
1201     }
1202
1203     return OC_STACK_OK;
1204 }
1205
1206 OCStackResult SaveDeviceInfo(OCDeviceInfo info)
1207 {
1208     OCStackResult res = OC_STACK_OK;
1209
1210     DeleteDeviceInfo();
1211
1212     res = DeepCopyDeviceInfo(info);
1213
1214     VERIFY_SUCCESS(res, OC_STACK_OK);
1215
1216     if(OCGetServerInstanceID() == NULL)
1217     {
1218         OC_LOG(INFO, TAG, PCF("Device ID generation failed"));
1219         res =  OC_STACK_ERROR;
1220         goto exit;
1221     }
1222
1223     OC_LOG(INFO, TAG, PCF("Device initialized successfully."));
1224     return OC_STACK_OK;
1225
1226     exit:
1227         DeleteDeviceInfo();
1228         return res;
1229
1230 }