To come on this changeset: All convergences between and server and client observation...
[platform/upstream/iotivity.git] / csdk / stack / src / ocstack.c
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Corporation 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
22 //-----------------------------------------------------------------------------
23 // Includes
24 //-----------------------------------------------------------------------------
25 #include "ocstack.h"
26 #include "ocstackinternal.h"
27 #include "ocserverrequest.h"
28 #include "ocresource.h"
29 #include "occlientcb.h"
30 #include "ocobserve.h"
31 #include "ocrandom.h"
32 #include "debug.h"
33 #include "occoap.h"
34
35 //-----------------------------------------------------------------------------
36 // Typedefs
37 //-----------------------------------------------------------------------------
38 typedef enum {
39     OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED
40 } OCStackState;
41
42 //-----------------------------------------------------------------------------
43 // Private variables
44 //-----------------------------------------------------------------------------
45 static OCStackState stackState = OC_STACK_UNINITIALIZED;
46 OCResource *headResource = NULL;
47
48 //-----------------------------------------------------------------------------
49 // Macros
50 //-----------------------------------------------------------------------------
51 #define TAG  PCF("OCStack")
52 #define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
53              TAG, PCF(#arg " is NULL")); return (retVal); } }
54
55 //-----------------------------------------------------------------------------
56 // Internal API function
57 //-----------------------------------------------------------------------------
58
59 //This function will be called back by occoap layer when a request is received
60 OCStackResult HandleStackRequests(OCRequest * request) {
61     OC_LOG(INFO, TAG, "Entering OCStackHandleReceiveRequest (OCStack Layer)");
62
63     char *filterValue;
64     uint8_t filterOn;
65     OCStackResult result;
66
67     VERIFY_NON_NULL(request, ERROR, OC_STACK_ERROR);
68     VERIFY_NON_NULL(request->entityHandlerRequest, ERROR, OC_STACK_ERROR);
69
70     if (IsVirtualResource((const char*)request->resourceUrl))
71     {
72         result = ValidateUrlQuery(request->resourceUrl,
73                                   request->entityHandlerRequest->query, &filterOn,
74                                   &filterValue);
75
76         if (result == OC_STACK_OK)
77         {
78             result = ProcessResourceDiscoverReq(
79                     (const unsigned char*) request->entityHandlerRequest->reqJSONPayload,
80                     (unsigned char *) request->entityHandlerRequest->resJSONPayload, filterOn,
81                     filterValue);
82         }
83     }
84     else
85     {
86         OCResource* resource = FindResourceByUri((const char*)request->resourceUrl);
87         if (resource)
88         {
89             request->entityHandlerRequest->resource = (OCResourceHandle)resource;
90             result = resource->entityHandler(OC_REQUEST_FLAG, request->entityHandlerRequest);
91         }
92         else
93         {
94             OC_LOG(INFO, TAG, "Resource Not found");
95             result = OC_STACK_NO_RESOURCE;
96         }
97         if (request->observe != NULL)
98         {
99             result = ProcessObserveRequest (resource, request);
100         }
101     }
102
103     return result;
104 }
105
106 //This function will be called back by occoap layer when a response is received
107 void HandleStackResponses(OCResponse * response) {
108     OCStackApplicationResult result = OC_STACK_DELETE_TRANSACTION;
109     OC_LOG(INFO, TAG, "Entering HandleStackResponses (OCStack Layer)");
110
111     if (response->cbNode) {
112         OC_LOG(INFO, TAG, PCF("Calling into application address space"));
113         result = response->cbNode->callBack(response->cbNode->context, response->cbNode->handle, response->clientResponse);
114         if (result == OC_STACK_DELETE_TRANSACTION) {
115             DeleteClientCB(response->cbNode);
116         }
117     }
118 }
119
120 int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr) {
121     size_t index = 0;
122     unsigned char *itr, *coap;
123     uint8_t dotCount = 0;
124
125     /* search for scheme */
126     itr = ipAddrStr;
127     if (!isdigit((unsigned char) *ipAddrStr)) {
128         coap = (unsigned char *) OC_COAP_SCHEME;
129         while (*coap && tolower(*itr) == *coap) {
130             coap++;
131             itr++;
132         }
133     }
134     ipAddrStr = itr;
135
136     while (*ipAddrStr) {
137         if (isdigit((unsigned char) *ipAddrStr)) {
138             ipAddr[index] *= 10;
139             ipAddr[index] += *ipAddrStr - '0';
140         } else if ((unsigned char) *ipAddrStr == '.') {
141             index++;
142             dotCount++;
143         } else {
144             break;
145         }
146         ipAddrStr++;
147     }
148
149     if (ipAddr[0] < 255 && ipAddr[1] < 255 && ipAddr[2] < 255 && ipAddr[3] < 255
150             && dotCount == 3) {
151         return 1;
152     } else {
153         return 0;
154     }
155 }
156 //-----------------------------------------------------------------------------
157 // Private internal function prototypes
158 //-----------------------------------------------------------------------------
159
160 static OCDoHandle GenerateInvocationHandle();
161 static void initResources();
162 static void insertResource(OCResource *resource);
163 static OCResource *findResource(OCResource *resource);
164 static void insertResourceType(OCResource *resource,
165         OCResourceType *resourceType);
166 static OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle,
167         uint8_t index);
168 static void insertResourceInterface(OCResource *resource,
169         OCResourceInterface *resourceInterface);
170 static OCResourceInterface *findResourceInterfaceAtIndex(
171         OCResourceHandle handle, uint8_t index);
172 static void deleteResourceType(OCResourceType *resourceType);
173 static void deleteResourceInterface(OCResourceInterface *resourceInterface);
174 static void deleteResourceElements(OCResource *resource);
175 static int deleteResource(OCResource *resource);
176
177 //-----------------------------------------------------------------------------
178 // Default resource entity handler function
179 //-----------------------------------------------------------------------------
180 void defaultResourceEHandler(OCEntityHandlerFlag flag,
181         OCEntityHandlerRequest * request) {
182     TODO ("Implement me!!!!");
183     // TODO:  remove silence unused param warnings
184     (void) flag;
185     (void) request;
186 }
187
188 //-----------------------------------------------------------------------------
189 // Public APIs
190 //-----------------------------------------------------------------------------
191
192 /**
193  * Initialize the OC Stack.  Must be called prior to starting the stack.
194  *
195  * @param ipAddr
196  *     IP Address of host device
197  * @param port
198  *     Port of host device
199  * @param mode
200  *     Host device is client, server, or client-server
201  *
202  * @return
203  *     OC_STACK_OK    - no errors
204  *     OC_STACK_ERROR - stack init error
205  */
206 OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode) {
207     OC_LOG(INFO, TAG, PCF("Entering OCInit"));
208
209     if (ipAddr) {
210         OC_LOG_V(INFO, TAG, "IP Address = %s", ipAddr);
211     }
212
213     switch (mode) {
214     case OC_CLIENT:
215         OC_LOG(INFO, TAG, PCF("Client mode"));
216         break;
217     case OC_SERVER:
218         OC_LOG(INFO, TAG, PCF("Server mode"));
219         break;
220     case OC_CLIENT_SERVER:
221         OC_LOG(INFO, TAG, PCF("Client-server mode"));
222         break;
223     default:
224         OC_LOG(ERROR, TAG, PCF("Invalid mode"));
225         return OC_STACK_ERROR;
226         break;
227     }
228
229     // Initialize resource
230     initResources();
231
232     // Make call to OCCoAP layer
233     if (OCInitCoAP(ipAddr, (uint16_t) port, mode) == 0) {
234         stackState = OC_STACK_INITIALIZED;
235         return OC_STACK_OK;
236     }
237
238     OC_LOG(ERROR, TAG, PCF("Stack initialization error"));
239     return OC_STACK_ERROR;
240 }
241
242 /**
243  * Stop the OC stack.  Use for a controlled shutdown.
244  * @return
245  *     OC_STACK_OK    - no errors
246  *     OC_STACK_ERROR - stack not initialized
247  */
248 OCStackResult OCStop() {
249     OC_LOG(INFO, TAG, PCF("Entering OCStop"));
250
251     if (stackState != OC_STACK_INITIALIZED) {
252         OC_LOG(ERROR, TAG, PCF("Stack not initialized"));
253         return OC_STACK_ERROR;
254     }
255
256     // Make call to OCCoAP layer
257     if (OCStopCoAP() == 0) {
258         // Remove all observers
259         DeleteObserverList();
260         // Remove all the client callbacks
261         DeleteClientCBList();
262         stackState = OC_STACK_UNINITIALIZED;
263         return OC_STACK_OK;
264     }
265
266     OC_LOG(ERROR, TAG, PCF("Stack stop error"));
267     return OC_STACK_ERROR;
268 }
269
270 /**
271  * Discover or Perform requests on a specified resource (specified by that Resource's respective URI).
272  *
273  * @param handle             - @ref OCDoHandle to refer to the request sent out on behalf of calling this API.
274  * @param method             - @ref OCMethod to perform on the resource
275  * @param requiredUri        - URI of the resource to interact with
276  * @param referenceUri       - URI of the reference resource
277  * @param request            - JSON encoded request
278  * @param qos                - quality of service
279  * @param cbData             - struct that contains asynchronous callback function that is invoked
280  *                             by the stack when discovery or resource interaction is complete
281  *
282  * @return
283  *     OC_STACK_OK               - no errors
284  *     OC_STACK_INVALID_CALLBACK - invalid callback function pointer
285  *     OC_STACK_INVALID_METHOD   - invalid resource method
286  *     OC_STACK_INVALID_URI      - invalid required or reference URI
287  */
288
289 OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requiredUri,
290                            const char *referenceUri, const char *request,
291                            OCQualityOfService qos, OCCallbackData *cbData)
292 {
293     OCStackResult result = OC_STACK_ERROR;
294     OCCoAPToken * token = NULL;
295     ClientCB *clientCB = NULL;
296     (void) referenceUri;
297
298     OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
299
300     // Validate input parameters
301     VERIFY_NON_NULL(cbData, FATAL, OC_STACK_INVALID_CALLBACK);
302     VERIFY_NON_NULL(cbData->cb, FATAL, OC_STACK_INVALID_CALLBACK);
303
304     TODO ("Need to form the final query by concatenating require and reference URI's");
305     VERIFY_NON_NULL(requiredUri, FATAL, OC_STACK_INVALID_URI);
306
307     switch (method)
308     {
309         case OC_REST_GET:
310         case OC_REST_PUT:
311             break;
312         case OC_REST_OBSERVE:
313         case OC_REST_OBSERVE_ALL:
314             break;
315         default:
316             DeleteClientCB(clientCB);
317             return OC_STACK_INVALID_METHOD;
318     }
319
320     *handle = GenerateInvocationHandle();
321     VERIFY_NON_NULL(*handle, FATAL, OC_STACK_ERROR);
322     token = OCGenerateCoAPToken();
323     if (!token)
324     {
325         goto exit;
326     }
327     if((result = AddClientCB(&clientCB, cbData, token, *handle, method)) != OC_STACK_OK)
328     {
329         goto exit;
330     }
331
332     // Make call to OCCoAP layer
333     result = OCDoCoAPResource(method, qos, token, requiredUri, request);
334
335 exit:
336
337     if (result != OC_STACK_OK)
338     {
339         OC_LOG(ERROR, TAG, PCF("OCDoResource error"));
340         if (clientCB)
341         {
342             DeleteClientCB(clientCB);
343         }
344         else
345         {
346             OCFree(token);
347             OCFree(*handle);
348         }
349     }
350     return result;
351 }
352
353 /**
354  * Cancel a request associated with a specific @ref OCDoResource invocation.
355  *
356  * @param handle - Used to identify a specific OCDoResource invocation.
357  *
358  * @return
359  *     OC_STACK_OK               - No errors; Success
360  *     OC_STACK_INVALID_PARAM    - The handle provided is invalid.
361  */
362 OCStackResult OCCancel(OCDoHandle handle) {
363     /*
364      * This ftn can be implemented one of two ways:
365      *
366      * 1. When observe is unobserved..Remove the callback associated on client side.
367      *      When the next notification comes in from server, reply with RST message to server.
368      *
369      * 2. When OCCancel is called, and it is associated with an observe request
370      *      (i.e. ClientCB->method == OC_REST_OBSERVE || OC_REST_OBSERVE_ALL),
371      *      Send Observe request to server with observe flag = OC_RESOURCE_OBSERVE_DEREGISTER.
372      *      Remove the callback associated on client side.
373      *
374      *      Number 1 is implemented here.
375      */
376     if(!handle) {
377         return OC_STACK_INVALID_PARAM;
378     }
379
380     OC_LOG(INFO, TAG, PCF("Entering OCCancel"));
381
382     ClientCB *clientCB = GetClientCB(NULL, handle);
383
384     if(clientCB) {
385         switch (clientCB->method)
386         {
387             case OC_REST_OBSERVE:
388             case OC_REST_OBSERVE_ALL:
389                 // Make call to OCCoAP layer
390                     DeleteClientCB(clientCB);
391                 break;
392             default:
393                 return OC_STACK_INVALID_METHOD;
394         }
395     }
396     return OC_STACK_OK;
397 }
398
399 /**
400  * Called in main loop of OC client or server.  Allows low-level processing of
401  * stack services.
402  *
403  * @return
404  *     OC_STACK_OK    - no errors
405  *     OC_STACK_ERROR - stack process error
406  */
407 OCStackResult OCProcess() {
408
409     OC_LOG(INFO, TAG, PCF("Entering OCProcess"));
410     OCProcessCoAP();
411
412     return OC_STACK_OK;
413 }
414 /**
415  * Create a resource
416  *
417  * @param handle - pointer to handle to newly created resource.  Set by ocstack.  Used to refer to resource
418  * @param resourceTypeName - name of resource type.  Example: "core.led"
419  * @param resourceAttributeRepresentation - attribute representation.  list of attributes:type, with each pair
420  *                                          separated by semicolons.  Example:  "state:oc.bt.b;power:oc.bt.i"
421  * @param resourceInterfaceName - name of resource interface.  Example: "core.rw"
422  * @param allowedMethods - methods permitted on interface.  Example: OC_REST_GET|OC_REST_PUT
423  * @param uri - URI of the resource.  Example:  "/a/led"
424  * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
425  * @param resourceProperties - properties supported by resource.  Example: OC_DISCOVERABLE|OC_OBSERVABLE
426  *
427  * @return
428  *     OC_STACK_OK    - no errors
429  *     OC_STACK_ERROR - stack process error
430  */
431 OCStackResult OCCreateResource(OCResourceHandle *handle,
432         const char *resourceTypeName,
433         const char *resourceAttributeRepresentation,
434         const char *resourceInterfaceName, uint8_t allowedMethods,
435         const char *uri, OCEntityHandler entityHandler,
436         uint8_t resourceProperties) {
437
438     OCResource *pointer = NULL;
439     char *str = NULL;
440     size_t size;
441     OCStackResult result = OC_STACK_ERROR;
442
443     OC_LOG(INFO, TAG, PCF("Entering OCCreateResource"));
444
445     // Validate parameters
446     // TODO:  Does resource attribute representation really have to be maintained in stack?
447     // Is it presented during resource discovery?
448     //    VERIFY_NON_NULL(resourceAttributeRepresentation, ERROR, OC_STACK_ERROR);
449     if (!handle || !resourceTypeName || !resourceInterfaceName || !uri) {
450         OC_LOG(ERROR, TAG, PCF("Input parameter is NULL"));
451         return OC_STACK_INVALID_PARAM;
452     }
453
454     // Make sure allowedMethods bitmask has allowed methods specified
455     if ((allowedMethods
456             > (OC_REST_GET | OC_REST_PUT | OC_REST_POST | OC_REST_DELETE
457                     | OC_REST_OBSERVE))
458             || (allowedMethods == OC_REST_NOMETHOD)) {
459         OC_LOG(ERROR, TAG, PCF("Invalid method"));
460         return OC_STACK_INVALID_PARAM;
461     }
462
463     // Make sure resourceProperties bitmask has allowed properties specified
464     if (resourceProperties
465             > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW)) {
466         OC_LOG(ERROR, TAG, PCF("Invalid property"));
467         return OC_STACK_INVALID_PARAM;
468     }
469
470     // If the headResource is NULL, then no resources have been created...
471     pointer = headResource;
472     if (pointer) {
473         // At least one resources is in the resource list, so we need to search for
474         // repeated URLs, which are not allowed.  If a repeat is found, exit with an error
475         while (pointer) {
476             if (strcmp(uri, pointer->uri) == 0) {
477                 OC_LOG(ERROR, TAG, PCF("URI already in use"));
478                 return OC_STACK_INVALID_PARAM;
479             }
480             pointer = pointer->next;
481         }
482     }
483     // Create the pointer and insert it into the resource list
484     pointer = (OCResource *) OCMalloc(sizeof(OCResource));
485     if (!pointer) {
486         goto exit;
487     }
488     memset(pointer, 0, sizeof(OCResource));
489
490     insertResource(pointer);
491
492     // Set the uri
493     size = strlen(uri) + 1;
494     str = (char *) OCMalloc(size);
495     if (!str) {
496         goto exit;
497     }
498     strncpy(str, uri, size);
499     pointer->uri = str;
500
501     // Set properties.  Set OC_ACTIVE
502     pointer->resourceProperties = (OCResourceProperty) (resourceProperties
503             | OC_ACTIVE);
504
505     // Add the resourcetype to the resource
506     result = OCBindResourceTypeToResource((OCResourceHandle) pointer,
507             resourceTypeName, resourceAttributeRepresentation);
508     if (result != OC_STACK_OK) {
509         OC_LOG(ERROR, TAG, PCF("Error adding resourcetype"));
510         goto exit;
511     }
512
513     // Add the resourceinterface to the resource
514     result = OCBindResourceInterfaceToResource((OCResourceHandle) pointer,
515             resourceInterfaceName, allowedMethods);
516     if (result != OC_STACK_OK) {
517         OC_LOG(ERROR, TAG, PCF("Error adding resourceinterface"));
518         goto exit;
519     }
520
521     // added [CL]
522     result = OCBindResourceHandler((OCResourceHandle) pointer, entityHandler);
523     if (result != OC_STACK_OK) {
524         OC_LOG(ERROR, TAG, PCF("Error adding resourceinterface"));
525         goto exit;
526     }
527
528     *handle = pointer;
529     result = OC_STACK_OK;
530
531 exit:
532     if (result != OC_STACK_OK)
533     {
534         OCFree(pointer);
535         OCFree(str);
536     }
537     return result;
538 }
539
540 /**
541  * Add a resource to a container resource.
542  *
543  * @param containerHandle - handle to the container resource
544  * @param addedResourceHandle - handle to resource to be added to the container resource
545  *
546  * @return
547  *     OC_STACK_OK    - no errors
548  *     OC_STACK_ERROR - stack process error
549  */
550 OCStackResult OCBindContainedResourceToResource(
551         OCResourceHandle containerHandle, OCResourceHandle addedResourceHandle) {
552     OCResource *resource;
553     uint8_t i;
554
555     OC_LOG(INFO, TAG, PCF("Entering OCBindContainedResourceToResource"));
556
557     // Validate parameters
558     VERIFY_NON_NULL(containerHandle, ERROR, OC_STACK_ERROR);
559     VERIFY_NON_NULL(addedResourceHandle, ERROR, OC_STACK_ERROR);
560     // Container cannot contain itself
561     if (containerHandle == addedResourceHandle) {
562         OC_LOG(ERROR, TAG, PCF("Added handle equals container handle"));
563         return OC_STACK_INVALID_PARAM;
564     }
565
566     // Use the handle to find the resource in the resource linked list
567     resource = findResource((OCResource *) containerHandle);
568     if (!resource) {
569         OC_LOG(ERROR, TAG, PCF("Resource not found"));
570         return OC_STACK_INVALID_PARAM;
571     }
572
573     // Look for an open slot to add add the child resource.
574     // If found, add it and return success
575     for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
576         if (!resource->rsrcResources[i]) {
577             resource->rsrcResources[i] = (OCResourceHandle) addedResourceHandle;
578             OC_LOG(INFO, TAG, PCF("resource bound"));
579             return OC_STACK_OK;
580         }
581     }
582
583     // Unable to add addedResourceHandle, so return error
584     return OC_STACK_ERROR;
585 }
586
587 /**
588  * Bind a resourcetype to a resource.
589  *
590  * @param handle - handle to the container resource
591  * @param resourceTypeName - name of resource type.  Example: "core.led"
592  * @param resourceAttributeRepresentation - attribute representation.  list of attributes:type, with each pair
593  *                                          separated by semicolons.  Example:  "state:oc.bt.b;power:oc.bt.i"
594  *
595  * @return
596  *     OC_STACK_OK    - no errors
597  *     OC_STACK_ERROR - stack process error
598  */
599 OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
600         const char *resourceTypeName,
601         const char *resourceAttributeRepresentation) {
602
603     OCResourceType *pointer = NULL;
604     char *str = NULL;
605     size_t size;
606     OCResource *resource;
607     OCStackResult result = OC_STACK_ERROR;
608
609     OC_LOG(INFO, TAG, PCF("Entering OCBindResourceTypeToResource"));
610
611     // Validate parameters
612     VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
613     // TODO:  Does resource attribute resentation really have to be maintained in stack?
614     // Is it presented during resource discovery?
615     // VERIFY_NON_NULL(resourceAttributeRepresentation, ERROR, OC_STACK_ERROR);
616
617     // Make sure resource exists
618     resource = findResource((OCResource *) handle);
619     if (!resource) {
620         OC_LOG(ERROR, TAG, PCF("Resource not found"));
621         return OC_STACK_ERROR;
622     }
623
624     TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
625
626     // Create the resourcetype and insert it into the resource list
627     pointer = (OCResourceType *) OCMalloc(sizeof(OCResourceType));
628     if (!pointer) {
629         goto exit;
630     }
631     memset(pointer, 0, sizeof(OCResourceType));
632
633     // Set the resourceTypeName
634     size = strlen(resourceTypeName) + 1;
635     str = (char *) OCMalloc(size);
636     if (!str) {
637         goto exit;
638     }
639     strncpy(str, resourceTypeName, size);
640     pointer->resourcetypename = str;
641
642     // If the resourceAttributeRepresentation is defined, add it.
643     if (resourceAttributeRepresentation) {
644         size = strlen(resourceAttributeRepresentation) + 1;
645         str = (char *) OCMalloc(size);
646         if (!str) {
647             goto exit;
648         }
649         strncpy(str, resourceAttributeRepresentation, size);
650         pointer->typerepresentation = str;
651     }
652     // Bind the resourcetype to the resource
653     insertResourceType(resource, pointer);
654
655     result = OC_STACK_OK;
656
657     exit: if (result != OC_STACK_OK) {
658         OCFree(pointer);
659         OCFree(str);
660     }
661     return result;
662 }
663
664 /**
665  * Bind a resourceinterface to a resource.
666  *
667  * @param handle - handle to the container resource
668  * @param resourceInterfaceName - name of resource interface.  Example: "core.rw"
669  * @param allowedMethods - methods permitted on interface.  Example: OC_REST_GET|OC_REST_PUT
670  *
671  * @return
672  *     OC_STACK_OK    - no errors
673  *     OC_STACK_ERROR - stack process error
674  */
675 OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
676         const char *resourceInterfaceName, uint8_t allowedMethods) {
677
678     OCResourceInterface *pointer = NULL;
679     char *str = NULL;
680     size_t size;
681     OCResource *resource;
682     OCStackResult result = OC_STACK_ERROR;
683
684     OC_LOG(INFO, TAG, PCF("Entering OCBindResourceInterfaceToResource"));
685
686     // Validate parameters
687     VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
688
689     // Make sure allowedMethods bitmask has allowed methods specified
690     if ((allowedMethods
691             > (OC_REST_GET | OC_REST_PUT | OC_REST_POST | OC_REST_DELETE
692                     | OC_REST_OBSERVE))
693             || (allowedMethods == OC_REST_NOMETHOD)) {
694         OC_LOG(ERROR, TAG, PCF("Invalid method"));
695         return OC_STACK_INVALID_PARAM;
696     }
697
698     // Make sure resource exists
699     resource = findResource((OCResource *) handle);
700     if (!resource) {
701         OC_LOG(ERROR, TAG, PCF("Resource not found"));
702         return OC_STACK_INVALID_PARAM;
703     }
704
705     TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
706
707     // Create the resourceinterface and insert it into the resource list
708     pointer = (OCResourceInterface *) OCMalloc(sizeof(OCResourceInterface));
709     if (!pointer) {
710         goto exit;
711     }
712     memset(pointer, 0, sizeof(OCResourceInterface));
713
714     // Set the resourceinterface name
715     size = strlen(resourceInterfaceName) + 1;
716     str = (char *) OCMalloc(size);
717     if (!str) {
718         goto exit;
719     }
720     strncpy(str, resourceInterfaceName, size);
721     pointer->name = str;
722
723     pointer->allowedMethods = allowedMethods;
724
725     // Bind the resourceinterface to the resource
726     insertResourceInterface(resource, pointer);
727
728     result = OC_STACK_OK;
729     exit: if (result != OC_STACK_OK) {
730         OCFree(pointer);
731         OCFree(str);
732     }
733     return result;
734 }
735
736 /**
737  * Get the number of resources that have been created in the stack.
738  *
739  * @param numResources - pointer to count variable
740  *
741  * @return
742  *     OC_STACK_OK    - no errors
743  *     OC_STACK_ERROR - stack process error
744
745  */
746 OCStackResult OCGetNumberOfResources(uint8_t *numResources) {
747     OCResource *pointer = headResource;
748
749     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResources"));
750     VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
751     *numResources = 0;
752     while (pointer) {
753         *numResources = *numResources + 1;
754         pointer = pointer->next;
755     }
756     return OC_STACK_OK;
757 }
758
759 /**
760  * Get a resource handle by index.
761  *
762  * @param index - index of resource, 0 to Count - 1
763  *
764  * @return
765  *    Resource handle - if found
766  *    NULL - if not found
767  */
768 OCResourceHandle OCGetResourceHandle(uint8_t index) {
769     OCResource *pointer = headResource;
770     uint8_t i = 0;
771
772     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandle"));
773
774     // Iterate through the list
775     while ((i < index) && pointer) {
776         i++;
777         pointer = pointer->next;
778     }
779     return (OCResourceHandle) pointer;
780 }
781
782 /**
783  * Delete resource specified by handle.  Deletes resource and all resourcetype and resourceinterface
784  * linked lists.
785  *
786  * @param handle - handle of resource to be deleted
787  *
788  * @return
789  *     OC_STACK_OK    - no errors
790  *     OC_STACK_ERROR - stack process error
791  */
792 OCStackResult OCDeleteResource(OCResourceHandle handle) {
793     OC_LOG(INFO, TAG, PCF("Entering OCDeleteResource"));
794
795     if (!handle) {
796         OC_LOG(ERROR, TAG, PCF("Resource not found"));
797         return OC_STACK_INVALID_PARAM;
798     }
799
800     if (deleteResource((OCResource *) handle) == 0) {
801         OC_LOG(ERROR, TAG, PCF("Error deleting resource"));
802         return OC_STACK_ERROR;
803     }
804
805     return OC_STACK_OK;
806 }
807
808 /**
809  * Get the URI of the resource specified by handle.
810  *
811  * @param handle - handle of resource
812  * @return
813  *    URI string - if resource found
814  *    NULL - resource not found
815  */
816 const char *OCGetResourceUri(OCResourceHandle handle) {
817     OCResource *resource;
818     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceUri"));
819
820     resource = findResource((OCResource *) handle);
821     if (resource) {
822         return resource->uri;
823     }
824     return (const char *) NULL;
825 }
826
827 /**
828  * Get the properties of the resource specified by handle.
829  * NOTE: that after a resource is created, the OC_ACTIVE property is set
830  * for the resource by the stack.
831  *
832  * @param handle - handle of resource
833  * @return
834  *    property bitmap - if resource found
835  *    NULL - resource not found
836  */
837 uint8_t OCGetResourceProperties(OCResourceHandle handle) {
838     OCResource *resource;
839     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceProperties"));
840
841     resource = findResource((OCResource *) handle);
842     if (resource) {
843         return resource->resourceProperties;
844     }
845     return 0;
846 }
847
848 /**
849  * Get the number of resource types of the resource.
850  *
851  * @param handle - handle of resource
852  * @param numResourceTypes - pointer to count variable
853  *
854  * @return
855  *     OC_STACK_OK    - no errors
856  *     OC_STACK_ERROR - stack process error
857  */
858 OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
859         uint8_t *numResourceTypes) {
860     OCResource *resource;
861     OCResourceType *pointer;
862
863     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceTypes"));
864     VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
865     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
866
867     *numResourceTypes = 0;
868
869     resource = findResource((OCResource *) handle);
870     if (resource) {
871         pointer = resource->rsrcType;
872         while (pointer) {
873             *numResourceTypes = *numResourceTypes + 1;
874             pointer = pointer->next;
875         }
876     }
877     return OC_STACK_OK;
878 }
879
880 /**
881  * Get name of resource type of the resource.
882  *
883  * @param handle - handle of resource
884  * @param index - index of resource, 0 to Count - 1
885  *
886  * @return
887  *    resource type name - if resource found
888  *    NULL - resource not found
889  */
890 const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index) {
891     OCResourceType *resourceType;
892
893     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceTypeName"));
894
895     resourceType = findResourceTypeAtIndex(handle, index);
896     if (resourceType) {
897         return resourceType->resourcetypename;
898     }
899     return (const char *) NULL;
900 }
901
902 /**
903  * Get attributes of resource type of the resource.
904  *
905  * @param handle - handle of resource
906  * @param index - index of resource, 0 to Count - 1
907  *
908  * @return
909  *    resource type attributes - if resource found
910  *    NULL - resource not found
911  */
912 const char *OCGetResourceAttributeRepresentation(OCResourceHandle handle,
913         uint8_t index) {
914     OCResourceType *resourceType;
915
916     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceAttributeRepresentation"));
917
918     resourceType = findResourceTypeAtIndex(handle, index);
919     if (resourceType) {
920         return resourceType->typerepresentation;
921     }
922     return (const char *) NULL;
923 }
924
925 /**
926  * Get the number of resource interfaces of the resource.
927  *
928  * @param handle - handle of resource
929  * @param numResources - pointer to count variable
930  *
931  * @return
932  *     OC_STACK_OK    - no errors
933  *     OC_STACK_ERROR - stack process error
934
935  */
936 OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
937         uint8_t *numResourceInterfaces) {
938     OCResourceInterface *pointer;
939     OCResource *resource;
940
941     OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceInterfaces"));
942
943     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
944     VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
945
946     *numResourceInterfaces = 0;
947     resource = findResource((OCResource *) handle);
948     if (resource) {
949         pointer = resource->rsrcInterface;
950         while (pointer) {
951             *numResourceInterfaces = *numResourceInterfaces + 1;
952             pointer = pointer->next;
953         }
954     }
955     return OC_STACK_OK;
956 }
957
958 /**
959  * Get name of resource interface of the resource.
960  *
961  * @param handle - handle of resource
962  * @param index - index of resource, 0 to Count - 1
963  *
964  * @return
965  *    resource interface name - if resource found
966  *    NULL - resource not found
967  */
968 const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index) {
969     OCResourceInterface *resourceInterface;
970
971     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceName"));
972
973     resourceInterface = findResourceInterfaceAtIndex(handle, index);
974     if (resourceInterface) {
975         return resourceInterface->name;
976     }
977     return (const char *) NULL;
978 }
979
980 /**
981  * Get methods of resource interface of the resource.
982  *
983  * @param handle - handle of resource
984  * @param index - index of resource, 0 to Count - 1
985  *
986  * @return
987  *    allowed methods - if resource found
988  *    NULL - resource not found
989  */
990 uint8_t OCGetResourceInterfaceAllowedMethods(OCResourceHandle handle,
991         uint8_t index) {
992     OCResourceInterface *resourceInterface;
993
994     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceAllowedMethods"));
995
996     resourceInterface = findResourceInterfaceAtIndex(handle, index);
997     if (resourceInterface) {
998         return resourceInterface->allowedMethods;
999     }
1000     return (uint8_t) 0;
1001 }
1002
1003 /**
1004  * Get name of resource interface of the resource.
1005  *
1006  * @param containerHandle - handle of container resource
1007  * @param index - index of contained resource, 0 to Count - 1
1008  *
1009  * @return
1010  *    handle to contained resource - if resource found
1011  *    NULL - resource not found
1012  */
1013 OCResourceHandle OCGetContainedResourceHandle(OCResourceHandle containerHandle,
1014         uint8_t index) {
1015     OCResource *resource;
1016
1017     OC_LOG(INFO, TAG, PCF("Entering OCGetContainedResource"));
1018
1019     if (index >= MAX_CONTAINED_RESOURCES) {
1020         return NULL;
1021     }
1022
1023     resource = findResource((OCResource *) containerHandle);
1024     if (!resource) {
1025         return NULL;
1026     }
1027
1028     return resource->rsrcResources[index];
1029 }
1030
1031 /**
1032  * Bind an entity handler to the resource.
1033  *
1034  * @param handle - handle to the resource that the contained resource is to be bound
1035  * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
1036  * @return
1037  *     OC_STACK_OK    - no errors
1038  *     OC_STACK_ERROR - stack process error
1039  */
1040 OCStackResult OCBindResourceHandler(OCResourceHandle handle,
1041         OCEntityHandler entityHandler) {
1042     OCResource *resource;
1043
1044     OC_LOG(INFO, TAG, PCF("Entering OCBindResourceHandler"));
1045
1046     // Validate parameters
1047     VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
1048     VERIFY_NON_NULL(entityHandler, ERROR, OC_STACK_INVALID_PARAM);
1049
1050     // Use the handle to find the resource in the resource linked list
1051     resource = findResource(handle);
1052     if (!resource) {
1053         OC_LOG(ERROR, TAG, PCF("Resource not found"));
1054         return OC_STACK_ERROR;
1055     }
1056
1057     // Bind the handler
1058     resource->entityHandler = entityHandler;
1059
1060     return OC_STACK_OK;
1061 }
1062
1063 /**
1064  * Get the entity handler for a resource.
1065  *
1066  * @param handle - handle of resource
1067  *
1068  * @return
1069  *    entity handler - if resource found
1070  *    NULL - resource not found
1071  */
1072 OCEntityHandler OCGetResourceHandler(OCResourceHandle handle) {
1073     OCResource *resource;
1074
1075     OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandler"));
1076
1077     // Use the handle to find the resource in the resource linked list
1078     resource = findResource(handle);
1079     if (!resource) {
1080         OC_LOG(ERROR, TAG, PCF("Resource not found"));
1081         return NULL;
1082     }
1083
1084     // Bind the handler
1085     return resource->entityHandler;
1086 }
1087
1088 /**
1089  * Notify observers that an observed value has changed.
1090  *
1091  *
1092  * @param handle - handle of resource
1093  *
1094  * @return
1095  *     OC_STACK_OK    - no errors
1096  *     OC_STACK_ERROR - stack not initialized
1097  */
1098 OCStackResult OCNotifyObservers(OCResourceHandle handle) {
1099     OCResource *resPtr = NULL;
1100     OCStackResult result;
1101
1102     OC_LOG(INFO, TAG, PCF("Entering OCNotifyObservers"));
1103
1104     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
1105
1106     // Verify that the resource exists
1107     resPtr = findResource ((OCResource *) handle);
1108     if (NULL == resPtr)
1109     {
1110         return OC_STACK_NO_RESOURCE;
1111     } else {
1112         result = SendObserverNotification (handle, resPtr);
1113         return result;
1114     }
1115 }
1116
1117 //-----------------------------------------------------------------------------
1118 // Private internal function definitions
1119 //-----------------------------------------------------------------------------
1120 /**
1121  * Generate handle of OCDoResource invocation for callback management.
1122  */
1123 static OCDoHandle GenerateInvocationHandle()
1124 {
1125     OCDoHandle handle = NULL;
1126     // Generate token here, it will be deleted when the transaction is deleted
1127     handle = (OCDoHandle) malloc(sizeof(uint8_t[MAX_TOKEN_LENGTH]));
1128     if (handle)
1129     {
1130         OCFillRandomMem((uint8_t*)handle, sizeof(uint8_t[MAX_TOKEN_LENGTH]));
1131     }
1132
1133     return handle;
1134 }
1135
1136 /**
1137  * Initialize resource data structures, variables, etc.
1138  */
1139 void initResources() {
1140     TODO ("Do we need to create a resource for /oc/core???");
1141     // Init resource vars
1142     headResource = NULL;
1143 }
1144
1145 /**
1146  * Add a resource to the end of the linked list of resources.
1147  *
1148  * @param resource - resource to be added
1149  */
1150 void insertResource(OCResource *resource) {
1151     OCResource *pointer;
1152
1153     if (!headResource) {
1154         headResource = resource;
1155     } else {
1156         pointer = headResource;
1157
1158         while (pointer->next) {
1159             pointer = pointer->next;
1160         }
1161         pointer->next = resource;
1162     }
1163     resource->next = NULL;
1164 }
1165
1166 /**
1167  * Find a resource in the linked list of resources.
1168  *
1169  * @param resource - resource to be found
1170  * @return
1171  *     NULL                - resource not found
1172  *     pointer to resource - pointer to resource that was found in the linked list
1173  */
1174 OCResource *findResource(OCResource *resource) {
1175     OCResource *pointer = headResource;
1176
1177     while (pointer) {
1178         if (pointer == resource) {
1179             return resource;
1180         }
1181         pointer = pointer->next;
1182     }
1183     return NULL;
1184 }
1185
1186 /**
1187  * Delete the resource from the linked list.
1188  *
1189  * @param resource - resource to be deleted
1190  * @return
1191  *    0 - error
1192  *    1 - success
1193  */
1194 int deleteResource(OCResource *resource) {
1195     OCResource *prev = NULL;
1196     OCResource *temp;
1197
1198     temp = headResource;
1199     while (temp) {
1200         if (temp == resource) {
1201             if (temp == headResource) {
1202                 headResource = temp->next;
1203             } else {
1204                 prev->next = temp->next;
1205             }
1206             deleteResourceElements(temp);
1207             OCFree(temp);
1208             return 1;
1209         } else {
1210             prev = temp;
1211             temp = temp->next;
1212         }
1213     }
1214
1215     return 0;
1216 }
1217
1218 /**
1219  * Delete all of the dynamically allocated elements that were created for the resource.
1220  *
1221  * @param resource - specified resource
1222  */
1223 void deleteResourceElements(OCResource *resource) {
1224     if (!resource) {
1225         return;
1226     }
1227
1228     // remove URI
1229     OCFree(resource->uri);
1230
1231     // Delete resourcetype linked list
1232     deleteResourceType(resource->rsrcType);
1233
1234     // Delete resourceinterface linked list
1235     deleteResourceInterface(resource->rsrcInterface);
1236 }
1237
1238 /**
1239  * Delete all of the dynamically allocated elements that were created for the resource type.
1240  *
1241  * @param resourceType - specified resource type
1242  */
1243 void deleteResourceType(OCResourceType *resourceType) {
1244     OCResourceType *pointer = resourceType;
1245     OCResourceType *next;
1246
1247     while (pointer) {
1248         next = pointer->next;
1249         OCFree(pointer->resourcetypename);
1250         OCFree(pointer->typerepresentation);
1251         OCFree(pointer);
1252         pointer = next;
1253     }
1254 }
1255
1256 /**
1257  * Delete all of the dynamically allocated elements that were created for the resource interface.
1258  *
1259  * @param resourceInterface - specified resource interface
1260  */
1261 void deleteResourceInterface(OCResourceInterface *resourceInterface) {
1262     OCResourceInterface *pointer = resourceInterface;
1263     OCResourceInterface *next;
1264
1265     while (pointer) {
1266         next = pointer->next;
1267         OCFree(pointer->name);
1268         OCFree(pointer);
1269         pointer = next;
1270     }
1271 }
1272
1273 /**
1274  * Insert a resource type into a resource's resource type linked list.
1275  *
1276  * @param resource - resource where resource type is to be inserted
1277  * @param resourceType - resource type to be inserted
1278  */
1279 void insertResourceType(OCResource *resource, OCResourceType *resourceType) {
1280     OCResourceType *pointer;
1281
1282     if (!resource->rsrcType) {
1283         resource->rsrcType = resourceType;
1284     } else {
1285         pointer = resource->rsrcType;
1286         while (pointer->next) {
1287             pointer = pointer->next;
1288         }
1289         pointer->next = resourceType;
1290     }
1291     resourceType->next = NULL;
1292 }
1293
1294 /**
1295  * Get a resource type at the specified index within a resource.
1296  *
1297  * @param handle - handle of resource
1298  * @param index - index of resource type
1299  *
1300  * @return
1301  *    resourcetype - if found
1302  *    NULL - not found
1303  */
1304 OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index) {
1305     OCResource *resource;
1306     OCResourceType *pointer;
1307     uint8_t i;
1308
1309     // Find the specified resource
1310     resource = findResource((OCResource *) handle);
1311     if (!resource) {
1312         return NULL;
1313     }
1314
1315     // Make sure a resource has a resourcetype
1316     if (!resource->rsrcType) {
1317         return NULL;
1318     }
1319
1320     // Iterate through the list
1321     pointer = resource->rsrcType;
1322     i = 0;
1323     while ((i < index) && pointer) {
1324         i++;
1325         pointer = pointer->next;
1326     }
1327     return pointer;
1328 }
1329
1330 /**
1331  * Insert a resource interface into a resource's resource interface linked list.
1332  *
1333  * @param resource - resource where resource interface is to be inserted
1334  * @param resourceInterface - resource interface to be inserted
1335  */
1336 void insertResourceInterface(OCResource *resource,
1337         OCResourceInterface *resourceInterface) {
1338     OCResourceInterface *pointer;
1339
1340     if (!resource->rsrcInterface) {
1341         resource->rsrcInterface = resourceInterface;
1342     } else {
1343         pointer = resource->rsrcInterface;
1344         while (pointer->next) {
1345             pointer = pointer->next;
1346         }
1347         pointer->next = resourceInterface;
1348     }
1349     resourceInterface->next = NULL;
1350 }
1351
1352 /**
1353  * Get a resource interface at the specified index within a resource.
1354  *
1355  * @param handle - handle of resource
1356  * @param index - index of resource interface
1357  *
1358  * @return
1359  *    resourceinterface - if found
1360  *    NULL - not found
1361  */
1362 OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
1363         uint8_t index) {
1364     OCResource *resource;
1365     OCResourceInterface *pointer;
1366     uint8_t i = 0;
1367
1368     // Find the specified resource
1369     resource = findResource((OCResource *) handle);
1370     if (!resource) {
1371         return NULL;
1372     }
1373
1374     // Make sure a resource has a resourceinterface
1375     if (!resource->rsrcInterface) {
1376         return NULL;
1377     }
1378
1379     // Iterate through the list
1380     pointer = resource->rsrcInterface;
1381
1382     while ((i < index) && pointer) {
1383         i++;
1384         pointer = pointer->next;
1385     }
1386     return pointer;
1387 }
1388
1389 // TODO: Remove these!  Should be in an ocmalloc module
1390 void *OCMalloc(size_t size) {
1391     TODO ("This should be moved into an ocmalloc dir and implemented as a separate OC module");
1392     return malloc(size);
1393 }
1394
1395 void OCFree(void *ptr) {
1396     TODO ("This should be moved into an ocmalloc dir and implemented as a separate OC module");
1397     free(ptr);
1398 }
1399