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