[Telepathy-commits] [telepathy-salut/master] Stream tube object sends a close tube message when the tube is close. It has a reference on the XmppConnectionManager to request a connection. When a close tube message is received, close the tube.

Alban Crequy alban.crequy at collabora.co.uk
Tue Nov 25 03:59:13 PST 2008


20080721114615-a41c0-e516a921271f991b7a7ab359e070a5f5ba8ff190.gz
---
 src/salut-tubes-channel.c |   26 +++++++-
 src/salut-tubes-channel.h |    3 +
 src/salut-tubes-manager.c |   90 ++++++++++++++++++----------
 src/tube-stream.c         |  147 ++++++++++++++++++++++++++++++++++-----------
 src/tube-stream.h         |    7 +-
 5 files changed, 201 insertions(+), 72 deletions(-)

diff --git a/src/salut-tubes-channel.c b/src/salut-tubes-channel.c
index 964d9d7..ae047c4 100644
--- a/src/salut-tubes-channel.c
+++ b/src/salut-tubes-channel.c
@@ -943,6 +943,27 @@ tubes_message_received (SalutTubesChannel *self,
     }
 }
 
+void tubes_message_close_received (SalutTubesChannel *self,
+                                   TpHandle initiator_handle,
+                                   guint tube_id)
+{
+  SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
+
+  SalutTubeIface *tube;
+
+  tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
+
+  if (tube)
+    {
+      DEBUG ("received a tube close message");
+      salut_tube_iface_close (tube);
+    }
+  else
+    {
+      DEBUG ("received a tube close message on a non existant tube");
+    }
+}
+
 static void
 muc_connection_new_senders_cb (GibberMucConnection *conn,
                                GArray *senders,
@@ -1142,8 +1163,8 @@ create_new_tube (SalutTubesChannel *self,
       break;
     case TP_TUBE_TYPE_STREAM:
       tube = SALUT_TUBE_IFACE (salut_tube_stream_new (priv->conn,
-          priv->handle, priv->handle_type, priv->self_handle, initiator,
-          service, parameters, tube_id));
+          priv->xmpp_connection_manager, priv->handle, priv->handle_type,
+          priv->self_handle, initiator, service, parameters, tube_id));
       break;
     default:
       g_assert_not_reached ();
@@ -1889,6 +1910,7 @@ _send_channel_iq_tube (gpointer key,
           g_error_free (error);
         }
 
+      g_object_unref (stanza);
       g_free (tube_id_str);
     }
 
diff --git a/src/salut-tubes-channel.h b/src/salut-tubes-channel.h
index 932f6f7..4941f9f 100644
--- a/src/salut-tubes-channel.h
+++ b/src/salut-tubes-channel.h
@@ -75,6 +75,9 @@ void tubes_message_received (SalutTubesChannel *self,
     const gchar *service, TpTubeType tube_type, TpHandle initiator_handle,
     GHashTable *parameters, guint tube_id);
 
+void tubes_message_close_received (SalutTubesChannel *self,
+    TpHandle initiator_handle, guint tube_id);
+
 G_END_DECLS
 
 #endif /* #ifndef __SALUT_TUBES_CHANNEL_H__*/
diff --git a/src/salut-tubes-manager.c b/src/salut-tubes-manager.c
index 2dd7242..0905505 100644
--- a/src/salut-tubes-manager.c
+++ b/src/salut-tubes-manager.c
@@ -127,6 +127,7 @@ iq_tube_request_filter (SalutXmppConnectionManager *xcm,
 static gboolean
 extract_tube_information (TpHandleRepoIface *contact_repo,
                           GibberXmppStanza *stanza,
+                          gboolean *close,
                           TpTubeType *type,
                           TpHandle *initiator_handle,
                           const gchar **service,
@@ -134,7 +135,8 @@ extract_tube_information (TpHandleRepoIface *contact_repo,
                           guint *tube_id)
 {
   GibberXmppNode *iq;
-  GibberXmppNode *tube_node;
+  GibberXmppNode *tube_node, *close_node, *node;
+  gboolean _close;
 
   iq = stanza->node;
 
@@ -159,13 +161,35 @@ extract_tube_information (TpHandleRepoIface *contact_repo,
 
   tube_node = gibber_xmpp_node_get_child_ns (iq, "tube",
       GIBBER_TELEPATHY_NS_TUBES);
-  if (tube_node == NULL)
+  close_node = gibber_xmpp_node_get_child_ns (iq, "close",
+      GIBBER_TELEPATHY_NS_TUBES);
+
+  if (tube_node == NULL && close_node == NULL)
     {
-      DEBUG ("The <iq> does not have a <tube>");
+      DEBUG ("The <iq> does not have a <tube> nor a <close>");
       return FALSE;
     }
+  if (tube_node != NULL && close_node != NULL)
+    {
+      DEBUG ("The <iq> has both a <tube> nor a <close>");
+      return FALSE;
+    }
+  if (tube_node != NULL)
+    {
+      node = tube_node;
+    }
+  else
+    {
+      node = close_node;
+    }
+
+  _close = close_node != NULL;
+  if (close != NULL)
+    {
+      *close = _close;
+    }
 
-  if (type != NULL)
+  if (!_close && type != NULL)
     {
       const gchar *tube_type;
 
@@ -181,12 +205,12 @@ extract_tube_information (TpHandleRepoIface *contact_repo,
         }
     }
 
-  if (service != NULL)
+  if (!_close && service != NULL)
     {
       *service = gibber_xmpp_node_get_attribute (tube_node, "service");
     }
 
-  if (parameters != NULL)
+  if (!_close && parameters != NULL)
     {
       GibberXmppNode *node;
 
@@ -201,10 +225,10 @@ extract_tube_information (TpHandleRepoIface *contact_repo,
       gchar *endptr;
       long int tmp;
 
-      str = gibber_xmpp_node_get_attribute (tube_node, "id");
+      str = gibber_xmpp_node_get_attribute (node, "id");
       if (str == NULL)
         {
-          DEBUG ("no tube id in SI request");
+          DEBUG ("no tube id in tube request");
           return FALSE;
         }
 
@@ -231,55 +255,57 @@ iq_tube_request_cb (SalutXmppConnectionManager *xcm,
   TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
       (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
 
-  GibberXmppNode *close;
   GibberXmppStanza *reply;
 
   /* tube informations */
-  const gchar *service;
-  TpTubeType tube_type;
+  const gchar *service = NULL;
+  TpTubeType tube_type = TP_TUBE_TYPE_DBUS;
   TpHandle initiator_handle;
-  GHashTable *parameters;
+  GHashTable *parameters = NULL;
   guint tube_id;
+  gboolean close;
 
   SalutTubesChannel *chan;
 
   /* after this point, the message is for us, so in all cases we either handle
    * it or send an error reply */
 
-  close = gibber_xmpp_node_get_child_ns (stanza->node, "close",
-      GIBBER_TELEPATHY_NS_TUBES);
-  if (close != NULL)
-    {
-      DEBUG ("received a close tube request. Not implemented.");
-      return;
-    }
-
-  if (!extract_tube_information (contact_repo, stanza, &tube_type,
+  if (!extract_tube_information (contact_repo, stanza, &close, &tube_type,
           &initiator_handle, &service, &parameters, &tube_id))
     {
       GibberXmppStanza *reply;
 
       reply = gibber_iq_helper_new_error_reply (stanza, XMPP_ERROR_BAD_REQUEST,
-          "failed to parse SI request");
+          "failed to parse tube request");
       gibber_xmpp_connection_send (conn, reply, NULL);
 
       g_object_unref (reply);
       return;
     }
 
-  DEBUG ("received a tube request of type %d, tube_id %d", tube_type, tube_id);
+  DEBUG ("received a tube request, tube_id %d", tube_id);
 
   chan = g_hash_table_lookup (priv->channels,
       GUINT_TO_POINTER (initiator_handle));
-  if (chan == NULL)
-    {
-      chan = new_tubes_channel (self, initiator_handle);
-      tp_channel_factory_iface_emit_new_channel (self,
-          (TpChannelIface *) chan, NULL);
-    }
-
-  tubes_message_received (chan, service, tube_type, initiator_handle,
-      parameters, tube_id);
+  if (close)
+  {
+    if (chan != NULL)
+      {
+        tubes_message_close_received (chan, initiator_handle, tube_id);
+      }
+  }
+  else
+  {
+    if (chan == NULL)
+      {
+        chan = new_tubes_channel (self, initiator_handle);
+        tp_channel_factory_iface_emit_new_channel (self,
+            (TpChannelIface *) chan, NULL);
+      }
+
+    tubes_message_received (chan, service, tube_type, initiator_handle,
+        parameters, tube_id);
+  }
 
   reply = gibber_iq_helper_new_result_reply (stanza);
   gibber_xmpp_connection_send (conn, reply, NULL);
diff --git a/src/tube-stream.c b/src/tube-stream.c
index a6dfbea..0759404 100644
--- a/src/tube-stream.c
+++ b/src/tube-stream.c
@@ -38,6 +38,7 @@
 #include <gibber/gibber-bytestream-iface.h>
 #include <gibber/gibber-transport.h>
 #include <gibber/gibber-fd-transport.h>
+#include <gibber/gibber-iq-helper.h>
 
 #define DEBUG_FLAG DEBUG_TUBES
 
@@ -48,6 +49,7 @@
 #include "tube-iface.h"
 #include "salut-bytestream-manager.h"
 #include "salut-contact-manager.h"
+#include "salut-xmpp-connection-manager.h"
 
 static void
 tube_iface_init (gpointer g_iface, gpointer iface_data);
@@ -88,6 +90,7 @@ static guint signals[LAST_SIGNAL] = {0};
 enum
 {
   PROP_CONNECTION = 1,
+  PROP_CHANNEL,
   PROP_HANDLE,
   PROP_HANDLE_TYPE,
   PROP_SELF_HANDLE,
@@ -101,6 +104,7 @@ enum
   PROP_ADDRESS,
   PROP_ACCESS_CONTROL,
   PROP_ACCESS_CONTROL_PARAM,
+  PROP_XMPP_CONNECTION_MANAGER,
   LAST_PROPERTY
 };
 
@@ -131,6 +135,10 @@ struct _SalutTubeStreamPrivate
   guint listen_io_channel_source_id;
   gboolean closed;
 
+  /* we need to send an iq stanza to close the tube */
+  GibberIqHelper *iq_helper;
+  SalutXmppConnectionManager *xmpp_connection_manager;
+
   gboolean offer_needed;
 
   gboolean dispose_has_run;
@@ -915,6 +923,12 @@ salut_tube_stream_dispose (GObject *object)
       priv->listen_io_channel = NULL;
     }
 
+  if (priv->iq_helper != NULL)
+    {
+      g_object_unref (priv->iq_helper);
+      priv->iq_helper = NULL;
+    }
+
   priv->dispose_has_run = TRUE;
 
   if (G_OBJECT_CLASS (salut_tube_stream_parent_class)->dispose)
@@ -998,6 +1012,9 @@ salut_tube_stream_get_property (GObject *object,
       case PROP_ACCESS_CONTROL_PARAM:
         g_value_set_pointer (value, priv->access_control_param);
         break;
+      case PROP_XMPP_CONNECTION_MANAGER:
+        g_value_set_object (value, priv->xmpp_connection_manager);
+        break;
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
         break;
@@ -1065,6 +1082,10 @@ salut_tube_stream_set_property (GObject *object,
                 g_value_get_pointer (value));
           }
         break;
+      case PROP_XMPP_CONNECTION_MANAGER:
+        priv->xmpp_connection_manager = g_value_get_object (value);
+        g_object_ref (priv->xmpp_connection_manager);
+        break;
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
         break;
@@ -1204,6 +1225,31 @@ salut_tube_stream_class_init (SalutTubeStreamClass *salut_tube_stream_class)
   g_object_class_install_property (object_class, PROP_ACCESS_CONTROL_PARAM,
       param_spec);
 
+  param_spec = g_param_spec_object (
+      "channel",
+      "SalutTubesChannel object",
+      "Salut Tubes Channel associated with this stream tube object",
+      SALUT_TYPE_TUBES_CHANNEL,
+      G_PARAM_CONSTRUCT_ONLY |
+      G_PARAM_READWRITE |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (object_class, PROP_CHANNEL,
+      param_spec);
+
+  param_spec = g_param_spec_object (
+      "xmpp-connection-manager",
+      "SalutXmppConnectionManager object",
+      "Salut XMPP Connection manager used for this tube channel in case of "
+          "1-1 tube",
+      SALUT_TYPE_XMPP_CONNECTION_MANAGER,
+      G_PARAM_CONSTRUCT_ONLY |
+      G_PARAM_READWRITE |
+      G_PARAM_STATIC_NICK |
+      G_PARAM_STATIC_BLURB);
+  g_object_class_install_property (object_class, PROP_XMPP_CONNECTION_MANAGER,
+      param_spec);
+
   signals[OPENED] =
     g_signal_new ("opened",
                   G_OBJECT_CLASS_TYPE (salut_tube_stream_class),
@@ -1262,6 +1308,7 @@ data_received_cb (GibberBytestreamIface *bytestream,
 
 SalutTubeStream *
 salut_tube_stream_new (SalutConnection *conn,
+                        SalutXmppConnectionManager *xmpp_connection_manager,
                         TpHandle handle,
                         TpHandleType handle_type,
                         TpHandle self_handle,
@@ -1272,6 +1319,7 @@ salut_tube_stream_new (SalutConnection *conn,
 {
   return g_object_new (SALUT_TYPE_TUBE_STREAM,
       "connection", conn,
+      "xmpp-connection-manager", xmpp_connection_manager,
       "handle", handle,
       "handle-type", handle_type,
       "self-handle", self_handle,
@@ -1322,6 +1370,15 @@ salut_tube_stream_offer_needed (SalutTubeIface *tube)
   return priv->offer_needed;
 }
 
+static void
+iq_close_reply_cb (GibberIqHelper *helper,
+                   GibberXmppStanza *sent_stanza,
+                   GibberXmppStanza *reply_stanza,
+                   GObject *object,
+                   gpointer user_data)
+{
+}
+
 /**
  * salut_tube_stream_close
  *
@@ -1342,43 +1399,63 @@ salut_tube_stream_close (SalutTubeIface *tube)
 
   if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
     {
-      /* TODO: implement 1-1 tube */
-#if 0
-      LmMessage *msg;
-      const gchar *jid;
+      GibberXmppStanza *stanza;
+      const gchar *jid_from, *jid_to;
       TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
           (TpBaseConnection*) priv->conn, TP_HANDLE_TYPE_CONTACT);
-      gchar *id_str;
-
-      jid = tp_handle_inspect (contact_repo, priv->handle);
-      id_str = g_strdup_printf ("%u", priv->id);
-
-      /* Send the close message */
-      msg = lm_message_build (jid, LM_MESSAGE_TYPE_MESSAGE,
-          '(', "close", "",
-            '@', "xmlns", NS_TUBES,
-            '@', "tube", id_str,
-          ')',
-          '(', "amp", "",
-            '@', "xmlns", NS_AMP,
-            '(', "rule", "",
-              '@', "condition", "deliver-at",
-              '@', "value", "stored",
-              '@', "action", "error",
-            ')',
-            '(', "rule", "",
-              '@', "condition", "match-resource",
-              '@', "value", "exact",
-              '@', "action", "error",
-            ')',
-          ')',
-          NULL);
-      g_free (id_str);
-
-      _salut_connection_send (priv->conn, msg, NULL);
-
-      lm_message_unref (msg);
-#endif
+      gchar *tube_id_str;
+      GError *error = NULL;
+
+      jid_to = tp_handle_inspect (contact_repo, priv->handle);
+      jid_from = tp_handle_inspect (contact_repo, priv->self_handle);
+      tube_id_str = g_strdup_printf ("%u", priv->id);
+
+      stanza = gibber_xmpp_stanza_build (GIBBER_STANZA_TYPE_IQ,
+          GIBBER_STANZA_SUB_TYPE_SET,
+          jid_from, jid_to,
+          GIBBER_NODE, "close",
+            GIBBER_NODE_XMLNS, GIBBER_TELEPATHY_NS_TUBES,
+            GIBBER_NODE_ATTRIBUTE, "id", tube_id_str,
+          GIBBER_NODE_END,
+          GIBBER_STANZA_END);
+
+      if (priv->iq_helper == NULL)
+        {
+          SalutXmppConnectionManagerRequestConnectionResult result;
+          SalutContactManager *contact_mgr;
+          SalutContact *contact;
+          GibberXmppConnection *xmpp_connection = NULL;
+
+          g_object_get (priv->conn, "contact-manager", &contact_mgr, NULL);
+          g_assert (contact_mgr != NULL);
+
+          contact = salut_contact_manager_get_contact (contact_mgr,
+              priv->handle);
+
+          result = salut_xmpp_connection_manager_request_connection (
+              priv->xmpp_connection_manager, contact, &xmpp_connection, NULL);
+
+          if (result ==
+              SALUT_XMPP_CONNECTION_MANAGER_REQUEST_CONNECTION_RESULT_DONE)
+            {
+              priv->iq_helper = gibber_iq_helper_new (xmpp_connection);
+              g_assert (priv->iq_helper);
+            }
+        }
+
+      if (priv->iq_helper != NULL)
+        {
+          if (!gibber_iq_helper_send_with_reply (priv->iq_helper, stanza,
+              iq_close_reply_cb, G_OBJECT(self), tube, &error))
+            {
+              DEBUG ("ERROR: '%s'", error->message);
+              g_error_free (error);
+            }
+        }
+
+      g_free (tube_id_str);
+
+      g_object_unref (stanza);
     }
 
   g_signal_emit (G_OBJECT (self), signals[CLOSED], 0);
diff --git a/src/tube-stream.h b/src/tube-stream.h
index f770198..3472065 100644
--- a/src/tube-stream.h
+++ b/src/tube-stream.h
@@ -25,6 +25,7 @@
 #include <telepathy-glib/enums.h>
 
 #include "salut-connection.h"
+#include "salut-tubes-channel.h"
 
 G_BEGIN_DECLS
 
@@ -60,9 +61,9 @@ GType salut_tube_stream_get_type (void);
                               SalutTubeStreamClass))
 
 SalutTubeStream *salut_tube_stream_new (SalutConnection *conn,
-    TpHandle handle, TpHandleType handle_type, TpHandle self_handle,
-    TpHandle initiator, const gchar *service, GHashTable *parameters,
-    guint id);
+    SalutXmppConnectionManager *xmpp_connection_manager, TpHandle handle,
+    TpHandleType handle_type, TpHandle self_handle, TpHandle initiator,
+    const gchar *service, GHashTable *parameters, guint id);
 
 gboolean salut_tube_stream_check_params (TpSocketAddressType address_type,
     const GValue *address, TpSocketAccessControl access_control,
-- 
1.5.6.5




More information about the Telepathy-commits mailing list