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
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
sprintf((char *)fullUri, "%s%s", OC_MULTICAST_IP, rcvdUri);
cbNode = GetClientCB(NULL, NULL, fullUri);
isMulticastPresence = 1;
+ isPresenceNotification = 0;
}
#endif
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;
}
}
}
}
+ // 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
}
VERIFY_SUCCESS(result, OC_STACK_OK);
}
exit:
+ OCFree(resourceTypeName);
OCFree(response);
}
#include <ocstack.h>
#include <occoaptoken.h>
+#include <ocresource.h>
typedef struct OCPresence {
// This is the TTL associated with presence
// 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;
* @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.
*
*/
//------------------------------------------------------------------------
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 -----------------------------------------------------------
//------------------------------------------------------------------------
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
*
#define OC_COLLECTION_H
#include "ocstack.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
uint8_t GetNumOfResourcesInCollection (OCResource *resource);
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-#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_ */
--- /dev/null
+//******************************************************************
+//
+// 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
#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;
OCStackResult BindResourceTypeToResource(OCResource* resource,
const char *resourceTypeName);
+OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName);
#ifdef WITH_PRESENCE
//TODO: should the following function be public?
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
* 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
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) {
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;
}
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;
#include <string.h>
#include "ocstack.h"
#include "ocstackinternal.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
#include "logger.h"
#include "debug.h"
#include "cJSON.h"
#include "ocstackconfig.h"
#include "ocstackinternal.h"
#include "ocobserve.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
#include "occoap.h"
#include "utlist.h"
#include "debug.h"
{
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,
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);
#include "ocstack.h"
#include "ocstackconfig.h"
#include "ocstackinternal.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
#include "ocobserve.h"
#include "occollection.h"
#include "occoap.h"
else
{
if(resource->resourceProperties & OC_ACTIVE){
- SendPresenceNotification(resource->rsrcType);
+ SendPresenceNotification(NULL);
}
}
#endif
#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;} }
//-----------------------------------------------------------------------------
#include "ocstack.h"
#include "ocstackinternal.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
#include "occlientcb.h"
#include "ocobserve.h"
#include "ocrandom.h"
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();
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"));
#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;
requestUri = (unsigned char *) OCMalloc(uriLen + 1);
if(requestUri)
{
- memcpy(requestUri, newURI, (uriLen + 1));
+ memcpy(requestUri, newUri, (uriLen + 1));
}
else
{
// 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;
}
// 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)
{
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;
}
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,
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
}
/**
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;
}
/**
+ * 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
{
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, "?");
leftToken = strtok(NULL, "?");
}
- *newURI = ptr;
+ *newURI = tempURI;
return OC_STACK_OK;