[telepathy-sofiasip/master] Refactored heartbeat to work per connection

Mikhail Zabaluev mikhail.zabaluev at nokia.com
Mon Sep 14 06:51:28 PDT 2009


There is an iphb client connection for every connection, triggering
wakeups according to the connection's individual keepalive interval.
The Sofia-SIP stack retains a 30 s deadline for its deferrable
timers (which may serve more purposes than keepalives).

The iphb wakeups are supposed to fit with keepalive timer(s)
expiring. Another improvement is an initial sync-in
with other iphb clients using an overlapping interval range.
---
 src/sip-connection-helpers.c |   96 ++++++++++++++++++++++++++++++++++++++
 src/sip-connection-helpers.h |    7 +++
 src/sip-connection-manager.c |  105 +-----------------------------------------
 src/sip-connection-private.h |   11 ++++
 src/sip-connection.c         |    4 ++
 src/sip-connection.h         |    3 +
 6 files changed, 122 insertions(+), 104 deletions(-)

diff --git a/src/sip-connection-helpers.c b/src/sip-connection-helpers.c
index 02717f7..17cdd11 100644
--- a/src/sip-connection-helpers.c
+++ b/src/sip-connection-helpers.c
@@ -18,6 +18,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <config.h>
+
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
@@ -933,3 +935,97 @@ tpsip_handle_parse_from (TpHandleRepoIface *contact_repo,
 
   return handle;
 }
+
+#ifdef HAVE_LIBIPHB
+
+static int
+heartbeat_wakeup (su_root_magic_t *foo,
+                  su_wait_t *wait,
+                  void *user_data)
+{
+  TpsipConnection *self = (TpsipConnection *) user_data;
+  TpsipConnectionPrivate *priv = TPSIP_CONNECTION_GET_PRIVATE (self);
+  gint keepalive_earliest; 
+
+  DEBUG("tick");
+
+  g_assert (priv->heartbeat != NULL);
+
+  if ((wait->revents & (SU_WAIT_HUP | SU_WAIT_ERR)) != 0)
+    {
+      g_warning ("heartbeat descriptor invalidated prematurely with event mask %hd", wait->revents);
+      tpsip_conn_heartbeat_shutdown (self);
+      return 0;
+    }
+
+  keepalive_earliest = (int) priv->keepalive_interval - TPSIP_DEFER_TIMEOUT;
+  if (keepalive_earliest < 0)
+    keepalive_earliest = 0;
+
+  iphb_wait (priv->heartbeat,
+      (gushort) keepalive_earliest,
+      (gushort) MIN(priv->keepalive_interval, G_MAXUSHORT),
+      0);
+
+  return 0;
+}
+
+#endif /* HAVE_LIBIPHB */
+
+void
+tpsip_conn_heartbeat_init (TpsipConnection *self)
+{
+#ifdef HAVE_LIBIPHB
+  TpsipConnectionPrivate *priv = TPSIP_CONNECTION_GET_PRIVATE (self);
+  int wait_id;
+  int reference_interval = 0;
+
+  priv->heartbeat = iphb_open (&reference_interval);
+
+  if (priv->heartbeat == NULL)
+    {
+      g_warning ("opening IP heartbeat failed: %s", strerror (errno));
+      return;
+    }
+
+  DEBUG("heartbeat opened with reference interval %d", reference_interval);
+
+  su_wait_init (priv->heartbeat_wait);
+  if (su_wait_create (priv->heartbeat_wait,
+                      iphb_get_fd (priv->heartbeat),
+                      SU_WAIT_IN) != 0)
+    g_critical ("could not create a wait object");
+
+  wait_id = su_root_register (priv->sofia_root,
+      priv->heartbeat_wait, heartbeat_wakeup, self, 0);
+
+  g_return_if_fail (wait_id > 0);
+  priv->heartbeat_wait_id = wait_id;
+
+  /* Prime the heartbeat for the first time.
+   * The minimum wakeup timeout is 0 to fall in step with other
+   * clients using the same interval */
+  iphb_wait (priv->heartbeat,
+      0, (gushort) MIN(priv->keepalive_interval, G_MAXUSHORT), 0);
+
+#endif /* HAVE_LIBIPHB */
+}
+
+void
+tpsip_conn_heartbeat_shutdown (TpsipConnection *self)
+{
+#ifdef HAVE_LIBIPHB
+  TpsipConnectionPrivate *priv = TPSIP_CONNECTION_GET_PRIVATE (self);
+
+  if (priv->heartbeat_wait_id == 0)
+    return;
+
+  su_root_deregister (priv->sofia_root, priv->heartbeat_wait_id);
+  priv->heartbeat_wait_id = 0;
+
+  su_wait_destroy (priv->heartbeat_wait);
+
+  iphb_close (priv->heartbeat);
+  priv->heartbeat = NULL;
+#endif /* HAVE_LIBIPHB */
+}
diff --git a/src/sip-connection-helpers.h b/src/sip-connection-helpers.h
index b256364..2ddbee7 100644
--- a/src/sip-connection-helpers.h
+++ b/src/sip-connection-helpers.h
@@ -72,6 +72,13 @@ const url_t* tpsip_conn_get_contact_url (TpsipConnection *conn,
 TpHandle tpsip_handle_parse_from (TpHandleRepoIface *contact_repo,
                                   const sip_t *sip);
 
+/***********************************************************************
+ * Heartbeat management for keepalives
+ ***********************************************************************/
+
+void tpsip_conn_heartbeat_init (TpsipConnection *self);
+void tpsip_conn_heartbeat_shutdown (TpsipConnection *self);
+
 G_END_DECLS
 
 #endif /* #ifndef __TPSIP_CONNECTION_HELPERS_H__*/
diff --git a/src/sip-connection-manager.c b/src/sip-connection-manager.c
index 8f51b4e..77118d2 100644
--- a/src/sip-connection-manager.c
+++ b/src/sip-connection-manager.c
@@ -37,20 +37,12 @@
 #include <tpsip/sofia-decls.h>
 #include <sofia-sip/su_glib.h>
 
-#ifdef HAVE_LIBIPHB
-#include <libiphb.h>
-#endif
-
 #include "sip-connection-manager.h"
 #include "sip-connection.h"
 
 #define DEBUG_FLAG TPSIP_DEBUG_CONNECTION
 #include "debug.h"
 
-/* Time bounds for heartbeat, in seconds */
-#define TPSIP_HEARTBEAT_MIN 0
-#define TPSIP_HEARTBEAT_MAX 30
-
 
 G_DEFINE_TYPE(TpsipConnectionManager, tpsip_connection_manager,
     TP_TYPE_BASE_CONNECTION_MANAGER)
@@ -210,103 +202,10 @@ const TpCMProtocolSpec tpsip_protocols[] = {
 struct _TpsipConnectionManagerPrivate
 {
   su_root_t *sofia_root;
-
-#ifdef HAVE_LIBIPHB
-  iphb_t    heartbeat;
-  su_wait_t heartbeat_wait[1];
-  int       heartbeat_wait_id;
-#endif
 };
 
 #define TPSIP_CONNECTION_MANAGER_GET_PRIVATE(obj) ((obj)->priv)
 
-#ifdef HAVE_LIBIPHB
-
-static void heartbeat_shutdown (TpsipConnectionManager *self);
-
-static int
-heartbeat_wakeup (TpsipConnectionManager *self,
-                  su_wait_t *wait,
-                  void *user_data)
-{
-  TpsipConnectionManagerPrivate *priv = TPSIP_CONNECTION_MANAGER_GET_PRIVATE (self);
-
-  DEBUG("tick");
-
-  g_assert (priv->heartbeat != NULL);
-
-  if ((wait->revents & (SU_WAIT_HUP | SU_WAIT_ERR)) != 0)
-    {
-      g_warning ("heartbeat descriptor invalidated prematurely with event mask %hd", wait->revents);
-      heartbeat_shutdown (self);
-      return 0;
-    }
-
-  iphb_wait (priv->heartbeat, TPSIP_HEARTBEAT_MIN, TPSIP_HEARTBEAT_MAX, 0);
-
-  return 0;
-}
-
-#endif /* HAVE_LIBIPHB */
-
-static void
-heartbeat_init (TpsipConnectionManager *self)
-{
-#ifdef HAVE_LIBIPHB
-  TpsipConnectionManagerPrivate *priv = TPSIP_CONNECTION_MANAGER_GET_PRIVATE (self);
-  int wait_id;
-  int reference_interval = 0;
-
-  su_root_set_max_defer (priv->sofia_root, TPSIP_HEARTBEAT_MAX * 1000L + 50L);
-
-  priv->heartbeat = iphb_open (&reference_interval);
-
-  if (priv->heartbeat == NULL)
-    {
-      g_warning ("opening IP heartbeat failed: %s", strerror (errno));
-      return;
-    }
-
-  DEBUG("heartbeat opened with reference interval %d", reference_interval);
-
-  su_wait_init (priv->heartbeat_wait);
-  if (su_wait_create (priv->heartbeat_wait,
-                      iphb_get_fd (priv->heartbeat),
-                      SU_WAIT_IN) != 0)
-    g_critical ("could not create a wait object");
-
-  wait_id = su_root_register (priv->sofia_root,
-      priv->heartbeat_wait, heartbeat_wakeup, NULL, 0);
-
-  g_return_if_fail (wait_id > 0);
-  priv->heartbeat_wait_id = wait_id;
-
-  /* Prime the heartbeat for the first time.
-   * The correct sequence is iphb_wait() -> poll */
-  iphb_wait (priv->heartbeat, TPSIP_HEARTBEAT_MIN, TPSIP_HEARTBEAT_MAX, 0);
-
-#endif /* HAVE_LIBIPHB */
-}
-
-static void
-heartbeat_shutdown (TpsipConnectionManager *self)
-{
-#ifdef HAVE_LIBIPHB
-  TpsipConnectionManagerPrivate *priv = TPSIP_CONNECTION_MANAGER_GET_PRIVATE (self);
-
-  if (priv->heartbeat_wait_id == 0)
-    return;
-
-  su_root_deregister (priv->sofia_root, priv->heartbeat_wait_id);
-  priv->heartbeat_wait_id = 0;
-
-  su_wait_destroy (priv->heartbeat_wait);
-
-  iphb_close (priv->heartbeat);
-  priv->heartbeat = NULL;
-#endif /* HAVE_LIBIPHB */
-}
-
 static void
 tpsip_connection_manager_init (TpsipConnectionManager *obj)
 {
@@ -321,7 +220,7 @@ tpsip_connection_manager_init (TpsipConnectionManager *obj)
   source = su_root_gsource(priv->sofia_root);
   g_source_attach(source, NULL);
 
-  heartbeat_init (obj);
+  su_root_set_max_defer (priv->sofia_root, TPSIP_DEFER_TIMEOUT * 1000L);
 }
 
 static void tpsip_connection_manager_finalize (GObject *object);
@@ -352,8 +251,6 @@ tpsip_connection_manager_finalize (GObject *object)
   TpsipConnectionManagerPrivate *priv = TPSIP_CONNECTION_MANAGER_GET_PRIVATE (self);
   GSource *source;
 
-  heartbeat_shutdown (self);
-
   source = su_root_gsource(priv->sofia_root);
   g_source_destroy(source);
   su_root_destroy(priv->sofia_root);
diff --git a/src/sip-connection-private.h b/src/sip-connection-private.h
index 4344322..23ab575 100644
--- a/src/sip-connection-private.h
+++ b/src/sip-connection-private.h
@@ -21,11 +21,16 @@
 #ifndef __TPSIP_CONNECTION_PRIVATE_H__
 #define __TPSIP_CONNECTION_PRIVATE_H__
 
+#include <config.h>
 #include "media-factory.h"
 
 #include <tpsip/sofia-decls.h>
 #include <sofia-sip/sresolv.h>
 
+#ifdef HAVE_LIBIPHB
+#include <libiphb.h>
+#endif
+
 struct _TpsipConnectionPrivate
 {
   su_root_t *sofia_root;
@@ -37,6 +42,12 @@ struct _TpsipConnectionPrivate
   url_t *proxy_url;
   url_t *registrar_url;
 
+#ifdef HAVE_LIBIPHB
+  iphb_t    heartbeat;
+  su_wait_t heartbeat_wait[1];
+  int       heartbeat_wait_id;
+#endif
+
   gchar *registrar_realm;
 
   TpsipMediaFactory *media_factory;
diff --git a/src/sip-connection.c b/src/sip-connection.c
index c89cec4..29af4c4 100644
--- a/src/sip-connection.c
+++ b/src/sip-connection.c
@@ -780,6 +780,8 @@ tpsip_connection_shut_down (TpBaseConnection *base)
   /* We disposed of the REGISTER handle in the disconnected method */
   g_assert (priv->register_op == NULL);
 
+  tpsip_conn_heartbeat_shutdown (self);
+
   if (priv->sofia_nua != NULL)
     nua_shutdown (priv->sofia_nua);
 
@@ -951,6 +953,8 @@ tpsip_connection_start_connecting (TpBaseConnection *base,
 
   nua_register (priv->register_op, TAG_NULL());
 
+  tpsip_conn_heartbeat_init (self);
+
   return TRUE;
 }
 
diff --git a/src/sip-connection.h b/src/sip-connection.h
index 1629a5c..1774cb6 100644
--- a/src/sip-connection.h
+++ b/src/sip-connection.h
@@ -34,6 +34,9 @@ G_BEGIN_DECLS
 
 #define TPSIP_DEFAULT_STUN_PORT 3478
 
+/* Maximum defer timeout for deferrable Sofia timers */
+#define TPSIP_DEFER_TIMEOUT 30
+
 typedef enum
 {
   TPSIP_CONNECTION_KEEPALIVE_AUTO = 0,	/** Keepalive management is up to the implementation */
-- 
1.5.6.5




More information about the telepathy-commits mailing list