[Telepathy-commits] [telepathy-salut/master] Caps: Reply to disco requests. Send disco requests.

Alban Crequy alban.crequy at collabora.co.uk
Thu Feb 26 11:20:10 PST 2009


---
 src/salut-caps-channel-manager.c |    2 +-
 src/salut-caps-channel-manager.h |    4 +-
 src/salut-caps-hash.c            |    3 +-
 src/salut-caps-hash.h            |    2 +-
 src/salut-connection.c           |  192 ++++++++++++++++++-
 src/salut-disco.c                |  406 ++++++++++++++++++++++++--------------
 src/salut-disco.h                |    7 +-
 src/salut-presence-cache.c       |   48 +++---
 src/salut-presence-cache.h       |    3 +-
 src/salut-tubes-channel.c        |    1 +
 10 files changed, 486 insertions(+), 182 deletions(-)

diff --git a/src/salut-caps-channel-manager.c b/src/salut-caps-channel-manager.c
index b79f236..41a9ee7 100644
--- a/src/salut-caps-channel-manager.c
+++ b/src/salut-caps-channel-manager.c
@@ -92,7 +92,7 @@ void salut_caps_channel_manager_get_feature_list (
 
 gpointer salut_caps_channel_manager_parse_capabilities (
     SalutCapsChannelManager *caps_manager,
-    GibberXmppStanza *child)
+    GibberXmppNode *child)
 {
   SalutCapsChannelManagerIface *iface =
     SALUT_CAPS_CHANNEL_MANAGER_GET_INTERFACE (caps_manager);
diff --git a/src/salut-caps-channel-manager.h b/src/salut-caps-channel-manager.h
index 9c7d3a1..e1e83de 100644
--- a/src/salut-caps-channel-manager.h
+++ b/src/salut-caps-channel-manager.h
@@ -68,7 +68,7 @@ typedef void (*SalutCapsChannelManagerGetFeatureListFunc) (
     GSList **features);
 
 typedef gpointer (*SalutCapsChannelManagerParseCapsFunc) (
-    SalutCapsChannelManager *manager, GibberXmppStanza *children);
+    SalutCapsChannelManager *manager, GibberXmppNode *children);
 
 typedef void (*SalutCapsChannelManagerFreeCapsFunc) (
     SalutCapsChannelManager *manager, gpointer specific_caps);
@@ -95,7 +95,7 @@ void salut_caps_channel_manager_get_feature_list (
     GSList **features);
 
 gpointer salut_caps_channel_manager_parse_capabilities (
-    SalutCapsChannelManager *manager, GibberXmppStanza *children);
+    SalutCapsChannelManager *manager, GibberXmppNode *children);
 
 void salut_caps_channel_manager_free_capabilities (SalutCapsChannelManager *manager,
     gpointer specific_caps);
diff --git a/src/salut-caps-hash.c b/src/salut-caps-hash.c
index da5b754..3447936 100644
--- a/src/salut-caps-hash.c
+++ b/src/salut-caps-hash.c
@@ -421,9 +421,8 @@ _parse_caps_item (GibberXmppNode *node, gpointer user_data)
  * Returns: the hash. The called must free the returned hash with g_free().
  */
 gchar *
-caps_hash_compute_from_stanza (GibberXmppStanza *stanza)
+caps_hash_compute_from_stanza (GibberXmppNode *node)
 {
-  GibberXmppNode *node = stanza->node;
   gchar *str;
   AllCapsData *caps_data;
 
diff --git a/src/salut-caps-hash.h b/src/salut-caps-hash.h
index 0bf5371..26be023 100644
--- a/src/salut-caps-hash.h
+++ b/src/salut-caps-hash.h
@@ -26,7 +26,7 @@
 
 #include <gibber/gibber-xmpp-stanza.h>
 
-gchar *caps_hash_compute_from_stanza (GibberXmppStanza *stanza);
+gchar *caps_hash_compute_from_stanza (GibberXmppNode *node);
 gchar *caps_hash_compute_from_self_presence (SalutSelf *self);
 
 #endif /* __SALUT_CAPS_HASH_H__ */
diff --git a/src/salut-connection.c b/src/salut-connection.c
index 1be7fb3..07872c1 100644
--- a/src/salut-connection.c
+++ b/src/salut-connection.c
@@ -17,7 +17,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#define DBUS_API_SUBJECT_TO_CHANGE
+#include "salut-connection.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -44,7 +44,7 @@
 #include "salut-avahi-discovery-client.h"
 #include "salut-caps-channel-manager.h"
 #include "salut-caps-hash.h"
-#include "salut-connection.h"
+#include "salut-capabilities.h"
 #include "salut-contact-channel.h"
 #include "salut-contact.h"
 #include "salut-contact-manager.h"
@@ -263,6 +263,183 @@ static void connection_capabilities_update_cb (SalutPresenceCache *cache,
     TpHandle handle, GHashTable *old_enhanced_caps,
     GHashTable *new_enhanced_caps, gpointer user_data);
 
+static gboolean
+caps_req_stanza_filter (SalutXmppConnectionManager *mgr,
+                        GibberXmppConnection *conn,
+                        GibberXmppStanza *stanza,
+                        SalutContact *contact,
+                        gpointer user_data)
+{
+  GibberStanzaSubType sub_type;
+  GibberXmppNode *query;
+
+  gibber_xmpp_stanza_get_type_info (stanza, NULL, &sub_type);
+
+  if (sub_type != GIBBER_STANZA_SUB_TYPE_GET)
+    return FALSE;
+
+  query = gibber_xmpp_node_get_child_ns (stanza->node, "query", NS_DISCO_INFO);
+
+  if (!query)
+    return FALSE;
+
+  return TRUE;
+}
+
+static void
+caps_req_stanza_callback (SalutXmppConnectionManager *mgr,
+                          GibberXmppConnection *conn,
+                          GibberXmppStanza *stanza,
+                          SalutContact *contact,
+                          gpointer user_data)
+{
+  SalutConnection *self = SALUT_CONNECTION (user_data);
+  SalutConnectionPrivate *priv = SALUT_CONNECTION_GET_PRIVATE (self);
+  TpBaseConnection *base_conn = TP_BASE_CONNECTION (self);
+  GibberXmppNode *iq, *result_iq, *query, *result_query;
+  const gchar *node;
+  const gchar *suffix;
+  GSList *i;
+  gchar *caps_hash;
+  TpHandleRepoIface *contact_repo;
+  const gchar *jid_from, *jid_to;
+
+  contact_repo = tp_base_connection_get_handles (base_conn,
+      TP_HANDLE_TYPE_CONTACT);
+  jid_from = tp_handle_inspect (contact_repo, base_conn->self_handle);
+  jid_to = tp_handle_inspect (contact_repo, contact->handle);
+
+  iq = stanza->node;
+  query = gibber_xmpp_node_get_child_ns (iq, "query", NS_DISCO_INFO);
+
+  if (query != NULL)
+    {
+      node = gibber_xmpp_node_get_attribute (query, "node");
+      if (node != NULL)
+        {
+          if (0 != strncmp (node, GIBBER_TELEPATHY_NS_CAPS "#",
+                strlen (GIBBER_TELEPATHY_NS_CAPS) + 1))
+            suffix = "";
+          else if (strlen (node) < strlen (GIBBER_TELEPATHY_NS_CAPS) + 2)
+            suffix = "";
+          else
+            suffix = node + strlen (GIBBER_TELEPATHY_NS_CAPS) + 1;
+        }
+      else
+        {
+          node = "";
+          suffix = "";
+        }
+    }
+  else
+    {
+      node = "";
+      suffix = "";
+    }
+
+  DEBUG ("got disco request for node %s", node);
+
+  /* Salut only supports XEP-0115 version 1.5. Bundles from old version 1.3 are
+   * not implemented. */
+  caps_hash = caps_hash_compute_from_self_presence (priv->self);
+
+  if (!tp_strdiff (suffix, caps_hash))
+    {
+      GibberXmppStanza *result;
+      GSList *features = capabilities_get_features (
+          priv->self->per_channel_manager_caps);
+
+      /* Every entity MUST have at least one identity (XEP-0030). Salut publishs
+       * one identity. If you change the identity here, you also need to change
+       * caps_hash_compute_from_self_presence(). */
+      result = gibber_xmpp_stanza_build (GIBBER_STANZA_TYPE_IQ,
+          GIBBER_STANZA_SUB_TYPE_RESULT,
+          jid_from, jid_to,
+          GIBBER_NODE, "query",
+            GIBBER_NODE_XMLNS, NS_DISCO_INFO,
+            GIBBER_NODE_ATTRIBUTE, "node", node,
+            GIBBER_NODE, "identity",
+              GIBBER_NODE_ATTRIBUTE, "category", "client",
+              GIBBER_NODE_ATTRIBUTE, "name", PACKAGE_STRING,
+              GIBBER_NODE_ATTRIBUTE, "type", "pc",
+            GIBBER_NODE_END,
+          GIBBER_NODE_END,
+          GIBBER_STANZA_END);
+
+      result_iq = result->node;
+      result_query = gibber_xmpp_node_get_child_ns (result_iq, "query", NULL);
+
+
+      for (i = features; NULL != i; i = i->next)
+        {
+          const Feature *feature = (const Feature *) i->data;
+          GibberXmppNode *feature_node;
+
+          feature_node = gibber_xmpp_node_add_child (result_query, "feature");
+          gibber_xmpp_node_set_attribute (feature_node, "var", feature->ns);
+        }
+      g_slist_free (features);
+
+      DEBUG ("sending disco response");
+
+      if (!gibber_xmpp_connection_send (conn, result, NULL))
+        {
+          DEBUG ("sending disco response failed");
+        }
+
+      g_object_unref (result);
+    }
+  else
+    {
+      GibberXmppStanza *result;
+
+      /* Return <item-not-found>. It is possible that the remote contact
+       * requested an old version (old hash) of our capabilities. In the
+       * meantime, it will have gotten a new hash, and query the new hash
+       * anyway. */
+      result = gibber_xmpp_stanza_build (GIBBER_STANZA_TYPE_IQ,
+          GIBBER_STANZA_SUB_TYPE_ERROR,
+          jid_from, jid_to,
+          GIBBER_NODE, "query",
+            GIBBER_NODE_XMLNS, NS_DISCO_INFO,
+            GIBBER_NODE_ATTRIBUTE, "node", node,
+            GIBBER_NODE, "error",
+              GIBBER_NODE_ATTRIBUTE, "type", "cancel",
+              GIBBER_NODE, "item-not-found",
+                GIBBER_NODE_XMLNS, GIBBER_XMPP_NS_STANZAS,
+              GIBBER_NODE_END,
+            GIBBER_NODE_END,
+          GIBBER_NODE_END,
+          GIBBER_STANZA_END);
+
+      DEBUG ("sending item-not-found as disco response");
+
+      if (!gibber_xmpp_connection_send (conn, result, NULL))
+        {
+          DEBUG ("sending item-not-found failed");
+        }
+
+      g_object_unref (result);
+    }
+  g_free (caps_hash);
+}
+
+
+static void
+xmpp_connection_manager_new_connection_cb (SalutXmppConnectionManager *mgr,
+                                           GibberXmppConnection *conn,
+                                           SalutContact *contact,
+                                           gpointer user_data)
+{
+  SalutConnection *self = SALUT_CONNECTION (user_data);
+  SalutConnectionPrivate *priv = SALUT_CONNECTION_GET_PRIVATE (self);
+
+  salut_xmpp_connection_manager_add_stanza_filter (
+      priv->xmpp_connection_manager, conn,
+      caps_req_stanza_filter, caps_req_stanza_callback, self);
+}
+
+
 static void
 salut_connection_init (SalutConnection *obj)
 {
@@ -306,8 +483,12 @@ salut_connection_constructor (GType type,
   obj = G_OBJECT_CLASS (salut_connection_parent_class)->
            constructor (type, n_props, props);
   self = SALUT_CONNECTION (obj);
+  SalutConnectionPrivate *priv = SALUT_CONNECTION_GET_PRIVATE(self);
 
-  self->disco = salut_disco_new (self);
+  g_signal_connect (priv->xmpp_connection_manager, "new-connection",
+      G_CALLBACK (xmpp_connection_manager_new_connection_cb), obj);
+
+  self->disco = salut_disco_new (self, priv->xmpp_connection_manager);
   self->presence_cache = salut_presence_cache_new (self);
   g_signal_connect (self->presence_cache, "capabilities-update", G_CALLBACK
       (connection_capabilities_update_cb), self);
@@ -840,6 +1021,9 @@ salut_connection_dispose (GObject *object)
 
   if (priv->xmpp_connection_manager)
     {
+      g_signal_handlers_disconnect_matched (priv->xmpp_connection_manager,
+          G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
+
       g_object_unref (priv->xmpp_connection_manager);
       priv->xmpp_connection_manager = NULL;
     }
@@ -1814,6 +1998,8 @@ connection_capabilities_update_cb (SalutPresenceCache *cache,
 {
   SalutConnection *conn = SALUT_CONNECTION (user_data);
 
+  g_assert (SALUT_IS_CONNECTION (user_data));
+
   if (old_enhanced_caps != NULL || new_enhanced_caps != NULL)
     _emit_contact_capabilities_changed (conn, handle,
         old_enhanced_caps, new_enhanced_caps);
diff --git a/src/salut-disco.c b/src/salut-disco.c
index ec3d7f6..474323d 100644
--- a/src/salut-disco.c
+++ b/src/salut-disco.c
@@ -26,17 +26,17 @@
 
 #include <string.h>
 
-#define DBUS_API_SUBJECT_TO_CHANGE
-
 #include <dbus/dbus-glib.h>
 #include <dbus/dbus-glib-lowlevel.h>
 #include <telepathy-glib/dbus.h>
+#include <gibber/gibber-iq-helper.h>
 #include <gibber/gibber-namespaces.h>
 
 #define DEBUG_FLAG DEBUG_DISCO
 
 #include "debug.h"
 #include "salut-connection.h"
+#include "salut-xmpp-connection-manager.h"
 #include "signals-marshal.h"
 
 #define DEFAULT_REQUEST_TIMEOUT 20000
@@ -54,6 +54,7 @@ static guint signals[LAST_SIGNAL] = {0};
 enum
 {
   PROP_CONNECTION = 1,
+  PROP_XMPP_CONNECTION_MANAGER,
   LAST_PROPERTY
 };
 
@@ -62,6 +63,9 @@ G_DEFINE_TYPE(SalutDisco, salut_disco, G_TYPE_OBJECT);
 struct _SalutDiscoPrivate
 {
   SalutConnection *connection;
+  SalutXmppConnectionManager *xmpp_connection_manager;
+
+  /* list of SalutDiscoRequest* */
   GList *requests;
   gboolean dispose_has_run;
 };
@@ -69,11 +73,19 @@ struct _SalutDiscoPrivate
 struct _SalutDiscoRequest
 {
   SalutDisco *disco;
-  guint timer_id;
 
+  /* The request cannot be sent immediately, we have to wait the
+   * XmppConnection to be established. Meanwhile, requested=FALSE. */
+  gboolean requested;
+
+  GibberIqHelper *iq_helper;
+  guint timer_id;
   SalutDiscoType type;
   SalutContact *contact;
+
+  /* uri as in XEP-0115 */
   gchar *node;
+
   SalutDiscoCb callback;
   gpointer user_data;
   GObject *bound_object;
@@ -107,6 +119,179 @@ static void salut_disco_get_property (GObject *object, guint property_id,
 static void salut_disco_dispose (GObject *object);
 static void salut_disco_finalize (GObject *object);
 
+static const char *
+disco_type_to_xmlns (SalutDiscoType type)
+{
+  switch (type) {
+    case SALUT_DISCO_TYPE_INFO:
+      return NS_DISCO_INFO;
+    case SALUT_DISCO_TYPE_ITEMS:
+      return NS_DISCO_ITEMS;
+    default:
+      g_assert_not_reached ();
+  }
+
+  return NULL;
+}
+
+static void notify_delete_request (gpointer data, GObject *obj);
+
+static void
+delete_request (SalutDiscoRequest *request)
+{
+  SalutDisco *disco = request->disco;
+  SalutDiscoPrivate *priv;
+
+  g_assert (NULL != request);
+  g_assert (SALUT_IS_DISCO (disco));
+
+  priv = SALUT_DISCO_GET_PRIVATE (disco);
+
+  g_assert (NULL != g_list_find (priv->requests, request));
+
+  priv->requests = g_list_remove (priv->requests, request);
+
+  if (NULL != request->bound_object)
+    {
+      g_object_weak_unref (request->bound_object, notify_delete_request,
+          request);
+    }
+
+  if (0 != request->timer_id)
+    {
+      g_source_remove (request->timer_id);
+    }
+
+  g_object_unref (request->contact);
+  g_free (request->node);
+  g_slice_free (SalutDiscoRequest, request);
+}
+
+static void
+notify_delete_request (gpointer data, GObject *obj)
+{
+  SalutDiscoRequest *request = (SalutDiscoRequest *) data;
+  request->bound_object = NULL;
+  delete_request (request);
+}
+
+static void
+request_reply_cb (GibberIqHelper *helper,
+                  GibberXmppStanza *sent_stanza,
+                  GibberXmppStanza *reply_stanza,
+                  GObject *object,
+                  gpointer user_data)
+{
+  SalutDiscoRequest *request = (SalutDiscoRequest *) user_data;
+  SalutDisco *disco = SALUT_DISCO (object);
+  SalutDiscoPrivate *priv = SALUT_DISCO_GET_PRIVATE (disco);
+  GibberXmppNode *query_node;
+  GError *err = NULL;
+  GibberStanzaSubType sub_type;
+
+  g_assert (request);
+
+  if (!g_list_find (priv->requests, request))
+    return;
+
+  query_node = gibber_xmpp_node_get_child_ns (reply_stanza->node,
+      "query", disco_type_to_xmlns (request->type));
+
+  gibber_xmpp_stanza_get_type_info (reply_stanza, NULL, &sub_type);
+
+  if (sub_type == GIBBER_STANZA_SUB_TYPE_ERROR)
+    {
+      err = gibber_message_get_xmpp_error (reply_stanza);
+
+      if (err == NULL)
+        {
+          err = g_error_new (SALUT_DISCO_ERROR,
+                             SALUT_DISCO_ERROR_UNKNOWN,
+                             "an unknown error occurred");
+        }
+    }
+  else if (NULL == query_node)
+    {
+      err = g_error_new (SALUT_DISCO_ERROR, SALUT_DISCO_ERROR_UNKNOWN,
+          "disco response contained no <query> node");
+    }
+
+  request->callback (request->disco, request, request->contact, request->node,
+                     query_node, err, request->user_data);
+  delete_request (request);
+
+  if (err)
+    g_error_free (err);
+
+  return;
+}
+
+static void
+send_disco_request (SalutDisco *self,
+                    GibberXmppConnection *conn,
+                    SalutContact *contact,
+                    SalutDiscoRequest *request)
+{
+  SalutDiscoPrivate *priv = SALUT_DISCO_GET_PRIVATE (self);
+  TpBaseConnection *base_conn = TP_BASE_CONNECTION (priv->connection);
+  GibberXmppStanza *stanza;
+  TpHandleRepoIface *contact_repo;
+  const gchar *jid_from, *jid_to;
+  GError *error;
+
+  contact_repo = tp_base_connection_get_handles (
+      (TpBaseConnection*) priv->connection, TP_HANDLE_TYPE_CONTACT);
+
+  jid_from = tp_handle_inspect (contact_repo, base_conn->self_handle);
+  jid_to = tp_handle_inspect (contact_repo, contact->handle);
+
+  stanza = gibber_xmpp_stanza_build (GIBBER_STANZA_TYPE_IQ,
+      GIBBER_STANZA_SUB_TYPE_SET,
+      jid_from, jid_to,
+      GIBBER_NODE, "query",
+        GIBBER_NODE_XMLNS, disco_type_to_xmlns (request->type),
+        GIBBER_NODE_ATTRIBUTE, "node", request->node,
+      GIBBER_NODE_END,
+      GIBBER_STANZA_END);
+
+  request->requested = TRUE;
+
+  request->iq_helper = gibber_iq_helper_new (conn);
+  g_assert (request->iq_helper);
+
+  if (!gibber_iq_helper_send_with_reply (request->iq_helper, stanza,
+      request_reply_cb, G_OBJECT(self), request, &error))
+    {
+      DEBUG ("Failed to send caps request: '%s'", error->message);
+      g_error_free (error);
+    }
+
+  g_object_unref (stanza);
+}
+
+static void
+xmpp_connection_manager_new_connection_cb (SalutXmppConnectionManager *mgr,
+                                           GibberXmppConnection *conn,
+                                           SalutContact *contact,
+                                           gpointer user_data)
+{
+  SalutDisco *self = SALUT_DISCO (user_data);
+  SalutDiscoPrivate *priv = SALUT_DISCO_GET_PRIVATE (self);
+  GList *req = priv->requests;
+
+  /* send all pending requests on this connection */
+  while (req != NULL)
+    {
+      SalutDiscoRequest *request = req->data;
+
+      if (request->contact == contact && !request->requested)
+        {
+          send_disco_request (self, conn, contact, request);
+        }
+      req = g_list_next (req);
+    }
+}
+
 static void
 salut_disco_class_init (SalutDiscoClass *salut_disco_class)
 {
@@ -133,6 +318,18 @@ salut_disco_class_init (SalutDiscoClass *salut_disco_class)
                                     G_PARAM_STATIC_BLURB);
   g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
 
+  param_spec = g_param_spec_object (
+      "xmpp-connection-manager",
+      "SalutXmppConnectionManager object",
+      "Salut XMPP Connection manager used for disco to send caps requests",
+      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[ITEM_FOUND] =
     g_signal_new ("item-found",
                   G_OBJECT_CLASS_TYPE (salut_disco_class),
@@ -152,14 +349,18 @@ salut_disco_get_property (GObject    *object,
   SalutDisco *chan = SALUT_DISCO (object);
   SalutDiscoPrivate *priv = SALUT_DISCO_GET_PRIVATE (chan);
 
-  switch (property_id) {
-    case PROP_CONNECTION:
-      g_value_set_object (value, priv->connection);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-      break;
-  }
+  switch (property_id)
+    {
+      case PROP_CONNECTION:
+        g_value_set_object (value, priv->connection);
+        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;
+    }
 }
 
 static void
@@ -171,14 +372,19 @@ salut_disco_set_property (GObject     *object,
   SalutDisco *chan = SALUT_DISCO (object);
   SalutDiscoPrivate *priv = SALUT_DISCO_GET_PRIVATE (chan);
 
-  switch (property_id) {
-    case PROP_CONNECTION:
-      priv->connection = g_value_get_object (value);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-      break;
-  }
+  switch (property_id)
+    {
+      case PROP_CONNECTION:
+        priv->connection = g_value_get_object (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;
+    }
 }
 
 static GObject *
@@ -194,6 +400,9 @@ salut_disco_constructor (GType type, guint n_props,
   disco = SALUT_DISCO (obj);
   priv = SALUT_DISCO_GET_PRIVATE (disco);
 
+  g_signal_connect (priv->xmpp_connection_manager, "new-connection",
+      G_CALLBACK (xmpp_connection_manager_new_connection_cb), obj);
+
   return obj;
 }
 
@@ -212,6 +421,15 @@ salut_disco_dispose (GObject *object)
 
   DEBUG ("dispose called");
 
+  if (priv->xmpp_connection_manager != NULL)
+    {
+      g_signal_handlers_disconnect_matched (priv->xmpp_connection_manager,
+          G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
+
+      g_object_unref (priv->xmpp_connection_manager);
+      priv->xmpp_connection_manager = NULL;
+    }
+
   /* cancel request removes the element from the list after cancelling */
   while (priv->requests)
     cancel_request (priv->requests->data);
@@ -236,53 +454,22 @@ salut_disco_finalize (GObject *object)
  * There should be one of these per connection
  */
 SalutDisco *
-salut_disco_new (SalutConnection *conn)
+salut_disco_new (SalutConnection *connection, 
+                 SalutXmppConnectionManager *xmpp_connection_manager)
 {
   SalutDisco *disco;
 
-  g_return_val_if_fail (SALUT_IS_CONNECTION (conn), NULL);
+  g_return_val_if_fail (SALUT_IS_CONNECTION (connection), NULL);
 
   disco = SALUT_DISCO (g_object_new (SALUT_TYPE_DISCO,
-        "connection", conn,
+        "connection", connection,
+        "xmpp-connection-manager", xmpp_connection_manager,
         NULL));
 
   return disco;
 }
 
 
-static void notify_delete_request (gpointer data, GObject *obj);
-
-static void
-delete_request (SalutDiscoRequest *request)
-{
-  SalutDisco *disco = request->disco;
-  SalutDiscoPrivate *priv;
-
-  g_assert (NULL != request);
-  g_assert (SALUT_IS_DISCO (disco));
-
-  priv = SALUT_DISCO_GET_PRIVATE (disco);
-
-  g_assert (NULL != g_list_find (priv->requests, request));
-
-  priv->requests = g_list_remove (priv->requests, request);
-
-  if (NULL != request->bound_object)
-    {
-      g_object_weak_unref (request->bound_object, notify_delete_request,
-          request);
-    }
-
-  if (0 != request->timer_id)
-    {
-      g_source_remove (request->timer_id);
-    }
-
-  g_object_unref (request->contact);
-  g_free (request->node);
-  g_slice_free (SalutDiscoRequest, request);
-}
-
 //static gboolean
 //timeout_request (gpointer data)
 //{
@@ -339,76 +526,6 @@ cancel_request (SalutDiscoRequest *request)
   delete_request (request);
 }
 
-/*
-static const char *
-disco_type_to_xmlns (SalutDiscoType type)
-{
-  switch (type) {
-    case SALUT_DISCO_TYPE_INFO:
-      return NS_DISCO_INFO;
-    case SALUT_DISCO_TYPE_ITEMS:
-      return NS_DISCO_ITEMS;
-    default:
-      g_assert_not_reached ();
-  }
-
-  return NULL;
-}
-
-static LmHandlerResult
-request_reply_cb (SalutConnection *conn, LmMessage *sent_msg,
-                  LmMessage *reply_msg, GObject *object, gpointer user_data)
-{
-  SalutDiscoRequest *request = (SalutDiscoRequest *) user_data;
-  SalutDisco *disco = SALUT_DISCO (object);
-  SalutDiscoPrivate *priv = SALUT_DISCO_GET_PRIVATE (disco);
-  LmMessageNode *query_node;
-  GError *err = NULL;
-
-  g_assert (request);
-
-  if (!g_list_find (priv->requests, request))
-    return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-
-  query_node = lm_message_node_get_child_with_namespace (reply_msg->node,
-      "query", disco_type_to_xmlns (request->type));
-
-  if (lm_message_get_sub_type (reply_msg) == LM_MESSAGE_SUB_TYPE_ERROR)
-    {
-      err = salut_message_get_xmpp_error (reply_msg);
-
-      if (err == NULL)
-        {
-          err = g_error_new (SALUT_DISCO_ERROR,
-                             SALUT_DISCO_ERROR_UNKNOWN,
-                             "an unknown error occurred");
-        }
-    }
-  else if (NULL == query_node)
-    {
-      err = g_error_new (SALUT_DISCO_ERROR, SALUT_DISCO_ERROR_UNKNOWN,
-          "disco response contained no <query> node");
-    }
-
-  request->callback (request->disco, request, request->jid, request->node,
-                     query_node, err, request->user_data);
-  delete_request (request);
-
-  if (err)
-    g_error_free (err);
-
-  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
-}
-*/
-
-static void
-notify_delete_request (gpointer data, GObject *obj)
-{
-  SalutDiscoRequest *request = (SalutDiscoRequest *) data;
-  request->bound_object = NULL;
-  delete_request (request);
-}
-
 /**
  * salut_disco_request:
  * @self: #SalutDisco object to use for request
@@ -433,11 +550,15 @@ salut_disco_request (SalutDisco *self, SalutDiscoType type,
 {
   SalutDiscoPrivate *priv = SALUT_DISCO_GET_PRIVATE (self);
   SalutDiscoRequest *request;
-  //LmMessage *msg;
-  //LmMessageNode *lm_node;
+  SalutXmppConnectionManagerRequestConnectionResult result;
+  GibberXmppConnection *conn = NULL;
+
+  g_assert (node != NULL);
+  g_assert (strlen (node) > 0);
 
   request = g_slice_new0 (SalutDiscoRequest);
   request->disco = self;
+  request->requested = FALSE;
   request->type = type;
   request->contact = g_object_ref (contact);
   if (node)
@@ -453,34 +574,27 @@ salut_disco_request (SalutDisco *self, SalutDiscoType type,
            request, request->contact->name);
 
   priv->requests = g_list_prepend (priv->requests, request);
-  /*
-  msg = lm_message_new_with_sub_type (jid, LM_MESSAGE_TYPE_IQ,
-                                           LM_MESSAGE_SUB_TYPE_GET);
-  lm_node = lm_message_node_add_child (msg->node, "query", NULL);
 
-  lm_message_node_set_attribute (lm_node, "xmlns", disco_type_to_xmlns (type));
+  result = salut_xmpp_connection_manager_request_connection (
+      priv->xmpp_connection_manager, contact, &conn, NULL);
 
-  if (node)
+  if (result == SALUT_XMPP_CONNECTION_MANAGER_REQUEST_CONNECTION_RESULT_DONE)
     {
-      lm_message_node_set_attribute (lm_node, "node", node);
+      DEBUG ("connection done.");
+      send_disco_request (self, conn, contact, request);
+      return request;
     }
-
-  if (! _salut_connection_send_with_reply (priv->connection, msg,
-        request_reply_cb, G_OBJECT(self), request, error))
+  else if (result ==
+      SALUT_XMPP_CONNECTION_MANAGER_REQUEST_CONNECTION_RESULT_PENDING)
     {
-      delete_request (request);
-      lm_message_unref (msg);
-      return NULL;
+      DEBUG ("Requested connection pending");
+      return request;
     }
   else
     {
-      request->timer_id =
-          g_timeout_add (DEFAULT_REQUEST_TIMEOUT, timeout_request, request);
-      lm_message_unref (msg);
-      return request;
+      delete_request (request);
+      return NULL;
     }
-*/
-/**/ return NULL;
 }
 
 void
diff --git a/src/salut-disco.h b/src/salut-disco.h
index 0c22272..e43f48c 100644
--- a/src/salut-disco.h
+++ b/src/salut-disco.h
@@ -26,9 +26,11 @@
 
 #include <glib-object.h>
 #include <gibber/gibber-xmpp-stanza.h>
+#include <gibber/gibber-xmpp-node.h>
 
 #include "salut-contact.h"
 #include "salut-connection.h"
+#include "salut-xmpp-connection-manager.h"
 
 G_BEGIN_DECLS
 
@@ -84,10 +86,11 @@ struct _SalutDisco {
 };
 
 typedef void (*SalutDiscoCb)(SalutDisco *self, SalutDiscoRequest *request,
-    SalutContact *contact, const gchar *node, GibberXmppStanza *query_result,
+    SalutContact *contact, const gchar *node, GibberXmppNode *query_result,
     GError* error, gpointer user_data);
 
-SalutDisco *salut_disco_new (SalutConnection *);
+SalutDisco *salut_disco_new (SalutConnection *connection,
+    SalutXmppConnectionManager *xmpp_connection_manager);
 
 SalutDiscoRequest *salut_disco_request (SalutDisco *self,
     SalutDiscoType type, SalutContact *contact, const char *node,
diff --git a/src/salut-presence-cache.c b/src/salut-presence-cache.c
index cf87b32..80e5f18 100644
--- a/src/salut-presence-cache.c
+++ b/src/salut-presence-cache.c
@@ -55,7 +55,7 @@ enum
 
 static guint signals[LAST_SIGNAL] = { 0 };
 
-#define SALUT_PRESENCE_CACHE_PRIV(account) ((account)->priv)
+#define SALUT_PRESENCE_CACHE_PRIV(cache) ((cache)->priv)
 
 struct _SalutPresenceCachePrivate
 {
@@ -252,8 +252,8 @@ salut_presence_cache_class_init (SalutPresenceCacheClass *klass)
     G_SIGNAL_RUN_LAST,
     0,
     NULL, NULL,
-    salut_signals_marshal_VOID__UINT_UINT_UINT_POINTER_POINTER, G_TYPE_NONE,
-    5, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_POINTER, G_TYPE_POINTER);
+    salut_signals_marshal_VOID__POINTER_POINTER_POINTER, G_TYPE_NONE,
+    3, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER);
 }
 
 static void
@@ -276,11 +276,9 @@ salut_presence_cache_constructor (GType type, guint n_props,
                                    GObjectConstructParam *props)
 {
   GObject *obj;
-  SalutPresenceCachePrivate *priv;
 
   obj = G_OBJECT_CLASS (salut_presence_cache_parent_class)->
            constructor (type, n_props, props);
-  priv = SALUT_PRESENCE_CACHE_PRIV (SALUT_PRESENCE_CACHE (obj));
 
   return obj;
 }
@@ -325,14 +323,15 @@ salut_presence_cache_get_property (GObject    *object,
   SalutPresenceCache *cache = SALUT_PRESENCE_CACHE (object);
   SalutPresenceCachePrivate *priv = SALUT_PRESENCE_CACHE_PRIV (cache);
 
-  switch (property_id) {
-    case PROP_CONNECTION:
-      g_value_set_object (value, priv->conn);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-      break;
-  }
+  switch (property_id)
+    {
+      case PROP_CONNECTION:
+        g_value_set_object (value, priv->conn);
+        break;
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
 }
 
 static void
@@ -344,14 +343,15 @@ salut_presence_cache_set_property (GObject     *object,
   SalutPresenceCache *cache = SALUT_PRESENCE_CACHE (object);
   SalutPresenceCachePrivate *priv = SALUT_PRESENCE_CACHE_PRIV (cache);
 
-  switch (property_id) {
-    case PROP_CONNECTION:
-      priv->conn = g_value_get_object (value);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-      break;
-  }
+  switch (property_id)
+    {
+      case PROP_CONNECTION:
+        priv->conn = g_value_get_object (value);
+        break;
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
 }
 
 static void
@@ -359,7 +359,7 @@ _caps_disco_cb (SalutDisco *disco,
                 SalutDiscoRequest *request,
                 SalutContact *contact,
                 const gchar *node,
-                GibberXmppStanza *query_result,
+                GibberXmppNode *query_result,
                 GError *error,
                 gpointer user_data)
 {
@@ -640,10 +640,10 @@ salut_presence_cache_process_caps (SalutPresenceCache *self,
 }
 
 SalutPresenceCache *
-salut_presence_cache_new (SalutConnection *conn)
+salut_presence_cache_new (SalutConnection *connection)
 {
   return g_object_new (SALUT_TYPE_PRESENCE_CACHE,
-                       "connection", conn,
+                       "connection", connection,
                        NULL);
 }
 
diff --git a/src/salut-presence-cache.h b/src/salut-presence-cache.h
index 594b59c..5d0881f 100644
--- a/src/salut-presence-cache.h
+++ b/src/salut-presence-cache.h
@@ -26,6 +26,7 @@
 
 #include "salut-connection.h"
 #include "salut-contact.h"
+#include "salut-xmpp-connection-manager.h"
 
 G_BEGIN_DECLS
 
@@ -67,7 +68,7 @@ struct _SalutPresenceCacheClass {
 
 GType salut_presence_cache_get_type (void);
 
-SalutPresenceCache *salut_presence_cache_new (SalutConnection *conn);
+SalutPresenceCache *salut_presence_cache_new (SalutConnection *connection);
 
 void salut_presence_cache_process_caps (SalutPresenceCache *self,
     SalutContact *contact, const gchar *hash, const gchar *node,
diff --git a/src/salut-tubes-channel.c b/src/salut-tubes-channel.c
index 09f44ed..06cca41 100644
--- a/src/salut-tubes-channel.c
+++ b/src/salut-tubes-channel.c
@@ -2370,6 +2370,7 @@ salut_tubes_channel_class_init (
       G_PARAM_STATIC_BLURB);
   g_object_class_install_property (object_class, PROP_XMPP_CONNECTION_MANAGER,
       param_spec);
+
   param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces",
       "Additional Channel.Interface.* interfaces",
       G_TYPE_STRV,
-- 
1.5.6.5




More information about the telepathy-commits mailing list