Merge changes I56f29eac,Ic7530d44
[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 #include <string.h>
22 #include "ocstack.h"
23 #include "ocstackconfig.h"
24 #include "ocstackinternal.h"
25 #include "ocresourcehandler.h"
26 #include "ocobserve.h"
27 #include "occollection.h"
28 #include "occoap.h"
29 #include "logger.h"
30 #include "debug.h"
31 #include "cJSON.h"
32
33 /// Module Name
34 #define TAG PCF("ocresource")
35 #define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
36             {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
37
38 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
39              TAG, PCF(#arg " is NULL")); return (retVal); } }
40
41 extern OCResource *headResource;
42
43 static const char * VIRTUAL_RSRCS[] = {
44        "/oc/core",
45        "/oc/core/d",
46        "/oc/core/types/d",
47        #ifdef WITH_PRESENCE
48        "/oc/presence"
49        #endif
50 };
51
52 //-----------------------------------------------------------------------------
53 // Default resource entity handler function
54 //-----------------------------------------------------------------------------
55 OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag,
56         OCEntityHandlerRequest * request) {
57     TODO ("Implement me!!!!");
58     // TODO:  remove silence unused param warnings
59     (void) flag;
60     (void) request;
61     return  OC_EH_OK; // Making sure that the Default EH and the Vendor EH have matching signatures
62 }
63
64 static OCStackResult ValidateUrlQuery (unsigned char *url, unsigned char *query,
65                                 uint8_t *filterOn, char **filterValue)
66 {
67     char *filterParam;
68
69     OC_LOG(INFO, TAG, PCF("Entering ValidateUrlQuery"));
70     if (!url)
71         return OC_STACK_INVALID_URI;
72
73     if (strcmp ((char *)url, GetVirtualResourceUri(OC_WELL_KNOWN_URI)) == 0) {
74         *filterOn = STACK_RES_DISCOVERY_NOFILTER;
75         if (query && *query) {
76             filterParam = strtok ((char *)query, "=");
77             *filterValue = strtok (NULL, " ");
78             if (!(*filterValue)) {
79                 return OC_STACK_INVALID_QUERY;
80             } else if (strcmp (filterParam, OC_RSRVD_INTERFACE) == 0) {
81                 // Resource discovery with interface filter
82                 *filterOn = STACK_RES_DISCOVERY_IF_FILTER;
83             } else if (strcmp (filterParam, OC_RSRVD_RESOURCE_TYPE) == 0) {
84                 // Resource discovery with resource type filter
85                 *filterOn = STACK_RES_DISCOVERY_RT_FILTER;
86             } else {
87                 // Other filter types not supported
88                 return OC_STACK_INVALID_QUERY;
89             }
90         }
91     }
92     #ifdef WITH_PRESENCE
93     else if (strcmp((char *)url, GetVirtualResourceUri(OC_PRESENCE)) == 0) {
94         //Nothing needs to be done, except for pass a OC_PRESENCE query through as OC_STACK_OK.
95         OC_LOG(INFO, TAG, PCF("OC_PRESENCE Request"));
96         *filterOn = STACK_RES_DISCOVERY_NOFILTER;
97     }
98     #endif
99     else {
100         // Other URIs not yet supported
101         return OC_STACK_INVALID_URI;
102     }
103     OC_LOG(INFO, TAG, PCF("Exiting ValidateUrlQuery"));
104     return OC_STACK_OK;
105 }
106
107 OCStackResult BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filterOn,
108                                             char *filterValue, char * out, uint16_t *remaining)
109 {
110     OCResourceType *resourceTypePtr;
111     OCResourceInterface *interfacePtr;
112     cJSON *resObj, *propObj, *rtArray;
113     char *jsonStr;
114     uint8_t encodeRes = 0;
115     OCStackResult ret = OC_STACK_OK;
116     uint16_t jsonLen;
117
118     OC_LOG(INFO, TAG, PCF("Entering BuildVirtualResourceResponse"));
119     resObj = cJSON_CreateObject();
120
121     if (resourcePtr)
122     {
123         encodeRes = 0;
124         if (filterOn == STACK_RES_DISCOVERY_RT_FILTER) {
125             resourceTypePtr = resourcePtr->rsrcType;
126             while (resourceTypePtr) {
127                 if (strcmp (resourceTypePtr->resourcetypename, filterValue) == 0) {
128                     encodeRes = 1;
129                     break;
130                 }
131                 resourceTypePtr = resourceTypePtr->next;
132             }
133         } else if (filterOn == STACK_RES_DISCOVERY_IF_FILTER) {
134             interfacePtr = resourcePtr->rsrcInterface;
135             while (interfacePtr) {
136                 if (strcmp (interfacePtr->name, filterValue) == 0) {
137                     encodeRes = 1;
138                     break;
139                 }
140                 interfacePtr = interfacePtr->next;
141             }
142         } else if (filterOn == STACK_RES_DISCOVERY_NOFILTER) {
143             encodeRes = 1;
144         } else {
145             //TODO: Unsupported query filter
146             return OC_STACK_INVALID_QUERY;
147         }
148
149         if (encodeRes) {
150             // Add URIs
151             cJSON_AddItemToObject (resObj, OC_RSRVD_HREF, cJSON_CreateString(resourcePtr->uri));
152
153             cJSON_AddItemToObject (resObj, "prop", propObj = cJSON_CreateObject());
154             // Add resource types
155             cJSON_AddItemToObject (propObj, OC_RSRVD_RESOURCE_TYPE, rtArray = cJSON_CreateArray());
156             resourceTypePtr = resourcePtr->rsrcType;
157             while (resourceTypePtr) {
158                 cJSON_AddItemToArray (rtArray,
159                                       cJSON_CreateString(resourceTypePtr->resourcetypename));
160                 resourceTypePtr = resourceTypePtr->next;
161             }
162             // Add interface types
163             cJSON_AddItemToObject (propObj, OC_RSRVD_INTERFACE, rtArray = cJSON_CreateArray());
164             interfacePtr = resourcePtr->rsrcInterface;
165             while (interfacePtr) {
166                 cJSON_AddItemToArray (rtArray, cJSON_CreateString(interfacePtr->name));
167                 interfacePtr = interfacePtr->next;
168             }
169             // If resource is observable, set observability flag.
170             // Resources that are not observable will not have the flag.
171             if (resourcePtr->resourceProperties & OC_OBSERVABLE) {
172                 cJSON_AddItemToObject (propObj, OC_RSRVD_OBSERVABLE,
173                                        cJSON_CreateNumber(OC_RESOURCE_OBSERVABLE));
174             }
175             // Set secure flag for secure resources
176             if (resourcePtr->resourceProperties & OC_SECURE) {
177                 uint16_t port;
178                 cJSON_AddNumberToObject (propObj, OC_RSRVD_SECURE, OC_RESOURCE_SECURE);
179                 //Set the IP port also as secure resources are hosted on a different port
180                 if (OCGetResourceEndPointInfo (resourcePtr, &port) == OC_STACK_OK) {
181                     cJSON_AddNumberToObject (propObj, OC_RSRVD_HOSTING_PORT, port);
182                 }
183             }
184
185         }
186     }
187     jsonStr = cJSON_PrintUnformatted (resObj);
188
189     jsonLen = strlen(jsonStr);
190     if (jsonLen < *remaining)
191     {
192         strcpy(out, jsonStr);
193         *remaining = *remaining - jsonLen;
194     }
195     else
196     {
197         ret = OC_STACK_ERROR;
198     }
199     cJSON_Delete (resObj);
200     free (jsonStr);
201
202     OC_LOG(INFO, TAG, PCF("Exiting BuildVirtualResourceResponse"));
203     return ret;
204 }
205
206 TODO ("Does it make sense to make this method as inline")
207 const char * GetVirtualResourceUri( OCVirtualResources resource)
208 {
209     if (resource < OC_MAX_VIRTUAL_RESOURCES)
210     {
211         return VIRTUAL_RSRCS[resource];
212     }
213
214     return NULL;
215 }
216
217 uint8_t IsVirtualResource(const char* resourceUri)
218 {
219     for (int i = 0; i < OC_MAX_VIRTUAL_RESOURCES; i++)
220     {
221         if (strcmp(resourceUri, GetVirtualResourceUri((OCVirtualResources)i)) == 0)
222         {
223             return 1;
224         }
225     }
226     return 0;
227 }
228
229 uint8_t IsCollectionResource (OCResource *resource)
230 {
231     for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
232     {
233         if (resource->rsrcResources[i])
234         {
235             return 1;
236         }
237     }
238     return 0;
239 }
240
241 OCResource *FindResourceByUri(const char* resourceUri)
242 {
243     OCResource * pointer = headResource;
244     while (pointer) {
245         if (strcmp(resourceUri, pointer->uri) == 0) {
246             return pointer;
247         }
248         pointer = pointer->next;
249     }
250     OC_LOG(INFO, TAG, PCF("Resource not found"));
251     return NULL;
252 }
253
254
255 OCStackResult DetermineResourceHandling (OCServerRequest *request,
256                                          ResourceHandling *handling,
257                                          OCResource **resource)
258 {
259
260     OC_LOG(INFO, TAG, PCF("Entering DetermineResourceHandling"));
261
262     // Check if virtual resource
263     if (IsVirtualResource((const char*)request->resourceUrl))
264     {
265         *handling = OC_RESOURCE_VIRTUAL;
266         *resource = headResource;
267         return OC_STACK_OK;
268     }
269     if (NULL == request->resourceUrl || (strlen((const char*)(request->resourceUrl)) == 0))
270     {
271         // Resource URL not specified
272         *handling = OC_RESOURCE_NOT_SPECIFIED;
273         return OC_STACK_OK;
274     }
275     else
276     {
277         OCResource *resourcePtr = NULL;
278         resourcePtr = FindResourceByUri((const char*)request->resourceUrl);
279         *resource = resourcePtr;
280         if (!resourcePtr)
281         {
282             if(defaultDeviceHandler)
283             {
284                 *handling = OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER;
285                 return OC_STACK_OK;
286             }
287
288             // Resource does not exist
289             // and default device handler does not exist
290             *handling = OC_RESOURCE_NOT_SPECIFIED;
291             return OC_STACK_NO_RESOURCE;
292         }
293
294         // secure resource will entertain only authorized requests
295         if ((resourcePtr->resourceProperties & OC_SECURE) && (request->secured == 0))
296         {
297             OC_LOG(INFO, TAG, PCF("Un-authorized request. Ignore it!"));
298             return OC_STACK_RESOURCE_ERROR;
299         }
300
301         if (IsCollectionResource (resourcePtr))
302         {
303             // Collection resource
304             if (resourcePtr->entityHandler != defaultResourceEHandler)
305             {
306                 *handling = OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER;
307                 return OC_STACK_OK;
308             } else {
309                 *handling = OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER;
310                 return OC_STACK_OK;
311             }
312         } else {
313             // Resource not a collection
314             if (resourcePtr->entityHandler != defaultResourceEHandler)
315             {
316                 *handling = OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER;
317                 return OC_STACK_OK;
318             } else {
319                 *handling = OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER;
320                 return OC_STACK_OK;
321             }
322         }
323     }
324 }
325
326 OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult)
327 {
328     OCStackResult result;
329
330     switch (ehResult)
331     {
332         case OC_EH_OK:
333             result = OC_STACK_OK;
334             break;
335         case OC_EH_SLOW:
336             result = OC_STACK_SLOW_RESOURCE;
337             break;
338         case OC_EH_ERROR:
339             result = OC_STACK_ERROR;
340             break;
341         case OC_EH_FORBIDDEN:
342             result = OC_STACK_RESOURCE_ERROR;
343             break;
344         case OC_EH_RESOURCE_CREATED:
345             result = OC_STACK_RESOURCE_CREATED;
346             break;
347         case OC_EH_RESOURCE_DELETED:
348             result = OC_STACK_RESOURCE_DELETED;
349             break;
350         default:
351             result = OC_STACK_ERROR;
352     }
353
354     return result;
355 }
356
357 static OCStackResult
358 HandleVirtualResource (OCServerRequest *request, OCResource* resource)
359 {
360     OCStackResult result = OC_STACK_ERROR;
361     char *filterValue = NULL;
362     uint8_t filterOn = 0;
363     uint16_t remaining = 0;
364     unsigned char * ptr = NULL;
365     uint8_t firstLoopDone = 0;
366     unsigned char discoveryResBuf[MAX_RESPONSE_LENGTH] = {0};
367
368     OC_LOG(INFO, TAG, PCF("Entering HandleVirtualResource"));
369
370     result = ValidateUrlQuery (request->resourceUrl,
371             request->query, &filterOn,
372             &filterValue);
373
374     if (result == OC_STACK_OK)
375     {
376         if (strcmp ((char *)request->resourceUrl, GetVirtualResourceUri(OC_WELL_KNOWN_URI)) == 0)
377         {
378             ptr = discoveryResBuf;
379             remaining = MAX_RESPONSE_LENGTH;
380
381             while(resource)
382             {
383                 if((resource->resourceProperties & OC_ACTIVE)
384                         && (resource->resourceProperties & OC_DISCOVERABLE))
385                 {
386                     // if there is data on the buffer, we have already added a response,
387                     // so we need to add a comma before we do anything
388                     if(firstLoopDone
389                             && remaining >= (sizeof(OC_JSON_SEPARATOR)+1))
390                     {
391                         *ptr = OC_JSON_SEPARATOR;
392                         ptr++;
393                         remaining--;
394                     }
395                     firstLoopDone = 1;
396                     result = BuildVirtualResourceResponse(resource, filterOn, filterValue,
397                             (char*)ptr, &remaining);
398
399                     if (result != OC_STACK_OK)
400                     {
401                         // if this failed, we need to remove the comma added above.
402                         if(!firstLoopDone)
403                         {
404                             ptr--;
405                             *ptr = '\0';
406                             remaining++;
407                         }
408                         break;
409                     }
410                     ptr += strlen((char *)ptr);
411                     *(ptr + 1) = '\0';
412                 }
413                 resource = resource->next;
414             }
415
416             if(strlen((const char *)discoveryResBuf) > 0)
417             {
418                 OCEntityHandlerResponse response = {0};
419
420                 response.ehResult = OC_EH_OK;
421                 response.payload = discoveryResBuf;
422                 response.payloadSize = strlen((const char *)discoveryResBuf) + 1;
423                 response.persistentBufferFlag = 0;
424                 response.requestHandle = (OCRequestHandle) request;
425                 response.resourceHandle = (OCResourceHandle) resource;
426
427                 result = OCDoResponse(&response);
428             }
429         }
430         #ifdef WITH_PRESENCE
431         else
432         {
433             if(resource->resourceProperties & OC_ACTIVE){
434                 SendPresenceNotification(NULL);
435             }
436         }
437         #endif
438     }
439     result = OC_STACK_VIRTUAL_DO_NOT_HANDLE;
440     return result;
441 }
442
443 static OCStackResult
444 HandleDefaultDeviceEntityHandler (OCServerRequest *request)
445 {
446     OCStackResult result = OC_STACK_OK;
447     OCEntityHandlerResult ehResult = OC_EH_ERROR;
448     OCEntityHandlerRequest ehRequest = {0};
449
450     OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithDefaultDeviceEntityHandler"));
451     result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
452             request->method, (OCResourceHandle) NULL, request->query,
453             request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
454             request->rcvdVendorSpecificHeaderOptions, (OCObserveAction)request->observationOption, (OCObservationId)0);
455     VERIFY_SUCCESS(result, OC_STACK_OK);
456
457     // At this point we know for sure that defaultDeviceHandler exists
458     ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest,
459                                   (char*) request->resourceUrl);
460     if(ehResult == OC_EH_SLOW)
461     {
462         OC_LOG(INFO, TAG, PCF("This is a slow resource"));
463         request->slowFlag = 1;
464     }
465     else if(ehResult == OC_EH_ERROR)
466     {
467         FindAndDeleteServerRequest(request);
468     }
469     result = EntityHandlerCodeToOCStackCode(ehResult);
470 exit:
471     return result;
472 }
473
474 static OCStackResult
475 HandleResourceWithEntityHandler (OCServerRequest *request,
476                                  OCResource *resource,
477                                  uint8_t collectionResource)
478 {
479     OCStackResult result = OC_STACK_ERROR;
480     OCEntityHandlerResult ehResult = OC_EH_ERROR;
481     OCEntityHandlerFlag ehFlag = OC_REQUEST_FLAG;
482     ResourceObserver *resObs = NULL;
483
484     OCEntityHandlerRequest ehRequest = {0};
485
486     OC_LOG(INFO, TAG, PCF("Entering HandleResourceWithEntityHandler"));
487     result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
488             request->method, (OCResourceHandle) resource, request->query,
489             request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
490             request->rcvdVendorSpecificHeaderOptions,
491             (OCObserveAction)request->observationOption, 0);
492     VERIFY_SUCCESS(result, OC_STACK_OK);
493
494     if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION)
495     {
496         OC_LOG(INFO, TAG, PCF("No observation requested"));
497         ehFlag = OC_REQUEST_FLAG;
498     }
499     else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER &&
500             !collectionResource)
501     {
502         OC_LOG(INFO, TAG, PCF("Registering observation requested"));
503         result = GenerateObserverId(&ehRequest.obsInfo.obsId);
504         VERIFY_SUCCESS(result, OC_STACK_OK);
505
506         result = AddObserver ((const char*)(request->resourceUrl),
507                 (const char *)(request->query),
508                 ehRequest.obsInfo.obsId, &request->requestToken,
509                 &request->requesterAddr, resource, request->qos);
510         if(result == OC_STACK_OK)
511         {
512             OC_LOG(DEBUG, TAG, PCF("Added observer successfully"));
513             request->observeResult = OC_STACK_OK;
514             ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG);
515         }
516         else
517         {
518             result = OC_STACK_OK;
519             request->observeResult = OC_STACK_ERROR;
520             OC_LOG(DEBUG, TAG, PCF("Observer Addition failed"));
521             ehFlag = OC_REQUEST_FLAG;
522         }
523
524     }
525     else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER &&
526             !collectionResource)
527     {
528         OC_LOG(INFO, TAG, PCF("Deregistering observation requested"));
529         resObs = GetObserverUsingToken (&request->requestToken);
530         if (NULL == resObs)
531         {
532             // Stack does not contain this observation request
533             // Either token is incorrect or observation list is corrupted
534             result = OC_STACK_ERROR;
535             goto exit;
536         }
537         ehRequest.obsInfo.obsId = resObs->observeId;
538         ehFlag = (OCEntityHandlerFlag)(ehFlag | OC_OBSERVE_FLAG);
539
540         result = DeleteObserverUsingToken (&request->requestToken);
541         if(result == OC_STACK_OK)
542         {
543             OC_LOG(DEBUG, TAG, PCF("Removed observer successfully"));
544             request->observeResult = OC_STACK_OK;
545         }
546         else
547         {
548             result = OC_STACK_OK;
549             request->observeResult = OC_STACK_ERROR;
550             OC_LOG(DEBUG, TAG, PCF("Observer Removal failed"));
551         }
552     }
553     else
554     {
555         result = OC_STACK_ERROR;
556         goto exit;
557     }
558
559     ehResult = resource->entityHandler(ehFlag, &ehRequest);
560     if(ehResult == OC_EH_SLOW)
561     {
562         OC_LOG(INFO, TAG, PCF("This is a slow resource"));
563         request->slowFlag = 1;
564     }
565     else if(ehResult == OC_EH_ERROR)
566     {
567         FindAndDeleteServerRequest(request);
568     }
569     result = EntityHandlerCodeToOCStackCode(ehResult);
570 exit:
571     return result;
572 }
573
574 static OCStackResult
575 HandleCollectionResourceDefaultEntityHandler (OCServerRequest *request,
576                                               OCResource *resource)
577 {
578     OCStackResult result = OC_STACK_ERROR;
579     OCEntityHandlerRequest ehRequest = {0};
580
581     result = FormOCEntityHandlerRequest(&ehRequest, (OCRequestHandle) request,
582             request->method, (OCResourceHandle) resource, request->query,
583             request->reqJSONPayload, request->numRcvdVendorSpecificHeaderOptions,
584             request->rcvdVendorSpecificHeaderOptions,
585             (OCObserveAction)request->observationOption, (OCObservationId) 0);
586     if(result != OC_STACK_OK)
587     {
588         return result;
589     }
590
591     return (DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest));
592 }
593
594 OCStackResult
595 ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request)
596 {
597     OCStackResult ret = OC_STACK_OK;
598
599     switch (resHandling)
600     {
601         case OC_RESOURCE_VIRTUAL:
602         {
603             ret = HandleVirtualResource (request, resource);
604             break;
605         }
606         case OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER:
607         {
608             ret = HandleDefaultDeviceEntityHandler(request);
609             break;
610         }
611         case OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER:
612         {
613             OC_LOG(INFO, TAG, PCF("OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER"));
614             return OC_STACK_ERROR;
615         }
616         case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER:
617         {
618             ret = HandleResourceWithEntityHandler (request, resource, 0);
619             break;
620         }
621         case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER:
622         {
623             ret = HandleResourceWithEntityHandler (request, resource, 1);
624             break;
625         }
626         case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER:
627         {
628             ret = HandleCollectionResourceDefaultEntityHandler (request, resource);
629             break;
630         }
631         case OC_RESOURCE_NOT_SPECIFIED:
632         {
633             ret = OC_STACK_NO_RESOURCE;
634             break;
635         }
636         default:
637         {
638             OC_LOG(INFO, TAG, PCF("Invalid Resource Determination"));
639             return OC_STACK_ERROR;
640         }
641     }
642     return ret;
643 }
644
645