Added support to allow more than one presence resource type filter.
authorJoseph Morrow <joseph.l.morrow@intel.com>
Mon, 8 Dec 2014 20:15:31 +0000 (15:15 -0500)
committerJoseph Morrow <joseph.l.morrow@intel.com>
Mon, 8 Dec 2014 20:15:31 +0000 (15:15 -0500)
Where only one filter was supported before, resource type filters must
be added one at a time through use of the OCDoResource() API, therefore
a call to OCDoResource() for every amend is req'd with this add-on.

Change-Id: I54a1166ad6992a26f133ed6797730fcdb4e9cf73
Signed-off-by: Joseph Morrow <joseph.l.morrow@intel.com>
13 files changed:
resource/csdk/occoap/src/occoap.c
resource/csdk/stack/include/internal/occlientcb.h
resource/csdk/stack/include/internal/occollection.h
resource/csdk/stack/include/internal/ocresource.h
resource/csdk/stack/include/internal/ocresourcehandler.h [new file with mode: 0644]
resource/csdk/stack/include/internal/ocstackinternal.h
resource/csdk/stack/include/ocstack.h
resource/csdk/stack/src/occlientcb.c
resource/csdk/stack/src/occollection.c
resource/csdk/stack/src/ocobserve.c
resource/csdk/stack/src/ocresource.c
resource/csdk/stack/src/ocserverrequest.c
resource/csdk/stack/src/ocstack.c

index 87d28fe..d29e7cd 100644 (file)
@@ -343,28 +343,30 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
     if(!strcmp((char *)rcvdUri, (char *)OC_PRESENCE_URI)){
         isPresenceNotification = 1;
         OC_LOG(INFO, TAG, PCF("Received a presence notification"));
-        tok = strtok((char *)bufRes, "[:]");
-        tok = strtok(NULL, "[:]");
+        tok = strtok((char *)bufRes, "[:]}");
+        bufRes[strlen((char *)bufRes)] = ':';
+        tok = strtok(NULL, "[:]}");
+        bufRes[strlen((char *)bufRes)] = ':';
         VERIFY_NON_NULL(tok);
         sequenceNumber = (uint32_t )atol(tok);
         OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", sequenceNumber);
-        tok = strtok(NULL, "[:]");
+        tok = strtok(NULL, "[:]}");
         VERIFY_NON_NULL(tok);
         maxAge = (uint32_t )atol(tok);
         OC_LOG_V(DEBUG, TAG, "The received TTL is %u", maxAge);
-        tok = strtok(NULL, "[:]");
-        bufRes[strlen((char *)bufRes)] = ':';
+        tok = strtok(NULL, "[:]}");
         if(tok) {
+            bufRes[strlen((char *)bufRes)] = ':';
             resourceTypeName = (char *)OCMalloc(strlen(tok));
             if(!resourceTypeName)
             {
                 goto exit;
             }
             strcpy(resourceTypeName, tok);
-            bufRes[strlen((char *)bufRes)] = ':';
             OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s",
                     resourceTypeName);
         }
+        bufRes[strlen((char *)bufRes)] = ']';
     }
     #endif
 
@@ -381,7 +383,7 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
     cbNode = GetClientCB(&rcvdToken, NULL, NULL);
 
     #ifdef WITH_PRESENCE
-    // Check if the application subcribed for presence
+    // Check if the application subscribed for presence
     if(!cbNode)
     {
         // get the address of the remote
@@ -400,6 +402,7 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
         sprintf((char *)fullUri, "%s%s", OC_MULTICAST_IP, rcvdUri);
         cbNode = GetClientCB(NULL, NULL, fullUri);
         isMulticastPresence = 1;
+        isPresenceNotification = 0;
     }
     #endif
 
@@ -511,12 +514,11 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
                     cbNode->sequenceNumber = clientResponse.sequenceNumber;;
                 }
 
+                // Ensure that a filter is actually applied.
                 if(resourceTypeName && response->cbNode->filterResourceType)
                 {
-                    if(strcmp(resourceTypeName,
-                            (const char *)response->cbNode->filterResourceType)!=0)
+                    if(!findResourceType(response->cbNode->filterResourceType, resourceTypeName))
                     {
-                        //Ignore presence callback if resource type does not match filter.
                         goto exit;
                     }
                 }
@@ -564,16 +566,14 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
                     }
                 }
 
+                // Ensure that a filter is actually applied.
                 if(resourceTypeName && response->cbNode->filterResourceType)
                 {
-                    if(strcmp(resourceTypeName,
-                            (const char *)response->cbNode->filterResourceType)!=0)
+                    if(!findResourceType(response->cbNode->filterResourceType, resourceTypeName))
                     {
-                        //Ignore presence callback if resource type does not match filter.
                         goto exit;
                     }
                 }
-
             }
             #endif
         }
@@ -609,6 +609,7 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
         VERIFY_SUCCESS(result, OC_STACK_OK);
     }
     exit:
+        OCFree(resourceTypeName);
         OCFree(response);
 }
 
index 0f3a49f..67c58a9 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <ocstack.h>
 #include <occoaptoken.h>
+#include <ocresource.h>
 
 typedef struct OCPresence {
     // This is the TTL associated with presence
@@ -61,7 +62,7 @@ typedef struct ClientCB {
     // Struct to hold TTL info for presence
     #ifdef WITH_PRESENCE
     OCPresence * presence;
-    unsigned char * filterResourceType;
+    OCResourceType * filterResourceType;
     #endif
     // next node in this list
     struct ClientCB    *next;
@@ -85,7 +86,7 @@ extern struct ClientCB *cbList;
  * @param[in] requestUri
  *              the resource uri of the request.
  * @param[in] resourceType
- *              the resourceType associated with this request.
+ *              the resourceType associated with a presence request.
  *
  * @brief If the handle you're looking for does not exist, the stack will reply with a RST message.
  *
@@ -93,7 +94,7 @@ extern struct ClientCB *cbList;
  */
 //------------------------------------------------------------------------
 OCStackResult AddClientCB(ClientCB** clientCB, OCCallbackData* cbData,
-        OCCoAPToken * token, OCDoHandle handle, OCMethod method,
+        OCCoAPToken * token, OCDoHandle *handle, OCMethod method,
         unsigned char * requestUri, unsigned char * resourceType);
 
 //-- DeleteClientCB -----------------------------------------------------------
@@ -127,6 +128,20 @@ void DeleteClientCB(ClientCB *cbNode);
 //------------------------------------------------------------------------
 ClientCB* GetClientCB(OCCoAPToken * token, OCDoHandle handle, unsigned char * requestUri);
 
+
+/**
+ * Inserts a new resource type filter into this clientCB node.
+ *
+ * @param cbNode - the node to add the new resourceType filter to
+ * @param resourceTypeName - the value to create the new resourceType filter from
+ *
+ * @return
+ *      OC_STACK_OK on success
+ *      OC_STACK_ERROR with invalid parameters
+ *      OC_STACK_NO_MEMORY when out of memory
+ */
+OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, const char * resourceTypeName);
+
 //-- DeleteClientCBList --------------------------------------------------
 /** @ingroup ocstack
  *
index 512ec93..e421d06 100644 (file)
@@ -22,7 +22,7 @@
 #define OC_COLLECTION_H
 
 #include "ocstack.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
 
 uint8_t GetNumOfResourcesInCollection (OCResource *resource);
 
index 62d5363..542cfb6 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-#ifndef OC_RESOURCE_H
-#define OC_RESOURCE_H
-
-#include "ocstack.h"
-#include "ocstackinternal.h"
-#include "ocserverrequest.h"
-
-#define OC_RSRVD_OC                     "oc"
-#define OC_RSRVD_PAYLOAD                "payload"
-#define OC_RSRVD_HREF                   "href"
-#define OC_RSRVD_RESOURCE_TYPE          "rt"
-#define OC_RSRVD_INTERFACE              "if"
-#define OC_RSRVD_INTERFACE_DEFAULT      "oc.mi.def"
-#define OC_RSRVD_INTERFACE_LL           "oc.mi.ll"
-#define OC_RSRVD_INTERFACE_BATCH        "oc.mi.b"
-#define OC_RSRVD_OBSERVABLE             "obs"
-#define OC_RSRVD_SECURE                 "sec"
-#define OC_RSRVD_HOSTING_PORT           "port"
-
-#define OC_JSON_PREFIX                     "{\"oc\":["
-#define OC_JSON_PREFIX_LEN                 (sizeof(OC_JSON_PREFIX) - 1)
-#define OC_JSON_SUFFIX                     "]}"
-#define OC_JSON_SUFFIX_LEN                 (sizeof(OC_JSON_SUFFIX) - 1)
-#define OC_JSON_SEPARATOR                  ','
-
-#define OC_RESOURCE_OBSERVABLE   1
-#define OC_RESOURCE_SECURE       1
+#ifndef OCRESOURCE_H_
+#define OCRESOURCE_H_
 
-typedef enum {
-    STACK_RES_DISCOVERY_NOFILTER = 0,
-    STACK_RES_DISCOVERY_IF_FILTER,
-    STACK_RES_DISCOVERY_RT_FILTER
-} StackQueryTypes;
+#define OC_OBSERVER_NOT_INTERESTED       (0)
+#define OC_OBSERVER_STILL_INTERESTED     (1)
+#define OC_OBSERVER_FAILED_COMM          (2)
+
+//-----------------------------------------------------------------------------
+// Virtual Resource Presence Attributes
+//-----------------------------------------------------------------------------
+#ifdef WITH_PRESENCE
+typedef struct PRESENCERESOURCE{
+    OCResourceHandle handle;
+    uint32_t presenceTTL;
+} PresenceResource;
+#endif
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+struct rsrc_t;
+
+//-----------------------------------------------------------------------------
+// Typedefs
+//-----------------------------------------------------------------------------
 
+// IF here stands for Interface
 typedef enum {
-    OC_RESOURCE_VIRTUAL = 0,
-    OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER,
-    OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER,
-    OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER,
-    OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER,
-    OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER,
-    OC_RESOURCE_NOT_SPECIFIED
-} ResourceHandling;
+    STACK_IF_DEFAULT = 0,
+    STACK_IF_LL,
+    STACK_IF_BATCH,
+    STACK_IF_INVALID
+} OCStackIfTypes;
+
+typedef struct resourcetype_t {
+    struct resourcetype_t *next; // linked list; for multiple types on resource
+
+    // Name of the type; this string is ‘.’ (dot) separate list of segments where each segment is a
+    // namespace and the final segment is the type; type and sub-types can be separate with
+    // ‘-‘ (dash) usually only two segments would be defined. Either way this string is meant to be
+    // human friendly and is used opaquely and not parsed by code. This name is used in the “rt=”
+    // parameter of a resource description when resources are introspected and is also use in the
+    // <base URI>/types list of available types.
+    char *resourcetypename;
+} OCResourceType;
+
+typedef struct attr_t {
+    struct attr_t *next; // Points to next resource in list
+
+    // The name of the attribute; used to look up the attribute in list;
+    // for a given attribute SHOULD not be changed once assigned
+    const char *attrName;
+    char *attrValue; // value of the attribute as string
+} OCAttribute;
 
-OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest * request);
+typedef struct resourceinterface_t {
+    struct resourceinterface_t *next; // linked list; for multiple interfaces on resource
 
-const char * GetVirtualResourceUri( OCVirtualResources resource);
-OCResource *FindResourceByUri(const char* resourceUri);
-uint8_t IsVirtualResource(const char* resourceUri);
+    // Name of the interface; this is ‘.’ (dot) separate list of segments where each segment is a
+    // namespace and the final segment is the interface; usually only two segments would be
+    // defined. Either way this string is opaque and not parsed by segment
+    char *name ;
 
-OCStackResult DetermineResourceHandling (OCServerRequest *request,
-                                         ResourceHandling *handling,
-                                         OCResource **resource);
+    // Supported content types to serialize request and response on this interface
+    // (REMOVE for V1 – only jSON for all but core.ll that uses Link Format)
+#if 0
+    char *inputContentType ;
+    char *outputContentType ;
+#endif
+    /*** Future placeholder for access control and policy ***/
+} OCResourceInterface;
 
-OCStackResult
-ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request);
+typedef struct rsrc_t {
+    struct rsrc_t *next; // Points to next resource in list
+    // Relative path on the device; will be combined with base url to create fully qualified path
+    char *host;
+    char *uri;
+    OCResourceType *rsrcType; // Resource type(s); linked list
+    OCResourceInterface *rsrcInterface; // Resource interface(s); linked list
+    OCAttribute *rsrcAttributes; // Resource interface(s); linked list
+    // Array of pointers to resources; can be used to represent a container of resources
+    // (i.e. hierarchies of resources) or for reference resources (i.e. for a resource collection)
+    struct rsrc_t *rsrcResources[MAX_CONTAINED_RESOURCES];
+    //struct rsrc_t *rsrcResources;
+    // Pointer to function that handles the entity bound to the resource.
+    // This handler has to be explicitly defined by the programmer
+    OCEntityHandler entityHandler;
+    // Properties on the resource – defines meta information on the resource
+    OCResourceProperty resourceProperties ; /* ACTIVE, DISCOVERABLE etc */
+    // Pointer to an opaque object where app/user specific data can be placed with the resource;
+    // this could be information for the entity handler between invocations
+    void *context;
+    // NOTE: Methods supported by this resource should be based on the interface targeted
+    // i.e. look into the interface structure based on the query request Can be removed here;
+    // place holder for the note above
+    /* method_t methods; */
+    // Sequence number for observable resources. Per the CoAP standard it is a 24 bit value.
+    uint32_t sequenceNum;
+} OCResource;
 
-OCStackResult
-BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filterOn,
-                        char *filterValue, char * out, uint16_t *remaining);
 
-OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult);
 
-#endif //OC_RESOURCE_H
+#endif /* OCRESOURCE_H_ */
diff --git a/resource/csdk/stack/include/internal/ocresourcehandler.h b/resource/csdk/stack/include/internal/ocresourcehandler.h
new file mode 100644 (file)
index 0000000..e5a24bc
--- /dev/null
@@ -0,0 +1,86 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef OC_RESOURCEHANDLER_H
+#define OC_RESOURCEHANDLER_H
+
+#include "ocstack.h"
+#include "ocstackinternal.h"
+#include "ocserverrequest.h"
+
+#define OC_RSRVD_OC                     "oc"
+#define OC_RSRVD_PAYLOAD                "payload"
+#define OC_RSRVD_HREF                   "href"
+#define OC_RSRVD_RESOURCE_TYPE          "rt"
+#define OC_RSRVD_RESOURCE_TYPE_PRESENCE "core.presence"
+#define OC_RSRVD_INTERFACE              "if"
+#define OC_RSRVD_INTERFACE_DEFAULT      "oc.mi.def"
+#define OC_RSRVD_INTERFACE_LL           "oc.mi.ll"
+#define OC_RSRVD_INTERFACE_BATCH        "oc.mi.b"
+#define OC_RSRVD_OBSERVABLE             "obs"
+#define OC_RSRVD_SECURE                 "sec"
+#define OC_RSRVD_HOSTING_PORT           "port"
+
+#define OC_JSON_PREFIX                     "{\"oc\":["
+#define OC_JSON_PREFIX_LEN                 (sizeof(OC_JSON_PREFIX) - 1)
+#define OC_JSON_SUFFIX                     "]}"
+#define OC_JSON_SUFFIX_LEN                 (sizeof(OC_JSON_SUFFIX) - 1)
+#define OC_JSON_SEPARATOR                  ','
+
+#define OC_RESOURCE_OBSERVABLE   1
+#define OC_RESOURCE_SECURE       1
+
+typedef enum {
+    STACK_RES_DISCOVERY_NOFILTER = 0,
+    STACK_RES_DISCOVERY_IF_FILTER,
+    STACK_RES_DISCOVERY_RT_FILTER
+} StackQueryTypes;
+
+typedef enum {
+    OC_RESOURCE_VIRTUAL = 0,
+    OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER,
+    OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER,
+    OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER,
+    OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER,
+    OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER,
+    OC_RESOURCE_NOT_SPECIFIED
+} ResourceHandling;
+
+OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest * request);
+
+const char * GetVirtualResourceUri( OCVirtualResources resource);
+OCResource *FindResourceByUri(const char* resourceUri);
+uint8_t IsVirtualResource(const char* resourceUri);
+
+OCStackResult DetermineResourceHandling (OCServerRequest *request,
+                                         ResourceHandling *handling,
+                                         OCResource **resource);
+
+OCStackResult
+ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request);
+
+OCStackResult
+BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filterOn,
+                        char *filterValue, char * out, uint16_t *remaining);
+
+OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult);
+
+#endif //OC_RESOURCEHANDLER_H
index 713b123..2d8b217 100644 (file)
@@ -51,102 +51,6 @@ extern OCDeviceEntityHandler defaultDeviceHandler;
 #define OC_COAP_SCHEME "coap://"
 #define OC_OFFSET_SEQUENCE_NUMBER (4) // the first outgoing sequence number will be 5
 
-#define OC_OBSERVER_NOT_INTERESTED       (0)
-#define OC_OBSERVER_STILL_INTERESTED     (1)
-#define OC_OBSERVER_FAILED_COMM          (2)
-
-//-----------------------------------------------------------------------------
-// Virtual Resource Presence Attributes
-//-----------------------------------------------------------------------------
-#ifdef WITH_PRESENCE
-typedef struct PRESENCERESOURCE{
-    OCResourceHandle handle;
-    uint32_t presenceTTL;
-} PresenceResource;
-#endif
-
-//-----------------------------------------------------------------------------
-// Forward declarations
-//-----------------------------------------------------------------------------
-struct rsrc_t;
-
-//-----------------------------------------------------------------------------
-// Typedefs
-//-----------------------------------------------------------------------------
-
-// IF here stands for Interface
-typedef enum {
-    STACK_IF_DEFAULT = 0,
-    STACK_IF_LL,
-    STACK_IF_BATCH,
-    STACK_IF_INVALID
-} OCStackIfTypes;
-
-typedef struct resourcetype_t {
-    struct resourcetype_t *next; // linked list; for multiple types on resource
-
-    // Name of the type; this string is ‘.’ (dot) separate list of segments where each segment is a
-    // namespace and the final segment is the type; type and sub-types can be separate with ‘-‘ (dash)
-    // usually only two segments would be defined. Either way this string is meant to be human friendly
-    // and is used opaquely and not parsed by code
-    // This name is used in the “rt=” parameter of a resource description when resources are introspected
-    // and is also use in the <base URI>/types list of available types
-    char *resourcetypename;
-} OCResourceType;
-
-typedef struct attr_t {
-    struct attr_t *next; // Points to next resource in list
-
-    // The name of the attribute; used to look up the attribute in list;
-    // for a given attribute SHOULD not be changed once assigned
-    const char *attrName;
-    char *attrValue; // value of the attribute as string
-} OCAttribute;
-
-typedef struct resourceinterface_t {
-    struct resourceinterface_t *next; // linked list; for multiple interfaces on resource
-
-    // Name of the interface; this is ‘.’ (dot) separate list of segments where each segment is
-    // a namespace and the final segment is the interface; usually only two segments would be defined.
-    // Either way this string is opaque and not parsed by segment
-    char *name ;
-
-    // Supported content types to serialize request and response on this interface
-    // (REMOVE for V1 – only jSON for all but core.ll that uses Link Format)
-#if 0
-    char *inputContentType ;
-    char *outputContentType ;
-#endif
-    /*** Future placeholder for access control and policy ***/
-} OCResourceInterface;
-
-typedef struct rsrc_t {
-    struct rsrc_t *next; // Points to next resource in list
-    // Relative path on the device; will be combined with base url to create fully qualified path
-    char *host;
-    char *uri;
-    OCResourceType *rsrcType; // Resource type(s); linked list
-    OCResourceInterface *rsrcInterface; // Resource interface(s); linked list
-    OCAttribute *rsrcAttributes; // Resource interface(s); linked list
-    // Array of pointers to resources; can be used to represent a container of resources
-    // (i.e. hierarchies of resources) or for reference resources (i.e. for a resource collection)
-    struct rsrc_t *rsrcResources[MAX_CONTAINED_RESOURCES];
-    //struct rsrc_t *rsrcResources;
-    // Pointer to function that handles the entity bound to the resource.
-    // This handler has to be explicitly defined by the programmer
-    OCEntityHandler entityHandler;
-    // Properties on the resource – defines meta information on the resource
-    OCResourceProperty resourceProperties ; /* ACTIVE, DISCOVERABLE etc */
-    // Pointer to an opaque object where app/user specific data can be placed with the resource;
-    // this could be information for the entity handler between invocations
-    void *context;
-    // NOTE: Methods supported by this resource should be based on the interface targeted
-    // i.e. look into the interface structure based on the query request Can be removed here; place holder for the note above
-    /* method_t methods; */
-    // Sequence number for observable resources. Per the CoAP standard it is a 24 bit value.
-    uint32_t sequenceNum;
-} OCResource;
-
 typedef struct {
     // Observe option field
     uint32_t option;
@@ -250,6 +154,7 @@ OCStackResult BindResourceInterfaceToResource(OCResource* resource,
 
 OCStackResult BindResourceTypeToResource(OCResource* resource,
                                             const char *resourceTypeName);
+OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName);
 
 #ifdef WITH_PRESENCE
 //TODO: should the following function be public?
index 343a874..ca6efcb 100644 (file)
@@ -395,9 +395,11 @@ OCStackResult OCStop();
 OCStackResult OCProcess();
 
 /**
- * Discover or Perform requests on a specified resource (specified by that Resource's respective URI).
+ * Discover or Perform requests on a specified resource (specified by that Resource's respective
+ * URI).
  *
- * @param handle             - @ref OCDoHandle to refer to the request sent out on behalf of calling this API.
+ * @param handle             - @ref OCDoHandle to refer to the request sent out on behalf of
+ *                             calling this API.
  * @param method             - @ref OCMethod to perform on the resource
  * @param requiredUri        - URI of the resource to interact with
  * @param referenceUri       - URI of the reference resource
@@ -409,6 +411,10 @@ OCStackResult OCProcess();
  *                             header options to be sent with the request
  * @param numOptions         - Number of header options to be included
  *
+ * Note: Presence subscription amendments (ie. adding additional resource type filters by calling
+ * this API again) require the use of the same base URI as the original request to successfully
+ * amend the presence filters.
+ *
  * @return
  *     OC_STACK_OK               - no errors
  *     OC_STACK_INVALID_CALLBACK - invalid callback function pointer
index e5e98e3..9e0b232 100644 (file)
@@ -33,29 +33,65 @@ struct ClientCB *cbList = NULL;
 OCMulticastNode * mcPresenceNodes = NULL;
 
 OCStackResult AddClientCB(ClientCB** clientCB, OCCallbackData* cbData,
-        OCCoAPToken * token, OCDoHandle handle, OCMethod method,
-        unsigned char * requestUri, unsigned char * resourceType) {
-    ClientCB *cbNode;
-    cbNode = (ClientCB*) OCMalloc(sizeof(ClientCB));
-    if (cbNode) {
-        cbNode->callBack = cbData->cb;
-        cbNode->context = cbData->context;
-        cbNode->deleteCallback = cbData->cd;
-        memcpy(&(cbNode->token), token, sizeof(OCCoAPToken));
-        cbNode->handle = handle;
-        cbNode->method = method;
-        cbNode->sequenceNumber = 0;
-        #ifdef WITH_PRESENCE
-        cbNode->presence = NULL;
-        cbNode->filterResourceType = resourceType;
-        #endif
-        cbNode->requestUri = requestUri;
-        LL_APPEND(cbList, cbNode);
+        OCCoAPToken * token, OCDoHandle *handle, OCMethod method,
+        unsigned char * requestUri, unsigned char * resourceTypeName) {
+
+    ClientCB *cbNode = NULL;
+
+    #ifdef WITH_PRESENCE
+    if(method == OC_REST_PRESENCE)
+    {   // Retrieve the presence callback structure for this specific requestUri.
+        cbNode = GetClientCB(NULL, NULL, requestUri);
+    }
+    #endif // WITH_PRESENCE
+
+    if(!cbNode)// If it does not already exist, create new node.
+    {
+        cbNode = (ClientCB*) OCMalloc(sizeof(ClientCB));
+        if(!cbNode)
+        {
+            *clientCB = NULL;
+            goto exit;
+        }
+        else
+        {
+            cbNode->callBack = cbData->cb;
+            cbNode->context = cbData->context;
+            cbNode->deleteCallback = cbData->cd;
+            memcpy(&(cbNode->token), token, sizeof(OCCoAPToken));
+            cbNode->handle = *handle;
+            cbNode->method = method;
+            cbNode->sequenceNumber = 0;
+            #ifdef WITH_PRESENCE
+            cbNode->presence = NULL;
+            cbNode->filterResourceType = NULL;
+            #endif // WITH_PRESENCE
+            cbNode->requestUri = requestUri;
+            LL_APPEND(cbList, cbNode);
+            *clientCB = cbNode;
+        }
+    }
+    else
+    {
+        // Ensure that the handle the SDK hands back up to the application layer for the
+        // OCDoResource call matches the found ClientCB Node.
         *clientCB = cbNode;
-        return OC_STACK_OK;
+        OCFree(requestUri);
+        OCFree(*handle);
+        *handle = cbNode->handle;
     }
-    *clientCB = NULL;
-    return OC_STACK_NO_MEMORY;
+
+    #ifdef WITH_PRESENCE
+    if(method == OC_REST_PRESENCE && resourceTypeName)
+    {   // Amend the found or created node by adding a new resourceType to it.
+        return InsertResourceTypeFilter(cbNode, (const char *)resourceTypeName);
+    }
+    #endif
+
+    return OC_STACK_OK;
+
+    exit:
+        return OC_STACK_NO_MEMORY;
 }
 
 void DeleteClientCB(ClientCB * cbNode) {
@@ -74,9 +110,20 @@ void DeleteClientCB(ClientCB * cbNode) {
         if(cbNode->presence) {
             OCFree(cbNode->presence->timeOut);
             OCFree(cbNode->presence);
-            OCFree(cbNode->filterResourceType);
         }
-        #endif
+        if(cbNode->method == OC_REST_PRESENCE)
+        {
+            OCResourceType * pointer = cbNode->filterResourceType;
+            OCResourceType * next = NULL;
+            while(pointer)
+            {
+                next = pointer->next;
+                OCFree(pointer->resourcetypename);
+                OCFree(pointer);
+                pointer = next;
+            }
+        }
+        #endif // WITH_PRESENCE
         OCFree(cbNode);
         cbNode = NULL;
     }
@@ -113,6 +160,26 @@ ClientCB* GetClientCB(OCCoAPToken * token, OCDoHandle handle, unsigned char * re
     return NULL;
 }
 
+OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, const char * resourceTypeName)
+{
+    OCResourceType * newResourceType = NULL;
+    if(cbNode && resourceTypeName)
+    {
+        // Form a new resourceType member.
+        newResourceType = (OCResourceType *) OCMalloc(sizeof(OCResourceType));
+        if(!newResourceType)
+        {
+            return OC_STACK_NO_MEMORY;
+        }
+
+        newResourceType->next = NULL;
+        newResourceType->resourcetypename = (char *) resourceTypeName;
+
+        LL_APPEND(cbNode->filterResourceType, newResourceType);
+        return OC_STACK_OK;
+    }
+    return OC_STACK_ERROR;
+}
 
 void DeleteClientCBList() {
     ClientCB* out;
index a5a4000..68ea8a0 100644 (file)
@@ -22,7 +22,7 @@
 #include <string.h>
 #include "ocstack.h"
 #include "ocstackinternal.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
 #include "logger.h"
 #include "debug.h"
 #include "cJSON.h"
index eb624ce..fc6737d 100644 (file)
@@ -23,7 +23,7 @@
 #include "ocstackconfig.h"
 #include "ocstackinternal.h"
 #include "ocobserve.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
 #include "occoap.h"
 #include "utlist.h"
 #include "debug.h"
@@ -134,7 +134,7 @@ OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr,
             {
                 OCEntityHandlerResponse ehResponse = {0};
                 unsigned char presenceResBuf[MAX_RESPONSE_LENGTH] = {0};
-                //we know it is the default entity handler
+                //This is effectively the implementation for the presence entity handler.
                 OC_LOG(DEBUG, TAG, PCF("This notification is for Presence"));
                 result = AddServerRequest(&request, 0, 0, 0, 1, OC_REST_GET,
                         0, OC_OBSERVE_NO_OPTION, OC_LOW_QOS,
@@ -143,7 +143,7 @@ OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr,
                 if(result == OC_STACK_OK)
                 {
                     // we create the payload here
-                    if(resourceType)
+                    if(resourceType && resourceType->resourcetypename)
                     {
                         sprintf((char *)presenceResBuf, "%u:%u:%s",
                                 resPtr->sequenceNum, maxAge, resourceType->resourcetypename);
index 3ee30cb..01abbc1 100644 (file)
@@ -22,7 +22,7 @@
 #include "ocstack.h"
 #include "ocstackconfig.h"
 #include "ocstackinternal.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
 #include "ocobserve.h"
 #include "occollection.h"
 #include "occoap.h"
@@ -431,7 +431,7 @@ HandleVirtualResource (OCServerRequest *request, OCResource* resource)
         else
         {
             if(resource->resourceProperties & OC_ACTIVE){
-                SendPresenceNotification(resource->rsrcType);
+                SendPresenceNotification(NULL);
             }
         }
         #endif
index 44d3f6c..882db9d 100644 (file)
@@ -20,7 +20,7 @@
 
 #include "ocstack.h"
 #include "ocserverrequest.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
 
 // Module Name
 #define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
index 2738c96..2e5400f 100644 (file)
@@ -24,7 +24,7 @@
 //-----------------------------------------------------------------------------
 #include "ocstack.h"
 #include "ocstackinternal.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
 #include "occlientcb.h"
 #include "ocobserve.h"
 #include "ocrandom.h"
@@ -440,6 +440,12 @@ OCStackResult OCStop()
         return OC_STACK_ERROR;
     }
 
+    #ifdef WITH_PRESENCE
+    // Ensure that the TTL associated with ANY and ALL presence notifications originating from
+    // here send with the code "OC_STACK_PRESENCE_STOPPED" result.
+    presenceResource.presenceTTL = 0;
+    #endif // WITH_PRESENCE
+
     // Free memory dynamically allocated for resources
     deleteAllResources();
 
@@ -532,7 +538,7 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
     ClientCB *clientCB = NULL;
     unsigned char * requestUri = NULL;
     unsigned char * resourceType = NULL;
-    char * newURI = (char *)requiredUri;
+    char * newUri = (char *)requiredUri;
     (void) referenceUri;
 
     OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
@@ -580,7 +586,14 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
 #ifdef WITH_PRESENCE
     if(method == OC_REST_PRESENCE)
     {
-        result = getResourceType(requiredUri, &resourceType, &newURI);
+        result = getResourceType(requiredUri, &resourceType, &newUri);
+        if(resourceType) {
+            OC_LOG_V(DEBUG, TAG, "Got Resource Type: %s", resourceType);
+        }
+        else
+        {
+            OC_LOG(DEBUG, TAG, "Got Resource Type is NULL.");
+        }
         if(result != OC_STACK_OK)
         {
             goto exit;
@@ -591,7 +604,7 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
     requestUri = (unsigned char *) OCMalloc(uriLen + 1);
     if(requestUri)
     {
-        memcpy(requestUri, newURI, (uriLen + 1));
+        memcpy(requestUri, newUri, (uriLen + 1));
     }
     else
     {
@@ -610,7 +623,7 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
     // with the request
     OCGenerateCoAPToken(&token);
 
-    if((result = AddClientCB(&clientCB, cbData, &token, *handle, method, requestUri, resourceType))
+    if((result = AddClientCB(&clientCB, cbData, &token, handle, method, requestUri, resourceType))
             != OC_STACK_OK)
     {
         result = OC_STACK_NO_MEMORY;
@@ -618,12 +631,12 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
     }
 
     // Make call to OCCoAP layer
-    result = OCDoCoAPResource(method, qos, &token, newURI, request, options, numOptions);
+    result = OCDoCoAPResource(method, qos, &token, newUri, request, options, numOptions);
 
 exit:
-    if(newURI != requiredUri)
+    if(newUri != requiredUri)
     {
-        OCFree(newURI);
+        OCFree(newUri);
     }
     if (result != OC_STACK_OK)
     {
@@ -1737,10 +1750,18 @@ OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService q
     OCMethod method = OC_REST_NOMETHOD;
     uint32_t maxAge = 0;
 
+    OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
+    #ifdef WITH_PRESENCE
+    if(handle == presenceResource.handle)
+    {
+        return OC_STACK_OK;
+    }
+    #endif // WITH_PRESENCE
     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
+
     // Verify that the resource exists
     resPtr = findResource ((OCResource *) handle);
-    if (NULL == resPtr || myStackMode == OC_CLIENT)
+    if (NULL == resPtr)
     {
         return OC_STACK_NO_RESOURCE;
     }
@@ -1920,7 +1941,7 @@ OCStackResult initResources() {
     presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL;
     //presenceResource.token = OCGenerateCoAPToken();
     result = OCCreateResource(&presenceResource.handle,
-            "core.presence",
+            OC_RSRVD_RESOURCE_TYPE_PRESENCE,
             "core.r",
             OC_PRESENCE_URI,
             NULL,
@@ -1982,9 +2003,22 @@ void deleteAllResources()
     while (pointer)
     {
         temp = pointer->next;
-        deleteResource(pointer);
+        #ifdef WITH_PRESENCE
+        if(pointer != (OCResource *) presenceResource.handle)
+        {
+            #endif // WITH_PRESENCE
+            deleteResource(pointer);
+            #ifdef WITH_PRESENCE
+        }
+        #endif // WITH_PRESENCE
         pointer = temp;
     }
+
+    #ifdef WITH_PRESENCE
+    // Ensure that the last resource to be deleted is the presence resource. This allows for all
+    // presence notification attributed to their deletion to be processed.
+    deleteResource((OCResource *) presenceResource.handle);
+    #endif // WITH_PRESENCE
 }
 
 /**
@@ -2004,15 +2038,27 @@ int deleteResource(OCResource *resource) {
         if (temp == resource) {
             // Invalidate all Resource Properties.
             resource->resourceProperties = (OCResourceProperty) 0;
-            OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
-
             #ifdef WITH_PRESENCE
+            if(resource != (OCResource *) presenceResource.handle)
+            {
+            #endif // WITH_PRESENCE
+                OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
+            #ifdef WITH_PRESENCE
+            }
+
             if(presenceResource.handle)
             {
                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
-                SendPresenceNotification(resource->rsrcType);
+                if(resource != (OCResource *) presenceResource.handle)
+                {
+                    SendPresenceNotification(resource->rsrcType);
+                }
+                else
+                {
+                    SendPresenceNotification(NULL);
+                }
             }
-            #endif
+        #endif
 
             if (temp == headResource) {
                 headResource = temp->next;
@@ -2151,6 +2197,35 @@ OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index)
 }
 
 /**
+ * Finds a resource type in an OCResourceType link-list.
+ *
+ * @param resourceTypeList - the link-list to be searched through
+ * @param resourceTypeName - the key to search for
+ *
+ * @return
+ *      resourceType that matches the key (ie. resourceTypeName)
+ *      NULL - either an invalid parameter or this function was unable to find the key.
+ */
+OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName)
+{
+    if(resourceTypeList && resourceTypeName)
+    {
+        OCResourceType * rtPointer = resourceTypeList;
+        while(resourceTypeName && rtPointer)
+        {
+            if(rtPointer->resourcetypename &&
+                    strcmp(resourceTypeName, (const char *)
+                    (rtPointer->resourcetypename)) == 0)
+            {
+                break;
+            }
+            rtPointer = rtPointer->next;
+        }
+        return rtPointer;
+    }
+    return NULL;
+}
+/**
  * Insert a resource interface into a resource's resource interface linked list.
  *
  * @param resource - resource where resource interface is to be inserted
@@ -2275,14 +2350,12 @@ OCStackResult getResourceType(const char * uri, unsigned char** resourceType, ch
     {
         return OC_STACK_INVALID_PARAM;
     }
-    char * ptr = NULL;
     char * leftToken = NULL;
     char * tempURI = (char *) OCMalloc(strlen(uri));
     if(!tempURI)
     {
         goto exit;
     }
-    ptr = tempURI;
     strcpy(tempURI, uri);
     leftToken = strtok((char *)tempURI, "?");
 
@@ -2301,7 +2374,7 @@ OCStackResult getResourceType(const char * uri, unsigned char** resourceType, ch
         leftToken = strtok(NULL, "?");
     }
 
-    *newURI = ptr;
+    *newURI = tempURI;
 
     return OC_STACK_OK;