#include "oic_string.h"
#include "ocpayload.h"
#include "ocserverrequest.h"
+#include "octhread.h"
#include "logger.h"
#include <coap/utlist.h>
#define VERIFY_NON_NULL(arg) { if (!arg) {OIC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
static struct ResourceObserver * g_serverObsList = NULL;
+static oc_mutex g_serverObsListMutex = NULL;
+
+static ResourceObserver* GetObserverUsingIdAsOwner (const OCObservationId observeId);
+
+static ResourceObserver* CloneObserverNode (ResourceObserver* observer)
+{
+ ResourceObserver* dupObsNode = NULL;
+ if (observer)
+ {
+ dupObsNode = (ResourceObserver *) OICCalloc(1, sizeof(ResourceObserver));
+ VERIFY_NON_NULL(dupObsNode);
+ memcpy(dupObsNode, observer, sizeof(ResourceObserver));
+
+ if (observer->resUri)
+ {
+ dupObsNode->resUri = OICStrdup(observer->resUri);
+ VERIFY_NON_NULL(dupObsNode->resUri);
+ }
+
+ if (observer->query)
+ {
+ dupObsNode->query = OICStrdup(observer->query);
+ VERIFY_NON_NULL(dupObsNode->query);
+ }
+
+ if (observer->token)
+ {
+ dupObsNode->token = (CAToken_t)OICMalloc(observer->tokenLength);
+ VERIFY_NON_NULL(dupObsNode->token);
+ memcpy(dupObsNode->token, observer->token, observer->tokenLength);
+ }
+
+ dupObsNode->next = NULL;
+ }
+
+ return dupObsNode;
+
+exit:
+ FreeObserver(dupObsNode);
+ return NULL;
+}
+
+static void FreeObserverList (ResourceObserver* list)
+{
+ ResourceObserver* head = list;
+ ResourceObserver* del = NULL;
+ while (NULL != head)
+ {
+ del = head;
+ head = head->next;
+
+ OICFree(del->resUri);
+ OICFree(del->query);
+ OICFree(del->token);
+ OICFree(del);
+ }
+}
+
+static ResourceObserver* CloneObserverList (ResourceObserver* obsList)
+{
+ ResourceObserver* dupList = NULL;
+ ResourceObserver* out = NULL;
+
+ LL_FOREACH(obsList, out)
+ {
+ ResourceObserver *obsNode = CloneObserverNode(out);
+ if (NULL == obsNode)
+ {
+ FreeObserverList(dupList);
+ dupList = NULL;
+ break;
+ }
+
+ LL_APPEND(dupList, obsNode);
+ }
+
+ return dupList;
+}
+
/**
* Determine observe QOS based on the QOS of the request.
* The qos passed as a parameter overrides what the client requested.
}
OCStackResult result = OC_STACK_ERROR;
- ResourceObserver * resourceObserver = g_serverObsList;
+ ResourceObserver * resourceObserver = NULL;
uint8_t numObs = 0;
OCServerRequest * request = NULL;
- OCEntityHandlerRequest ehRequest = {0};
- OCEntityHandlerResult ehResult = OC_EH_ERROR;
bool observeErrorFlag = false;
// Find clients that are observing this resource
+ oc_mutex_lock(g_serverObsListMutex);
+ resourceObserver = g_serverObsList;
while (resourceObserver)
{
if (resourceObserver->resource == resPtr)
if (!presenceResBuf)
{
+ oc_mutex_unlock(g_serverObsListMutex);
return OC_STACK_NO_MEMORY;
}
resourceObserver = resourceObserver->next;
}
+ oc_mutex_unlock(g_serverObsListMutex);
+
if (numObs == 0)
{
OIC_LOG(INFO, TAG, "Resource has no observers");
OIC_LOG(INFO, TAG, "Entering SendListObserverNotification");
while(numIds)
{
- observer = GetObserverUsingId (*obsIdList);
+ oc_mutex_lock(g_serverObsListMutex);
+ observer = GetObserverUsingIdAsOwner (*obsIdList);
if (observer)
{
// Found observer - verify if it matches the resource handle
if (!ehResponse.payload)
{
FindAndDeleteServerRequest(request);
+ oc_mutex_unlock(g_serverObsListMutex);
continue;
}
memcpy(ehResponse.payload, payload, sizeof(*payload));
FindAndDeleteServerRequest(request);
}
}
+
// Since we are in a loop, set an error flag to indicate
// at least one error occurred.
if (result != OC_STACK_OK)
}
}
}
+
+ oc_mutex_unlock(g_serverObsListMutex);
obsIdList++;
numIds--;
}
OCStackResult GenerateObserverId (OCObservationId *observationId)
{
- ResourceObserver *resObs = NULL;
+ bool found = false;
OIC_LOG(INFO, TAG, "Entering GenerateObserverId");
VERIFY_NON_NULL (observationId);
*observationId = OCGetRandomByte();
} while (0 == *observationId); //Make sure *observationId is not 0
// Check if observation Id already exists
- resObs = GetObserverUsingId (*observationId);
- } while (NULL != resObs);
+ found = IsObserverAvailable (*observationId);
+ } while (found);
OIC_LOG_V(INFO, TAG, "GeneratedObservation ID is %u", *observationId);
obsNode->TTL = GetTicks(MAX_OBSERVER_TTL_SECONDS * MILLISECONDS_PER_SECOND);
}
+ oc_mutex_lock(g_serverObsListMutex);
LL_APPEND (g_serverObsList, obsNode);
+ oc_mutex_unlock(g_serverObsListMutex);
return OC_STACK_OK;
}
if (observeId)
{
+ oc_mutex_lock(g_serverObsListMutex);
+ LL_FOREACH (g_serverObsList, out)
+ {
+ if (out->observeId == observeId)
+ {
+ oc_mutex_unlock(g_serverObsListMutex);
+ return CloneObserverNode(out);
+ }
+ CheckTimedOutObserver(out);
+ }
+ oc_mutex_unlock(g_serverObsListMutex);
+ }
+ OIC_LOG(INFO, TAG, "Observer node not found!!");
+ return NULL;
+}
+
+static ResourceObserver* GetObserverUsingIdAsOwner (const OCObservationId observeId)
+{
+ ResourceObserver *out = NULL;
+
+ if (observeId)
+ {
LL_FOREACH (g_serverObsList, out)
{
if (out->observeId == observeId)
return NULL;
}
+bool IsObserverAvailable (const OCObservationId observeId)
+{
+ ResourceObserver *out = NULL;
+
+ if (observeId)
+ {
+ oc_mutex_lock(g_serverObsListMutex);
+ LL_FOREACH (g_serverObsList, out)
+ {
+ if (out->observeId == observeId)
+ {
+ oc_mutex_unlock(g_serverObsListMutex);
+ return true;
+ }
+ }
+ oc_mutex_unlock(g_serverObsListMutex);
+ }
+
+ return false;
+}
+
ResourceObserver* GetObserverUsingToken (const CAToken_t token, uint8_t tokenLength)
{
if (token)
OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
ResourceObserver *out = NULL;
+ oc_mutex_lock(g_serverObsListMutex);
+ LL_FOREACH (g_serverObsList, out)
+ {
+ /* de-annotate below line if want to see all token in cbList */
+ //OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)out->token, tokenLength);
+ if ((memcmp(out->token, token, tokenLength) == 0))
+ {
+ OIC_LOG(INFO, TAG, "Found in observer list");
+ oc_mutex_unlock(g_serverObsListMutex);
+ return CloneObserverNode(out);
+ }
+ CheckTimedOutObserver(out);
+ }
+ oc_mutex_unlock(g_serverObsListMutex);
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Passed in NULL token");
+ }
+
+ OIC_LOG(INFO, TAG, "Observer node not found!!");
+ return NULL;
+}
+
+static ResourceObserver* GetObserverUsingTokenAsOwner (const CAToken_t token, uint8_t tokenLength)
+{
+ if (token)
+ {
+ OIC_LOG(INFO, TAG, "Looking for token");
+ OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
+
+ ResourceObserver *out = NULL;
LL_FOREACH (g_serverObsList, out)
{
/* de-annotate below line if want to see all token in cbList */
return OC_STACK_INVALID_PARAM;
}
- ResourceObserver *obsNode = GetObserverUsingToken (token, tokenLength);
+ oc_mutex_lock(g_serverObsListMutex);
+ ResourceObserver *obsNode = GetObserverUsingTokenAsOwner (token, tokenLength);
if (obsNode)
{
OIC_LOG_V(INFO, TAG, "deleting observer id %u with token", obsNode->observeId);
OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)obsNode->token, tokenLength);
+
LL_DELETE (g_serverObsList, obsNode);
- OICFree(obsNode->resUri);
- OICFree(obsNode->query);
- OICFree(obsNode->token);
- OICFree(obsNode);
+ FreeObserver(obsNode);
}
+ oc_mutex_unlock(g_serverObsListMutex);
+
// it is ok if we did not find the observer...
return OC_STACK_OK;
}
return OC_STACK_INVALID_PARAM;
}
+ oc_mutex_lock(g_serverObsListMutex);
+ ResourceObserver* obsDupList = CloneObserverList(g_serverObsList);
+ oc_mutex_unlock(g_serverObsListMutex);
+
ResourceObserver *out = NULL;
ResourceObserver *tmp = NULL;
- LL_FOREACH_SAFE(g_serverObsList, out, tmp)
+ LL_FOREACH_SAFE(obsDupList, out, tmp)
{
if (out)
{
}
}
+ FreeObserverList(obsDupList);
return OC_STACK_OK;
}
void DeleteObserverList()
{
- ResourceObserver *out = NULL;
- ResourceObserver *tmp = NULL;
- LL_FOREACH_SAFE (g_serverObsList, out, tmp)
+ oc_mutex_lock(g_serverObsListMutex);
+
+ ResourceObserver* head = g_serverObsList;
+ ResourceObserver* del = NULL;
+ while (NULL != head)
{
- if (out)
- {
- DeleteObserverUsingToken ((out->token), out->tokenLength);
- }
+ del = head;
+ head = head->next;
+
+ OIC_LOG_V(INFO, TAG, "deleting observer id %u with token", del->observeId);
+ OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)del->token, del->tokenLength);
+
+ FreeObserver(del);
}
+
g_serverObsList = NULL;
+ oc_mutex_unlock(g_serverObsListMutex);
}
/*
return OC_STACK_OK;
}
+OCStackResult InitializeObseverList()
+{
+ OIC_LOG(DEBUG, TAG, "InitializeObseverList IN");
+
+ if (NULL == g_serverObsListMutex)
+ {
+ g_serverObsListMutex = oc_mutex_new();
+ }
+
+ OIC_LOG(DEBUG, TAG, "InitializeObseverList OUT");
+ return OC_STACK_OK;
+}
+
+void TerminateObserverList()
+{
+ OIC_LOG(DEBUG, TAG, "TerminateObserverList IN");
+
+ DeleteObserverList();
+
+ if (NULL != g_serverObsListMutex)
+ {
+ oc_mutex_free(g_serverObsListMutex);
+ g_serverObsListMutex = NULL;
+ }
+
+ OIC_LOG(DEBUG, TAG, "TerminateObserverList OUT");
+}
+
+void FreeObserver (ResourceObserver* obsNode)
+{
+ if (NULL != obsNode)
+ {
+ OICFree(obsNode->resUri);
+ OICFree(obsNode->query);
+ OICFree(obsNode->token);
+ OICFree(obsNode);
+ }
+}