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