Add a maximum presence TTL of 24 hours
authorDoug Hudson <douglas.hudson@intel.com>
Thu, 23 Apr 2015 20:22:00 +0000 (16:22 -0400)
committerErich Keane <erich.keane@intel.com>
Fri, 24 Apr 2015 16:29:07 +0000 (16:29 +0000)
- Set TTL to max TTL if TTL exceeds max TTL.
- Rename static function to make name reflect what the function
  actually does.
- Change function signature so that float casts can be removed.
- Add guards against overflowing a uint32_t argument.

Change-Id: Ie391f96fa153b48771187ea6b3d5cf718f52cb52
Signed-off-by: Doug Hudson <douglas.hudson@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/819
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Joseph Morrow <joseph.l.morrow@intel.com>
Reviewed-by: Erich Keane <erich.keane@intel.com>
resource/csdk/stack/include/ocstack.h
resource/csdk/stack/src/ocstack.c
resource/include/OCPlatform.h

index fcea43d..0ceded3 100644 (file)
@@ -46,7 +46,8 @@ extern "C" {
 #define OC_MULTICAST_PORT                    5683
 
 #ifdef WITH_PRESENCE
-#define OC_DEFAULT_PRESENCE_TTL (60)
+#define OC_DEFAULT_PRESENCE_TTL_SECONDS (60)
+#define OC_MAX_PRESENCE_TTL_SECONDS     (60 * 60 * 24) // 60 sec/min * 60 min/hr * 24 hr/day
 #define OC_PRESENCE_URI                      "/oc/presence"
 #endif
 
@@ -525,6 +526,9 @@ OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption
  * @param ttl Time To Live in seconds.
  * Note: If ttl is '0', then the default stack value will be used (60 Seconds).
  *
+ *       If ttl is greater than OC_MAX_PRESENCE_TTL_SECONDS, then the ttl will be set to
+ *       OC_MAX_PRESENCE_TTL_SECONDS.
+ *
  * @return ::OC_STACK_OK on success, some other value upon failure.
  */
 OCStackResult OCStartPresence(const uint32_t ttl);
index f8b1787..09432d9 100644 (file)
 #include <arpa/inet.h>
 #endif
 
+#ifndef UINT32_MAX
+#define UINT32_MAX   (0xFFFFFFFFUL)
+#endif
+
 //-----------------------------------------------------------------------------
 // Typedefs
 //-----------------------------------------------------------------------------
@@ -103,6 +107,7 @@ OCDeviceEntityHandler defaultDeviceHandler;
 //TODO: we should allow the server to define this
 #define MAX_OBSERVE_AGE (0x2FFFFUL)
 
+#define MILLISECONDS_PER_SECOND   (1000)
 /**
  * Parse the presence payload and extract various parameters.
  * Note: Caller should invoke OCFree after done with resType pointer.
@@ -294,13 +299,13 @@ static OCStackResult getResourceType(const char * query, char** resourceType);
 static CAResult_t OCSelectNetwork();
 
 /**
- * Get the CoAP ticks after the specified number of seconds.
+ * Get the CoAP ticks after the specified number of milli-seconds.
  *
- * @param afterSeconds Seconds.
+ * @param afterMilliSeconds Milli-seconds.
  * @return
  *     CoAP ticks
  */
-static uint32_t GetTime(float afterSeconds);
+static uint32_t GetTicks(uint32_t afterMilliSeconds);
 
 /**
  * This method is used to create the IPv4 dev_addr structure.
@@ -435,11 +440,21 @@ static const ServerID OCGetServerInstanceID(void);
 // Internal functions
 //-----------------------------------------------------------------------------
 
-uint32_t GetTime(float afterSeconds)
+uint32_t GetTicks(uint32_t afterMilliSeconds)
 {
     coap_tick_t now;
     coap_ticks(&now);
-    return now + (uint32_t)(afterSeconds * COAP_TICKS_PER_SECOND);
+
+    // Guard against overflow of uint32_t
+    if (afterMilliSeconds <= ((UINT32_MAX - (uint32_t)now) * MILLISECONDS_PER_SECOND) /
+                             COAP_TICKS_PER_SECOND)
+    {
+        return now + (afterMilliSeconds * COAP_TICKS_PER_SECOND)/MILLISECONDS_PER_SECOND;
+    }
+    else
+    {
+        return now;
+    }
 }
 
 OCStackResult OCBuildIPv4Address(uint8_t a, uint8_t b, uint8_t c, uint8_t d,
@@ -727,14 +742,36 @@ static OCStackResult ResetPresenceTTL(ClientCB *cbNode, uint32_t maxAgeSeconds)
         return OC_STACK_INVALID_PARAM;
     }
 
-    OC_LOG_V(INFO, TAG, "Update presence TTL, time is %u", GetTime(0));
+    OC_LOG_V(INFO, TAG, "Update presence TTL, time is %u", GetTicks(0));
 
     cbNode->presence->TTL = maxAgeSeconds;
 
     for(int index = 0; index < PresenceTimeOutSize; index++)
     {
-        lowerBound = GetTime(PresenceTimeOut[index]/ 100.0f*cbNode->presence->TTL);
-        higherBound = GetTime(PresenceTimeOut[index + 1]/100.0f*cbNode->presence->TTL);
+        // Guard against overflow
+        if (cbNode->presence->TTL < (UINT32_MAX/(MILLISECONDS_PER_SECOND*PresenceTimeOut[index]))
+                                     * 100)
+        {
+            lowerBound = GetTicks((PresenceTimeOut[index] *
+                                  cbNode->presence->TTL *
+                                  MILLISECONDS_PER_SECOND)/100);
+        }
+        else
+        {
+            lowerBound = GetTicks(UINT32_MAX);
+        }
+
+        if (cbNode->presence->TTL < (UINT32_MAX/(MILLISECONDS_PER_SECOND*PresenceTimeOut[index+1]))
+                                     * 100)
+        {
+            higherBound = GetTicks((PresenceTimeOut[index + 1] *
+                                   cbNode->presence->TTL *
+                                   MILLISECONDS_PER_SECOND)/100);
+        }
+        else
+        {
+            higherBound = GetTicks(UINT32_MAX);
+        }
 
         cbNode->presence->timeOut[index] = OCGetRandomRange(lowerBound, higherBound);
 
@@ -2172,7 +2209,7 @@ OCStackResult OCProcessPresence()
         {
             if(cbNode->presence)
             {
-                uint32_t now = GetTime(0);
+                uint32_t now = GetTicks(0);
                 OC_LOG_V(DEBUG, TAG, "this TTL level %d",
                                                         cbNode->presence->TTLlevel);
                 OC_LOG_V(DEBUG, TAG, "current ticks %d", now);
@@ -2290,12 +2327,23 @@ OCStackResult OCStartPresence(const uint32_t ttl)
             &(((OCResource *)presenceResource.handle)->resourceProperties),
             OC_ACTIVE, 1);
 
-    if(ttl > 0)
+    if (OC_MAX_PRESENCE_TTL_SECONDS < ttl)
+    {
+        presenceResource.presenceTTL = OC_MAX_PRESENCE_TTL_SECONDS;
+        OC_LOG(INFO, TAG, PCF("Setting Presence TTL to max value"));
+    }
+    else if (0 == ttl)
+    {
+        presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL_SECONDS;
+        OC_LOG(INFO, TAG, PCF("Setting Presence TTL to default value"));
+    }
+    else
     {
         presenceResource.presenceTTL = ttl;
     }
+    OC_LOG_V(DEBUG, TAG, "Presence TTL is %lu seconds", presenceResource.presenceTTL);
 
-    if(OC_PRESENCE_UNINITIALIZED == presenceState)
+    if (OC_PRESENCE_UNINITIALIZED == presenceState)
     {
         presenceState = OC_PRESENCE_INITIALIZED;
 
@@ -3257,7 +3305,7 @@ OCStackResult initResources()
     tailResource = NULL;
     // Init Virtual Resources
     #ifdef WITH_PRESENCE
-    presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL;
+    presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL_SECONDS;
     //presenceResource.token = OCGenerateCoAPToken();
     result = OCCreateResource(&presenceResource.handle,
             OC_RSRVD_RESOURCE_TYPE_PRESENCE,
index d894295..f16c1be 100644 (file)
@@ -351,6 +351,11 @@ namespace OC
         * Start Presence announcements.
         *
         * @param ttl - time to live
+        * Note: If ttl is '0', then the default stack value will be used (60 Seconds).
+        *
+        *       If ttl is greater than OC_MAX_PRESENCE_TTL_SECONDS, then the ttl will be set to
+        *       OC_MAX_PRESENCE_TTL_SECONDS.
+        *
         * @return OCStackResult - Returns OCSTACK_OK if success <br>
         *
         * Server can call this function when it comes online for the