[telepathy-sofiasip/master] Experimental addition of a heartbeat wait source to the Sofia root
Mikhail Zabaluev
mikhail.zabaluev at nokia.com
Fri Jul 24 12:10:26 PDT 2009
As implemented currently, a mainloop timeout drives I/O events by writing
to a pipe. Deferrable timer functionality from the heartbeat branch is not
used yet.
---
src/sip-connection-manager.c | 114 +++++++++++++++++++++++++++++++++++++++++-
tpsip/sofia-decls.h | 1 +
2 files changed, 114 insertions(+), 1 deletions(-)
diff --git a/src/sip-connection-manager.c b/src/sip-connection-manager.c
index 4e190fe..9386158 100644
--- a/src/sip-connection-manager.c
+++ b/src/sip-connection-manager.c
@@ -26,6 +26,7 @@
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <dbus/dbus-protocol.h>
@@ -199,9 +200,116 @@ const TpCMProtocolSpec tpsip_protocols[] = {
struct _TpsipConnectionManagerPrivate
{
su_root_t *sofia_root;
+
+ su_wait_t heartbeat_wait[1];
+ int heartbeat_wait_id;
+ int heartbeat_pipe[2];
};
-#define TPSIP_CONNECTION_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TPSIP_TYPE_CONNECTION_MANAGER, TpsipConnectionManagerPrivate))
+#define TPSIP_CONNECTION_MANAGER_GET_PRIVATE(obj) ((obj)->priv)
+
+static void heartbeat_shutdown (TpsipConnectionManager *self);
+
+static int
+heartbeat_wakeup (TpsipConnectionManager *self,
+ su_wait_t *wait,
+ void *user_data)
+{
+ DEBUG("tick");
+
+ 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);
+ }
+ else if ((wait->revents & SU_WAIT_IN) != 0)
+ {
+ ssize_t bytes_read;
+ char foo[1];
+
+ bytes_read = read (wait->fd, foo, 1);
+
+ if (bytes_read < 0)
+ {
+ g_warning ("error reading from the heartbeat descriptor: %s", strerror (errno));
+ heartbeat_shutdown (self);
+ }
+ else if (bytes_read == 0)
+ {
+ g_warning ("premature EOF from heartbeat descriptor");
+ heartbeat_shutdown (self);
+ }
+ }
+ else
+ g_assert_not_reached ();
+
+ return 0;
+}
+
+static gboolean
+heartbeat_pump (gpointer data)
+{
+ TpsipConnectionManager *self = TPSIP_CONNECTION_MANAGER (data);
+ TpsipConnectionManagerPrivate *priv = TPSIP_CONNECTION_MANAGER_GET_PRIVATE (self);
+ ssize_t write_res;
+ char foo[1];
+
+ DEBUG("tock...");
+
+ write_res = write (priv->heartbeat_pipe[1], foo, 1);
+
+ if (write_res < 0)
+ {
+ g_warning ("error writing to the heartbeat pipe: %s", strerror (errno));
+ heartbeat_shutdown (self);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+heartbeat_init (TpsipConnectionManager *self)
+{
+ TpsipConnectionManagerPrivate *priv = TPSIP_CONNECTION_MANAGER_GET_PRIVATE (self);
+ int wait_id;
+
+ /* In this testing code, we emulate the heartbeat socket with a
+ * timer-driven pipe */
+ if (pipe (priv->heartbeat_pipe) != 0)
+ g_error ("heartbeat pipe creation failed");
+
+ su_wait_init (priv->heartbeat_wait);
+ if (su_wait_create (priv->heartbeat_wait, priv->heartbeat_pipe[0],
+ SU_WAIT_IN | SU_WAIT_HUP | SU_WAIT_ERR) != 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;
+
+ /* For testing purposes only */
+ g_timeout_add (10000, heartbeat_pump, self);
+}
+
+static void
+heartbeat_shutdown (TpsipConnectionManager *self)
+{
+ 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);
+
+ close (priv->heartbeat_pipe[1]);
+ close (priv->heartbeat_pipe[0]);
+}
static void
tpsip_connection_manager_init (TpsipConnectionManager *obj)
@@ -216,6 +324,8 @@ tpsip_connection_manager_init (TpsipConnectionManager *obj)
su_root_threading(priv->sofia_root, 0);
source = su_root_gsource(priv->sofia_root);
g_source_attach(source, NULL);
+
+ heartbeat_init (obj);
}
static void tpsip_connection_manager_finalize (GObject *object);
@@ -246,6 +356,8 @@ 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/tpsip/sofia-decls.h b/tpsip/sofia-decls.h
index 17e8894..64b938b 100644
--- a/tpsip/sofia-decls.h
+++ b/tpsip/sofia-decls.h
@@ -37,6 +37,7 @@
#define NUA_HMAGIC_T struct _TpsipEventTarget
#define SU_ROOT_MAGIC_T struct _TpsipConnectionManager
#define SU_TIMER_ARG_T struct _TpsipConnection
+#define SU_WAKEUP_ARG_T void
#include <sofia-sip/nua.h>
#include <sofia-sip/su.h>
--
1.5.6.5
More information about the telepathy-commits
mailing list