summaryrefslogtreecommitdiff
path: root/telepathy-glib/dbus-tube-channel.c
diff options
context:
space:
mode:
authorWill Thompson <will.thompson@collabora.co.uk>2012-03-30 09:00:50 +0100
committerWill Thompson <will.thompson@collabora.co.uk>2012-03-30 15:32:45 +0100
commitecbbb72e7d11951a13514151cdf16112e09e608c (patch)
tree7ab1cc7ddd7332378270a99e00975a1c1303e62d /telepathy-glib/dbus-tube-channel.c
parenta3725ba5c52443bdad1d6bf87230bd01af4cf53a (diff)
downloadtelepathy-glib-ecbbb72e7d11951a13514151cdf16112e09e608c.tar.gz
dbus-tube: fail offer/accept if channel is invalidated
Diffstat (limited to 'telepathy-glib/dbus-tube-channel.c')
-rw-r--r--telepathy-glib/dbus-tube-channel.c42
1 files changed, 39 insertions, 3 deletions
diff --git a/telepathy-glib/dbus-tube-channel.c b/telepathy-glib/dbus-tube-channel.c
index dfbb710dc..2967fdbe9 100644
--- a/telepathy-glib/dbus-tube-channel.c
+++ b/telepathy-glib/dbus-tube-channel.c
@@ -89,7 +89,8 @@ tp_dbus_tube_channel_dispose (GObject *obj)
TpDBusTubeChannel *self = (TpDBusTubeChannel *) obj;
tp_clear_pointer (&self->priv->parameters, g_hash_table_unref);
- g_clear_object (&self->priv->result);
+ /* If priv->result isn't NULL, it owns a ref to self. */
+ g_warn_if_fail (self->priv->result == NULL);
tp_clear_pointer (&self->priv->address, g_free);
G_OBJECT_CLASS (tp_dbus_tube_channel_parent_class)->dispose (obj);
@@ -123,8 +124,19 @@ tp_dbus_tube_channel_get_property (GObject *object,
static void
complete_operation (TpDBusTubeChannel *self)
{
- g_simple_async_result_complete (self->priv->result);
- g_clear_object (&self->priv->result);
+ TpDBusTubeChannelPrivate *priv = self->priv;
+ GSimpleAsyncResult *result = priv->result;
+
+ /* This dance is to ensure that we don't accidentally manipulate priv->result
+ * while calling out to user code. For instance, someone might call
+ * tp_proxy_invalidate() on us, which winds up landing us in here via our
+ * handler for that signal.
+ */
+ g_assert (priv->result != NULL);
+ result = priv->result;
+ priv->result = NULL;
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
}
static void
@@ -172,6 +184,27 @@ check_tube_open (TpDBusTubeChannel *self)
}
static void
+dbus_tube_invalidated_cb (
+ TpProxy *proxy,
+ guint domain,
+ gint code,
+ gchar *message,
+ gpointer user_data)
+{
+ TpDBusTubeChannel *self = TP_DBUS_TUBE_CHANNEL (proxy);
+ TpDBusTubeChannelPrivate *priv = self->priv;
+ GError error = { domain, code, message };
+
+ if (priv->result != NULL)
+ {
+ DEBUG ("Tube invalidated: '%s'; failing pending offer/accept method call",
+ message);
+ g_simple_async_result_set_from_error (priv->result, &error);
+ complete_operation (self);
+ }
+}
+
+static void
tube_state_changed_cb (TpChannel *channel,
TpTubeChannelState state,
gpointer user_data,
@@ -245,6 +278,9 @@ tp_dbus_tube_channel_constructed (GObject *obj)
TP_HASH_TYPE_STRING_VARIANT_MAP, params);
}
}
+
+ g_signal_connect (self, "invalidated",
+ G_CALLBACK (dbus_tube_invalidated_cb), NULL);
}
static void