[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