[Telepathy-commits] [telepathy-glib/master] TpMessageMixin: allow message sending to fail; return message ID from tp_message_mixin_take_received

Simon McVittie simon.mcvittie at collabora.co.uk
Thu Dec 18 10:41:31 PST 2008


20080415180149-53eee-f3bc47afef853411b1eb833c4852540907e9fb78.gz
---
 examples/cm/echo-message-parts/chan.c |    2 +-
 telepathy-glib/message-mixin.c        |  104 +++++++++++++++++++++++----------
 telepathy-glib/message-mixin.h        |   12 +++-
 3 files changed, 81 insertions(+), 37 deletions(-)

diff --git a/examples/cm/echo-message-parts/chan.c b/examples/cm/echo-message-parts/chan.c
index d695bc5..8f86fdf 100644
--- a/examples/cm/echo-message-parts/chan.c
+++ b/examples/cm/echo-message-parts/chan.c
@@ -99,7 +99,7 @@ send_message (GObject *object,
 
   /* "OK, we've sent the message" (after calling this, message must not be
    * dereferenced) */
-  tp_message_mixin_sent (object, message, "");
+  tp_message_mixin_sent (object, message, "", NULL);
 
   return TRUE;
 }
diff --git a/telepathy-glib/message-mixin.c b/telepathy-glib/message-mixin.c
index 4726b14..2c6ff4b 100644
--- a/telepathy-glib/message-mixin.c
+++ b/telepathy-glib/message-mixin.c
@@ -180,6 +180,8 @@ typedef struct {
     GPtrArray *content;
     TpChannelTextMessageFlags old_flags;
     gchar *old_text;
+    /* A non-NULL reference until we have been queued, NULL afterwards */
+    GObject *target;
 } PendingItem;
 
 
@@ -620,6 +622,31 @@ tp_message_mixin_get_message_types_async (TpSvcChannelTypeText *iface,
 }
 
 
+static gboolean
+queue_pending (gpointer data)
+{
+  PendingItem *pending = data;
+  GObject *object = pending->target;
+  TpMessageMixin *mixin = TP_MESSAGE_MIXIN (object);
+
+  pending->target = NULL;
+
+  g_queue_push_tail (mixin->priv->pending, pending);
+
+  tp_svc_channel_type_text_emit_received (object, pending->id,
+      pending->timestamp, pending->sender, pending->message_type,
+      pending->old_flags, pending->old_text);
+
+  tp_svc_channel_interface_message_parts_emit_message_received (object,
+      pending->id, pending->timestamp, pending->sender, pending->message_type,
+      pending->content);
+
+  g_object_unref (object);
+
+  return FALSE;
+}
+
+
 /**
  * tp_message_mixin_take_received:
  * @object: a channel with this mixin
@@ -637,8 +664,10 @@ tp_message_mixin_get_message_types_async (TpSvcChannelTypeText *iface,
  * Note that the sender and content arguments are *not* copied, and the caller
  * loses ownership of them (this is to avoid lengthy and unnecessary copying
  * of the content).
+ *
+ * Returns: the message ID
  */
-void
+guint
 tp_message_mixin_take_received (GObject *object,
                                 time_t timestamp,
                                 TpHandle sender,
@@ -666,18 +695,14 @@ tp_message_mixin_take_received (GObject *object,
   pending->old_flags = parts_to_text (content, text);
   pending->old_text = g_string_free (text, FALSE);
 
-  /* Queue it */
-
-  g_queue_push_tail (mixin->priv->pending, pending);
-
-  /* Signal it to clients */
-
-  tp_svc_channel_type_text_emit_received (object,
-      pending->id, timestamp, sender, message_type, pending->old_flags,
-      pending->old_text);
+  /* We don't actually add the pending message to the queue immediately,
+   * to guarantee that the caller of this function gets to see the message ID
+   * before anyone else does (so that it can acknowledge the message to the
+   * network). */
+  pending->target = g_object_ref (object);
+  g_idle_add (queue_pending, pending);
 
-  tp_svc_channel_interface_message_parts_emit_message_received (object,
-      pending->id, timestamp, sender, message_type, content);
+  return pending->id;
 }
 
 
@@ -699,11 +724,13 @@ struct _TpMessageMixinOutgoingMessagePrivate {
 void
 tp_message_mixin_sent (GObject *object,
                        TpMessageMixinOutgoingMessage *message,
-                       const gchar *token)
+                       const gchar *token,
+                       const GError *error)
 {
   TpMessageMixin *mixin = TP_MESSAGE_MIXIN (object);
   time_t now = time (NULL);
   GString *string;
+  guint i;
 
   g_return_if_fail (mixin != NULL);
   g_return_if_fail (object != NULL);
@@ -712,30 +739,43 @@ tp_message_mixin_sent (GObject *object,
   g_return_if_fail (message->parts != NULL);
   g_return_if_fail (message->priv != NULL);
   g_return_if_fail (message->priv->context != NULL);
+  g_return_if_fail (token == NULL || error == NULL);
+  g_return_if_fail (token != NULL || error != NULL);
 
-  if (token == NULL)
-    token = "";
-
-  /* emit Sent and MessageSent */
-
-  tp_svc_channel_interface_message_parts_emit_message_sent (object,
-      message->message_type, message->parts, token);
-  string = g_string_new ("");
-  parts_to_text (message->parts, string);
-  tp_svc_channel_type_text_emit_sent (object, now, message->message_type,
-      g_string_free (string, FALSE));
-
-  /* return successfully */
-
-  if (message->priv->message_parts)
+  if (error != NULL)
     {
-      tp_svc_channel_interface_message_parts_return_from_send_message (
-          message->priv->context, token);
+      GError *e = g_error_copy (error);
+
+      dbus_g_method_return_error (message->priv->context, e);
+      g_error_free (e);
     }
   else
     {
-      tp_svc_channel_type_text_return_from_send (
-          message->priv->context);
+      if (token == NULL)
+        token = "";
+
+      /* emit Sent and MessageSent */
+
+      tp_svc_channel_interface_message_parts_emit_message_sent (object,
+          message->message_type, message->parts, token);
+      string = g_string_new ("");
+      parts_to_text (message->parts, string);
+      tp_svc_channel_type_text_emit_sent (object, now, message->message_type,
+          string->str);
+      g_string_free (string, TRUE);
+
+      /* return successfully */
+
+      if (message->priv->message_parts)
+        {
+          tp_svc_channel_interface_message_parts_return_from_send_message (
+              message->priv->context, token);
+        }
+      else
+        {
+          tp_svc_channel_type_text_return_from_send (
+              message->priv->context);
+        }
     }
 
   message->priv->context = NULL;
diff --git a/telepathy-glib/message-mixin.h b/telepathy-glib/message-mixin.h
index 11b01e7..8155ce7 100644
--- a/telepathy-glib/message-mixin.h
+++ b/telepathy-glib/message-mixin.h
@@ -44,12 +44,14 @@ struct _TpMessageMixin {
 
 
 /* Receiving */
-void tp_message_mixin_take_received (GObject *object,
+
+guint tp_message_mixin_take_received (GObject *object,
     time_t timestamp, TpHandle sender, TpChannelTextMessageType message_type,
     GPtrArray *content);
 
 
 /* Sending */
+
 typedef struct _TpMessageMixinOutgoingMessagePrivate
     TpMessageMixinOutgoingMessagePrivate;
 
@@ -64,7 +66,11 @@ typedef gboolean (*TpMessageMixinSendImpl) (GObject *object,
     TpMessageMixinOutgoingMessage *message);
 
 void tp_message_mixin_sent (GObject *object,
-    TpMessageMixinOutgoingMessage *message, const gchar *token);
+    TpMessageMixinOutgoingMessage *message, const gchar *token,
+    const GError *error);
+
+void tp_message_mixin_implement_sending (GObject *object,
+    TpMessageMixinSendImpl send);
 
 
 /* Initialization */
@@ -76,8 +82,6 @@ void tp_message_mixin_class_init (GObjectClass *obj_cls, gsize offset);
 
 void tp_message_mixin_init (GObject *obj, gsize offset,
     TpHandleRepoIface *contact_repo);
-void tp_message_mixin_implement_sending (GObject *object,
-    TpMessageMixinSendImpl send);
 void tp_message_mixin_finalize (GObject *obj);
 
 G_END_DECLS
-- 
1.5.6.5




More information about the Telepathy-commits mailing list