[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