Fix Presence notification issues.
authorSashi Penta <sashi.kumar.penta@intel.com>
Tue, 24 Feb 2015 06:09:08 +0000 (22:09 -0800)
committerPatrick Lankswert <patrick.lankswert@intel.com>
Thu, 5 Mar 2015 20:45:50 +0000 (20:45 +0000)
* Handle duplicate stop notification on the client side.
* Once StopPresence is called on the server, no more notifications are sent. Fixes IOT-66.
* Correct implementation for sending the presence notification when unbinding.

Change-Id: I112a1ef2cb5c04d847c0c83f5309d67acdc4c1fb
Signed-off-by: Sashi Penta <sashi.kumar.penta@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/402
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Patrick Lankswert <patrick.lankswert@intel.com>
resource/csdk/stack/include/internal/ocstackinternal.h
resource/csdk/stack/src/ocstack.c

index e02ee39..7f5d366 100644 (file)
@@ -173,6 +173,7 @@ OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest);
 OCStackResult HandleStackResponses(OCResponse * response);
 #ifdef WITH_PRESENCE
 OCStackResult SendPresenceNotification(OCResourceType *resourceType);
+OCStackResult SendStopNotification();
 #endif // WITH_PRESENCE
 int ParseIPv4Address(unsigned char * ipAddrStr, uint8_t * ipAddr, uint16_t * port);
 
index 2bd3591..e505e2b 100644 (file)
@@ -395,6 +395,7 @@ void parsePresencePayload(char* payload, uint32_t* seqNum, uint32_t* maxAge, cha
     tok = strtok_r(NULL, "[:]}", &savePtr);
     payload[strlen((char *)payload)] = ':';
     *seqNum = (uint32_t) atoi(tok);
+
     tok = strtok_r(NULL, "[:]}", &savePtr);
     *maxAge = (uint32_t) atoi(tok);
     tok = strtok_r(NULL, "[:]}",&savePtr);
@@ -502,62 +503,79 @@ OCStackResult HandlePresenceResponse(const CARemoteEndpoint_t* endPoint,
                                 &resourceTypeName);
     }
 
-    if(maxAge == 0)
+    if(presenceSubscribe)
     {
-        OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
-        response.result = OC_STACK_PRESENCE_STOPPED;
-        if(cbNode->presence)
+        if(cbNode->sequenceNumber == response.sequenceNumber)
         {
-            OCFree(cbNode->presence->timeOut);
-            OCFree(cbNode->presence);
-            cbNode->presence = NULL;
+            OC_LOG(INFO, TAG, PCF("===============No presence change"));
+            goto exit;
         }
-    }
-    else if(presenceSubscribe)
-    {
-        if(!cbNode->presence)
+
+        if(maxAge == 0)
         {
-            cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
-            VERIFY_NON_NULL_V(cbNode->presence);
-            cbNode->presence->timeOut = NULL;
-            cbNode->presence->timeOut = (uint32_t *)
-                    OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
-            if(!(cbNode->presence->timeOut)){
+            OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
+            response.result = OC_STACK_PRESENCE_STOPPED;
+            if(cbNode->presence)
+            {
+                OCFree(cbNode->presence->timeOut);
                 OCFree(cbNode->presence);
-                result = OC_STACK_NO_MEMORY;
+                cbNode->presence = NULL;
             }
         }
-
-        OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %u", GetTime(0));
-        cbNode->presence->TTL = maxAge;
-        for(int index = 0; index < PresenceTimeOutSize; index++)
-        {
-            lowerBound = GetTime(((float)(PresenceTimeOut[index])
-                    /(float)100)*(float)cbNode->presence->TTL);
-            higherBound = GetTime(((float)(PresenceTimeOut[index + 1])
-                    /(float)100)*(float)cbNode->presence->TTL);
-            cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
-            OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout  %d", lowerBound);
-            OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
-            OC_LOG_V(DEBUG, TAG, "----------------timeOut entry  %d",
-                    cbNode->presence->timeOut[index]);
-        }
-        cbNode->presence->TTLlevel = 0;
-        OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
-        if(cbNode->sequenceNumber == response.sequenceNumber)
+        else
         {
-            OC_LOG(INFO, TAG, PCF("===============No presence change"));
-            goto exit;
-        }
-        OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
-        cbNode->sequenceNumber = response.sequenceNumber;
+            if(!cbNode->presence)
+            {
+                cbNode->presence = (OCPresence *) OCMalloc(sizeof(OCPresence));
 
-        // Ensure that a filter is actually applied.
-        if(resourceTypeName && cbNode->filterResourceType)
-        {
-            if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
+                if(!(cbNode->presence))
+                {
+                    OC_LOG(ERROR, TAG, PCF("Could not allocate memory for cbNode->presence"));
+                    result = OC_STACK_NO_MEMORY;
+                    goto exit;
+                }
+
+                VERIFY_NON_NULL_V(cbNode->presence);
+                cbNode->presence->timeOut = NULL;
+                cbNode->presence->timeOut = (uint32_t *)
+                        OCMalloc(PresenceTimeOutSize * sizeof(uint32_t));
+                if(!(cbNode->presence->timeOut)){
+                    OC_LOG(ERROR, TAG,
+                                  PCF("Could not allocate memory for cbNode->presence->timeOut"));
+                    OCFree(cbNode->presence);
+                    result = OC_STACK_NO_MEMORY;
+                    goto exit;
+                }
+            }
+
+            OC_LOG_V(INFO, TAG, "===============Update presence TTL, now time is %u", GetTime(0));
+            cbNode->presence->TTL = maxAge;
+            for(int index = 0; index < PresenceTimeOutSize; index++)
             {
-                goto exit;
+                lowerBound = GetTime(((float)(PresenceTimeOut[index])
+                        /(float)100)*(float)cbNode->presence->TTL);
+                higherBound = GetTime(((float)(PresenceTimeOut[index + 1])
+                        /(float)100)*(float)cbNode->presence->TTL);
+                cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
+                OC_LOG_V(DEBUG, TAG, "----------------lowerBound timeout  %d", lowerBound);
+                OC_LOG_V(DEBUG, TAG, "----------------higherBound timeout %d", higherBound);
+                OC_LOG_V(DEBUG, TAG, "----------------timeOut entry  %d",
+                        cbNode->presence->timeOut[index]);
+            }
+            cbNode->presence->TTLlevel = 0;
+            OC_LOG_V(DEBUG, TAG, "----------------this TTL level %d", cbNode->presence->TTLlevel);
+
+
+            OC_LOG(INFO, TAG, PCF("===============Presence changed, calling up the stack"));
+            cbNode->sequenceNumber = response.sequenceNumber;
+
+            // Ensure that a filter is actually applied.
+            if(resourceTypeName && cbNode->filterResourceType)
+            {
+                if(!findResourceType(cbNode->filterResourceType, resourceTypeName))
+                {
+                    goto exit;
+                }
             }
         }
     }
@@ -576,6 +594,12 @@ OCStackResult HandlePresenceResponse(const CARemoteEndpoint_t* endPoint,
                 goto exit;
             }
             mcNode->nonce = response.sequenceNumber;
+
+            if(maxAge == 0)
+            {
+                OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
+                response.result = OC_STACK_PRESENCE_STOPPED;
+            }
         }
         else
         {
@@ -598,6 +622,7 @@ OCStackResult HandlePresenceResponse(const CARemoteEndpoint_t* endPoint,
                 OC_LOG(INFO, TAG,
                     PCF("===============No Memory for Multicast Presence Node"));
                 result = OC_STACK_NO_MEMORY;
+                OCFree(uri);
                 goto exit;
             }
         }
@@ -2143,13 +2168,25 @@ OCStackResult OCStartPresence(const uint32_t ttl)
 OCStackResult OCStopPresence()
 {
     OCStackResult result = OC_STACK_ERROR;
-    //make resource inactive
+
+    if(presenceResource.handle)
+    {
+        ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
+    }
+
+    // make resource inactive
     result = OCChangeResourceProperty(
             &(((OCResource *) presenceResource.handle)->resourceProperties),
             OC_ACTIVE, 0);
-    result = SendPresenceNotification(NULL);
 
-    return result;
+    if(result != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG,
+                      PCF("Changing the presence resource properties to ACTIVE not successful"));
+        return result;
+    }
+
+    return SendStopNotification();
 }
 #endif
 
@@ -2458,20 +2495,22 @@ OCStackResult OCUnBindResource(
         if (resourceHandle == resource->rsrcResources[i]) {
             resource->rsrcResources[i] = (OCResource *) NULL;
             OC_LOG(INFO, TAG, PCF("resource unbound"));
+
+            // Send notification when resource is unbounded successfully.
+            #ifdef WITH_PRESENCE
+            if(presenceResource.handle)
+            {
+                ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
+                SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
+            }
+            #endif
+
             return OC_STACK_OK;
         }
     }
 
     OC_LOG(INFO, TAG, PCF("resource not found in collection"));
 
-    #ifdef WITH_PRESENCE
-    if(presenceResource.handle)
-    {
-        ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
-        SendPresenceNotification(((OCResource *) resourceHandle)->rsrcType);
-    }
-    #endif
-
     // Unable to add resourceHandle, so return error
     return OC_STACK_ERROR;
 }
@@ -2978,12 +3017,17 @@ void incrementSequenceNumber(OCResource * resPtr)
  *                       that was modified.
  * @param qos          - Quality Of Service
  *
+ * @return
+ *     OC_STACK_OK    - no errors
+ *     OC_STACK_ERROR - stack process error
  */
 #ifdef WITH_PRESENCE
+
+
 OCStackResult SendPresenceNotification(OCResourceType *resourceType)
 {
     OCResource *resPtr = NULL;
-    OCStackResult result;
+    OCStackResult result = OC_STACK_ERROR;
     OCMethod method = OC_REST_PRESENCE;
     uint32_t maxAge = 0;
     resPtr = findResource((OCResource *) presenceResource.handle);
@@ -2991,19 +3035,43 @@ OCStackResult SendPresenceNotification(OCResourceType *resourceType)
     {
         return OC_STACK_NO_RESOURCE;
     }
+
     if((((OCResource *) presenceResource.handle)->resourceProperties) & OC_ACTIVE)
     {
         maxAge = presenceResource.presenceTTL;
+
+        result = SendAllObserverNotification(method, resPtr, maxAge, resourceType, OC_LOW_QOS);
     }
-    else
+
+    return result;
+}
+
+/**
+ * Send Stop Notification to Presence subscribers
+ *
+ * @return
+ *     OC_STACK_OK    - no errors
+ *     OC_STACK_ERROR - stack process error
+ *
+ */
+
+OCStackResult SendStopNotification()
+{
+    OCResource *resPtr = NULL;
+    OCStackResult result = OC_STACK_ERROR;
+    OCMethod method = OC_REST_PRESENCE;
+    resPtr = findResource((OCResource *) presenceResource.handle);
+    if(NULL == resPtr)
     {
-        maxAge = 0;
+        return OC_STACK_NO_RESOURCE;
     }
 
-    result = SendAllObserverNotification(method, resPtr, maxAge, resourceType, OC_LOW_QOS);
+    // maxAge is 0. ResourceType is NULL.
+    result = SendAllObserverNotification(method, resPtr, 0, NULL, OC_LOW_QOS);
 
     return result;
 }
+
 #endif // WITH_PRESENCE
 /**
  * Notify observers that an observed value has changed.