1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
23 #include "ocstackconfig.h"
24 #include "ocstackinternal.h"
25 #include "ocobserve.h"
26 #include "ocresourcehandler.h"
28 #include "oic_malloc.h"
29 #include "oic_string.h"
30 #include "ocpayload.h"
31 #include "ocserverrequest.h"
35 #include <coap/utlist.h>
37 #include <coap/coap.h>
40 #define MOD_NAME "ocobserve"
42 #define TAG "OIC_RI_OBSERVE"
44 #define VERIFY_NON_NULL(arg) { if (!arg) {OIC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
46 #define MAX_OBSERVERS 3840
48 static struct ResourceObserver * g_serverObsList = NULL;
49 static oc_mutex g_serverObsListMutex = NULL;
51 static int observer_count = 0;
53 static ResourceObserver* GetObserverUsingIdAsOwner (const OCObservationId observeId);
55 static ResourceObserver* CloneObserverNode (ResourceObserver* observer)
57 ResourceObserver* dupObsNode = NULL;
60 dupObsNode = (ResourceObserver *) OICCalloc(1, sizeof(ResourceObserver));
61 VERIFY_NON_NULL(dupObsNode);
62 memcpy(dupObsNode, observer, sizeof(ResourceObserver));
66 dupObsNode->resUri = OICStrdup(observer->resUri);
67 VERIFY_NON_NULL(dupObsNode->resUri);
72 dupObsNode->query = OICStrdup(observer->query);
73 VERIFY_NON_NULL(dupObsNode->query);
78 dupObsNode->token = (CAToken_t)OICMalloc(observer->tokenLength);
79 VERIFY_NON_NULL(dupObsNode->token);
80 memcpy(dupObsNode->token, observer->token, observer->tokenLength);
83 dupObsNode->next = NULL;
89 FreeObserver(dupObsNode);
93 static void FreeObserverList (ResourceObserver* list)
95 ResourceObserver* head = list;
96 ResourceObserver* del = NULL;
102 OICFree(del->resUri);
109 static ResourceObserver* CloneObserverList (ResourceObserver* obsList)
111 ResourceObserver* dupList = NULL;
112 ResourceObserver* out = NULL;
114 LL_FOREACH(obsList, out)
116 ResourceObserver *obsNode = CloneObserverNode(out);
119 FreeObserverList(dupList);
124 LL_APPEND(dupList, obsNode);
131 * Determine observe QOS based on the QOS of the request.
132 * The qos passed as a parameter overrides what the client requested.
133 * If we want the client preference taking high priority make:
134 * qos = resourceObserver->qos;
136 * @param method RESTful method.
137 * @param resourceObserver Observer.
138 * @param appQoS Quality of service.
139 * @return The quality of service of the observer.
141 static OCQualityOfService DetermineObserverQoS(OCMethod method,
142 ResourceObserver * resourceObserver, OCQualityOfService appQoS)
144 if (!resourceObserver)
146 OIC_LOG(ERROR, TAG, "DetermineObserverQoS called with invalid resourceObserver");
150 OCQualityOfService decidedQoS = appQoS;
151 if (appQoS == OC_NA_QOS)
153 decidedQoS = resourceObserver->qos;
156 if (appQoS != OC_HIGH_QOS)
158 OIC_LOG_V(INFO, TAG, "Current NON count for this observer is %d",
159 resourceObserver->lowQosCount);
161 if ((resourceObserver->forceHighQos \
162 || resourceObserver->lowQosCount >= MAX_OBSERVER_NON_COUNT) \
163 && method != OC_REST_PRESENCE)
165 if (resourceObserver->forceHighQos \
166 || resourceObserver->lowQosCount >= MAX_OBSERVER_NON_COUNT)
169 resourceObserver->lowQosCount = 0;
170 // at some point we have to to send CON to check on the
171 // availability of observer
172 OIC_LOG(INFO, TAG, "This time we are sending the notification as High qos");
173 decidedQoS = OC_HIGH_QOS;
177 (resourceObserver->lowQosCount)++;
184 * Create a get request and pass to entityhandler to notify specific observer.
186 * @param observer Observer that need to be notified.
187 * @param qos Quality of service of resource.
189 * @return ::OC_STACK_OK on success, some other value upon failure.
191 static OCStackResult SendObserveNotification(ResourceObserver *observer,
192 OCQualityOfService qos)
194 OCStackResult result = OC_STACK_ERROR;
195 OCServerRequest * request = NULL;
196 OCEntityHandlerRequest ehRequest = {0};
197 OCEntityHandlerResult ehResult = OC_EH_ERROR;
199 result = AddServerRequest(&request, 0, 0, 1, OC_REST_GET,
200 0, observer->resource->sequenceNum, qos,
201 observer->query, NULL, NULL,
202 observer->token, observer->tokenLength,
203 observer->resUri, 0, observer->acceptFormat,
208 request->observeResult = OC_STACK_OK;
209 if (result == OC_STACK_OK)
211 result = FormOCEntityHandlerRequest(
213 (OCRequestHandle) request->requestId,
216 (OCResourceHandle) observer->resource,
218 PAYLOAD_TYPE_REPRESENTATION,
220 request->payloadSize,
221 request->numRcvdVendorSpecificHeaderOptions,
222 request->rcvdVendorSpecificHeaderOptions,
223 OC_OBSERVE_NO_OPTION,
226 if (result == OC_STACK_OK)
228 ehResult = observer->resource->entityHandler(OC_REQUEST_FLAG, &ehRequest,
229 observer->resource->entityHandlerCallbackParam);
231 // Clear server request on error case
232 if (!OCResultToSuccess(EntityHandlerCodeToOCStackCode(ehResult)))
234 FindAndDeleteServerRequest(request);
236 // Reset Observer TTL.
237 observer->TTL = GetTicks(MAX_OBSERVER_TTL_SECONDS * MILLISECONDS_PER_SECOND);
239 OCPayloadDestroy(ehRequest.payload);
247 OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge,
248 OCPresenceTrigger trigger, OCResourceType *resourceType, OCQualityOfService qos)
250 OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr, uint32_t maxAge,
251 OCQualityOfService qos)
254 OIC_LOG(INFO, TAG, "Entering SendObserverNotification");
257 return OC_STACK_INVALID_PARAM;
260 OCStackResult result = OC_STACK_ERROR;
261 ResourceObserver * resourceObserver = NULL;
263 OCServerRequest * request = NULL;
264 bool observeErrorFlag = false;
266 // Find clients that are observing this resource
267 oc_mutex_lock(g_serverObsListMutex);
268 resourceObserver = g_serverObsList;
269 while (resourceObserver)
271 if (resourceObserver->resource == resPtr)
275 if (method != OC_REST_PRESENCE)
278 qos = DetermineObserverQoS(method, resourceObserver, qos);
279 result = SendObserveNotification(resourceObserver, qos);
284 OCEntityHandlerResponse ehResponse = {0};
286 //This is effectively the implementation for the presence entity handler.
287 OIC_LOG(DEBUG, TAG, "This notification is for Presence");
288 result = AddServerRequest(&request, 0, 0, 1, OC_REST_GET,
289 0, resPtr->sequenceNum, qos, resourceObserver->query,
291 resourceObserver->token, resourceObserver->tokenLength,
292 resourceObserver->resUri, 0, resourceObserver->acceptFormat,
293 &resourceObserver->devAddr);
295 if (result == OC_STACK_OK)
297 OCPresencePayload* presenceResBuf = OCPresencePayloadCreate(
298 resPtr->sequenceNum, maxAge, trigger,
299 resourceType ? resourceType->resourcetypename : NULL);
303 oc_mutex_unlock(g_serverObsListMutex);
304 return OC_STACK_NO_MEMORY;
307 if (result == OC_STACK_OK)
309 ehResponse.ehResult = OC_EH_OK;
310 ehResponse.payload = (OCPayload*)presenceResBuf;
311 ehResponse.persistentBufferFlag = 0;
312 ehResponse.requestHandle = (OCRequestHandle) request->requestId;
313 ehResponse.resourceHandle = (OCResourceHandle) resPtr;
314 OICStrcpy(ehResponse.resourceUri, sizeof(ehResponse.resourceUri),
315 resourceObserver->resUri);
316 result = OCDoResponse(&ehResponse);
317 if (result != OC_STACK_OK)
319 OIC_LOG(ERROR, TAG, "Failed to send presence notification!");
320 FindAndDeleteServerRequest(request);
324 OCPresencePayloadDestroy(presenceResBuf);
329 // Since we are in a loop, set an error flag to indicate at least one error occurred.
330 if (result != OC_STACK_OK)
332 observeErrorFlag = true;
335 resourceObserver = resourceObserver->next;
338 oc_mutex_unlock(g_serverObsListMutex);
342 OIC_LOG(INFO, TAG, "Resource has no observers");
343 result = OC_STACK_NO_OBSERVERS;
345 else if (observeErrorFlag)
347 OIC_LOG(ERROR, TAG, "Observer notification error");
348 result = OC_STACK_ERROR;
353 OCStackResult SendListObserverNotification (OCResource * resource,
354 OCObservationId *obsIdList, uint16_t numberOfIds,
355 const OCRepPayload *payload,
357 OCQualityOfService qos)
360 if (!resource || !obsIdList || !payload)
362 return OC_STACK_INVALID_PARAM;
365 uint16_t numIds = numberOfIds;
366 ResourceObserver *observer = NULL;
367 uint16_t numSentNotification = 0;
368 OCServerRequest * request = NULL;
369 OCStackResult result = OC_STACK_ERROR;
370 bool observeErrorFlag = false;
372 OIC_LOG(INFO, TAG, "Entering SendListObserverNotification");
375 oc_mutex_lock(g_serverObsListMutex);
376 observer = GetObserverUsingIdAsOwner (*obsIdList);
379 // Found observer - verify if it matches the resource handle
380 if (observer->resource == resource)
382 qos = DetermineObserverQoS(OC_REST_GET, observer, qos);
385 result = AddServerRequest(&request, 0, 0, 1, OC_REST_GET,
386 0, resource->sequenceNum, qos, observer->query,
387 NULL, NULL, observer->token, observer->tokenLength,
388 observer->resUri, 0, observer->acceptFormat,
393 request->observeResult = OC_STACK_OK;
394 if (result == OC_STACK_OK)
396 OCEntityHandlerResponse ehResponse = {0};
397 ehResponse.ehResult = OC_EH_OK;
398 ehResponse.payload = (OCPayload*)OCRepPayloadCreate();
399 if (!ehResponse.payload)
401 FindAndDeleteServerRequest(request);
402 oc_mutex_unlock(g_serverObsListMutex);
405 memcpy(ehResponse.payload, payload, sizeof(*payload));
406 ehResponse.persistentBufferFlag = 0;
407 ehResponse.requestHandle = (OCRequestHandle) request->requestId;
408 ehResponse.resourceHandle = (OCResourceHandle) resource;
409 result = OCDoResponse(&ehResponse);
410 if (result == OC_STACK_OK)
412 OIC_LOG_V(INFO, TAG, "Observer id %d notified.", *obsIdList);
414 // Increment only if OCDoResponse is successful
415 numSentNotification++;
419 OIC_LOG_V(INFO, TAG, "Error notifying observer id %d.", *obsIdList);
420 FindAndDeleteServerRequest(request);
423 // Reset Observer TTL.
425 GetTicks(MAX_OBSERVER_TTL_SECONDS * MILLISECONDS_PER_SECOND);
427 OICFree(ehResponse.payload);
431 FindAndDeleteServerRequest(request);
435 // Since we are in a loop, set an error flag to indicate
436 // at least one error occurred.
437 if (result != OC_STACK_OK)
439 observeErrorFlag = true;
444 oc_mutex_unlock(g_serverObsListMutex);
449 if (numSentNotification == numberOfIds && !observeErrorFlag)
453 else if (numSentNotification == 0)
455 return OC_STACK_NO_OBSERVERS;
459 OIC_LOG(ERROR, TAG, "Observer notification error");
460 return OC_STACK_ERROR;
464 OCStackResult GenerateObserverId (OCObservationId *observationId)
468 OIC_LOG(INFO, TAG, "Entering GenerateObserverId");
469 VERIFY_NON_NULL (observationId);
471 oc_mutex_lock(g_serverObsListMutex);
473 if (observer_count < MAX_OBSERVERS)
475 oc_mutex_unlock(g_serverObsListMutex);
480 *observationId = OCGetRandomTwoByte();
481 } while (0 == *observationId); //Make sure *observationId is not 0
482 // Check if observation Id already exists
483 found = IsObserverAvailable (*observationId);
485 OIC_LOG_V(INFO, TAG, "GeneratedObservation ID is %u", *observationId);
486 //oc_mutex_unlock(g_serverObsListMutex);
492 OIC_LOG_V(ERROR, TAG, "No more observers can be added");
493 oc_mutex_unlock(g_serverObsListMutex);
495 return OC_STACK_ERROR;
498 return OC_STACK_ERROR;
501 OCStackResult AddObserver (const char *resUri,
503 OCObservationId obsId,
506 OCResource *resHandle,
507 OCQualityOfService qos,
508 OCPayloadFormat acceptFormat,
509 const OCDevAddr *devAddr)
511 // Check if resource exists and is observable.
514 return OC_STACK_INVALID_PARAM;
516 if (!(resHandle->resourceProperties & OC_OBSERVABLE))
518 return OC_STACK_RESOURCE_ERROR;
521 if (!resUri || !token)
523 return OC_STACK_INVALID_PARAM;
526 ResourceObserver *obsNode = (ResourceObserver *) OICCalloc(1, sizeof(ResourceObserver));
529 obsNode->observeId = obsId;
531 obsNode->resUri = OICStrdup(resUri);
532 VERIFY_NON_NULL (obsNode->resUri);
535 obsNode->acceptFormat = acceptFormat;
538 obsNode->query = OICStrdup(query);
539 VERIFY_NON_NULL (obsNode->query);
541 // If tokenLength is zero, the return value depends on the
542 // particular library implementation (it may or may not be a null pointer).
545 obsNode->token = (CAToken_t)OICMalloc(tokenLength);
546 VERIFY_NON_NULL (obsNode->token);
547 memcpy(obsNode->token, token, tokenLength);
549 obsNode->tokenLength = tokenLength;
551 obsNode->devAddr = *devAddr;
552 obsNode->resource = resHandle;
555 if ((strcmp(resUri, OC_RSRVD_PRESENCE_URI) == 0))
562 obsNode->TTL = GetTicks(MAX_OBSERVER_TTL_SECONDS * MILLISECONDS_PER_SECOND);
565 oc_mutex_lock(g_serverObsListMutex);
566 LL_APPEND (g_serverObsList, obsNode);
568 oc_mutex_unlock(g_serverObsListMutex);
576 OICFree(obsNode->resUri);
577 OICFree(obsNode->query);
580 return OC_STACK_NO_MEMORY;
584 * This function checks if the node is past its time to live and
585 * deletes it if timed-out. Calling this function with a presence callback
586 * with ttl set to 0 will not delete anything as presence nodes have
587 * their own mechanisms for timeouts. A null argument will cause the function to
590 static void CheckTimedOutObserver(ResourceObserver* observer)
592 if (!observer || observer->TTL == 0)
600 if (observer->TTL < now)
602 // Send confirmable notification message to observer.
603 OIC_LOG(INFO, TAG, "Sending High-QoS notification to observer");
604 SendObserveNotification(observer, OC_HIGH_QOS);
608 ResourceObserver* GetObserverUsingId (const OCObservationId observeId)
610 ResourceObserver *out = NULL;
614 oc_mutex_lock(g_serverObsListMutex);
615 LL_FOREACH (g_serverObsList, out)
617 if (out->observeId == observeId)
619 OIC_LOG(INFO, TAG, "Found in observer list");
620 ResourceObserver *observer = CloneObserverNode(out);
621 oc_mutex_unlock(g_serverObsListMutex);
624 CheckTimedOutObserver(out);
626 oc_mutex_unlock(g_serverObsListMutex);
628 OIC_LOG(INFO, TAG, "Observer node not found!!");
632 static ResourceObserver* GetObserverUsingIdAsOwner (const OCObservationId observeId)
634 ResourceObserver *out = NULL;
638 LL_FOREACH (g_serverObsList, out)
640 if (out->observeId == observeId)
644 CheckTimedOutObserver(out);
647 OIC_LOG(INFO, TAG, "Observer node not found!!");
651 bool IsObserverAvailable (const OCObservationId observeId)
653 ResourceObserver *out = NULL;
657 oc_mutex_lock(g_serverObsListMutex);
658 LL_FOREACH (g_serverObsList, out)
660 if (out->observeId == observeId)
662 oc_mutex_unlock(g_serverObsListMutex);
666 oc_mutex_unlock(g_serverObsListMutex);
672 ResourceObserver* GetObserverUsingToken (const CAToken_t token, uint8_t tokenLength)
676 OIC_LOG(INFO, TAG, "Looking for token");
677 OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
679 ResourceObserver *out = NULL;
680 oc_mutex_lock(g_serverObsListMutex);
681 LL_FOREACH (g_serverObsList, out)
683 /* de-annotate below line if want to see all token in cbList */
684 //OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)out->token, tokenLength);
685 if ((memcmp(out->token, token, tokenLength) == 0))
687 OIC_LOG(INFO, TAG, "Found in observer list");
688 ResourceObserver *observer = CloneObserverNode(out);
689 oc_mutex_unlock(g_serverObsListMutex);
692 CheckTimedOutObserver(out);
694 oc_mutex_unlock(g_serverObsListMutex);
698 OIC_LOG(ERROR, TAG, "Passed in NULL token");
701 OIC_LOG(INFO, TAG, "Observer node not found!!");
705 static ResourceObserver* GetObserverUsingTokenAsOwner (const CAToken_t token, uint8_t tokenLength)
709 OIC_LOG(INFO, TAG, "Looking for token");
710 OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)token, tokenLength);
712 ResourceObserver *out = NULL;
713 LL_FOREACH (g_serverObsList, out)
715 /* de-annotate below line if want to see all token in cbList */
716 //OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)out->token, tokenLength);
717 if ((memcmp(out->token, token, tokenLength) == 0))
719 OIC_LOG(INFO, TAG, "Found in observer list");
722 CheckTimedOutObserver(out);
727 OIC_LOG(ERROR, TAG, "Passed in NULL token");
730 OIC_LOG(INFO, TAG, "Observer node not found!!");
734 OCStackResult DeleteObserverUsingToken (CAToken_t token, uint8_t tokenLength)
738 return OC_STACK_INVALID_PARAM;
741 oc_mutex_lock(g_serverObsListMutex);
742 ResourceObserver *obsNode = GetObserverUsingTokenAsOwner (token, tokenLength);
745 OIC_LOG_V(INFO, TAG, "deleting observer id %u with token", obsNode->observeId);
746 OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)obsNode->token, tokenLength);
748 LL_DELETE (g_serverObsList, obsNode);
750 FreeObserver(obsNode);
752 oc_mutex_unlock(g_serverObsListMutex);
754 // it is ok if we did not find the observer...
758 OCStackResult DeleteObserverUsingDevAddr(const OCDevAddr *devAddr)
762 return OC_STACK_INVALID_PARAM;
765 oc_mutex_lock(g_serverObsListMutex);
766 ResourceObserver* obsDupList = CloneObserverList(g_serverObsList);
767 oc_mutex_unlock(g_serverObsListMutex);
769 ResourceObserver *out = NULL;
770 ResourceObserver *tmp = NULL;
771 LL_FOREACH_SAFE(obsDupList, out, tmp)
775 if ((strcmp(out->devAddr.addr, devAddr->addr) == 0)
776 && out->devAddr.port == devAddr->port)
778 OIC_LOG_V(INFO, TAG, "deleting observer id %u with %s:%u",
779 out->observeId, out->devAddr.addr, out->devAddr.port);
780 OCStackFeedBack(out->token, out->tokenLength, OC_OBSERVER_NOT_INTERESTED);
785 FreeObserverList(obsDupList);
789 OCStackResult DeleteObserverUsingResource(OCResource *res)
793 return OC_STACK_INVALID_PARAM;
796 oc_mutex_lock(g_serverObsListMutex);
797 ResourceObserver *obs = NULL;
798 ResourceObserver *next = NULL;
799 LL_FOREACH_SAFE(g_serverObsList, obs, next)
801 if (obs->resource == res)
803 OIC_LOG_V(INFO, TAG, "Deleting observer: id-%u, token-", obs->observeId);
804 OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)obs->token, obs->tokenLength);
805 LL_DELETE(g_serverObsList, obs);
809 oc_mutex_unlock(g_serverObsListMutex);
813 void DeleteObserverList()
815 oc_mutex_lock(g_serverObsListMutex);
817 ResourceObserver* head = g_serverObsList;
818 ResourceObserver* del = NULL;
824 OIC_LOG_V(INFO, TAG, "deleting observer id %u with token", del->observeId);
825 OIC_LOG_BUFFER(INFO, TAG, (const uint8_t *)del->token, del->tokenLength);
830 g_serverObsList = NULL;
831 oc_mutex_unlock(g_serverObsListMutex);
835 * CA layer expects observe registration/de-reg/notiifcations to be passed as a header
836 * option, which breaks the protocol abstraction requirement between RI & CA, and
837 * has to be fixed in the future. The function below adds the header option for observe.
838 * It should be noted that the observe header option is assumed to be the first option
839 * in the list of user defined header options and hence it is inserted at the front
840 * of the header options list and number of options adjusted accordingly.
843 CreateObserveHeaderOption (CAHeaderOption_t **caHdrOpt,
844 OCHeaderOption *ocHdrOpt,
850 return OC_STACK_INVALID_PARAM;
853 if (numOptions > 0 && !ocHdrOpt)
855 OIC_LOG (INFO, TAG, "options are NULL though number is non zero");
856 return OC_STACK_INVALID_PARAM;
859 CAHeaderOption_t *tmpHdrOpt = NULL;
861 tmpHdrOpt = (CAHeaderOption_t *) OICCalloc ((numOptions+1), sizeof(CAHeaderOption_t));
862 if (NULL == tmpHdrOpt)
864 return OC_STACK_NO_MEMORY;
866 tmpHdrOpt[0].protocolID = CA_COAP_ID;
867 tmpHdrOpt[0].optionID = COAP_OPTION_OBSERVE;
868 tmpHdrOpt[0].optionLength = sizeof(uint8_t);
869 tmpHdrOpt[0].optionData[0] = observeFlag;
870 for (uint8_t i = 0; i < numOptions; i++)
872 memcpy (&(tmpHdrOpt[i+1]), &(ocHdrOpt[i]), sizeof(CAHeaderOption_t));
875 *caHdrOpt = tmpHdrOpt;
880 * CA layer passes observe information to the RI layer as a header option, which
881 * breaks the protocol abstraction requirement between RI & CA, and has to be fixed
882 * in the future. The function below removes the observe header option and processes it.
883 * It should be noted that the observe header option is always assumed to be the first
884 * option in the list of user defined header options and hence it is deleted from the
885 * front of the header options list and the number of options is adjusted accordingly.
888 GetObserveHeaderOption (uint32_t * observationOption,
889 CAHeaderOption_t *options,
890 uint8_t * numOptions)
892 if (!observationOption)
894 return OC_STACK_INVALID_PARAM;
897 if (!options || !numOptions)
899 OIC_LOG (INFO, TAG, "No options present");
903 for(uint8_t i = 0; i < *numOptions; i++)
905 if (options[i].protocolID == CA_COAP_ID &&
906 options[i].optionID == COAP_OPTION_OBSERVE)
908 *observationOption = options[i].optionData[0];
909 for(uint8_t c = i; c < *numOptions-1; c++)
911 options[i] = options[i+1];
920 OCStackResult InitializeObserverList()
922 OIC_LOG(DEBUG, TAG, "InitializeObserverList IN");
924 if (NULL == g_serverObsListMutex)
926 g_serverObsListMutex = oc_mutex_new();
929 OIC_LOG(DEBUG, TAG, "InitializeObserverList OUT");
933 void TerminateObserverList()
935 OIC_LOG(DEBUG, TAG, "TerminateObserverList IN");
937 if (NULL != g_serverObsListMutex)
939 oc_mutex_free(g_serverObsListMutex);
940 g_serverObsListMutex = NULL;
943 OIC_LOG(DEBUG, TAG, "TerminateObserverList OUT");
946 void FreeObserver (ResourceObserver* obsNode)
950 OICFree(obsNode->resUri);
951 OICFree(obsNode->query);
952 OICFree(obsNode->token);