summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/jingle-factory.c42
-rw-r--r--src/jingle-mint.c37
2 files changed, 60 insertions, 19 deletions
diff --git a/src/jingle-factory.c b/src/jingle-factory.c
index ff815fdca..0edd2b3d8 100644
--- a/src/jingle-factory.c
+++ b/src/jingle-factory.c
@@ -39,7 +39,6 @@
#include "jingle-transport-rawudp.h"
#include "jingle-transport-iceudp.h"
#include "namespaces.h"
-#include "presence-cache.h"
#include "util.h"
#include "google-relay.h"
@@ -50,6 +49,7 @@ G_DEFINE_TYPE(GabbleJingleFactory, gabble_jingle_factory, G_TYPE_OBJECT);
enum
{
NEW_SESSION,
+ QUERY_CAP,
LAST_SIGNAL
};
@@ -235,6 +235,20 @@ gabble_jingle_factory_class_init (GabbleJingleFactoryClass *cls)
G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST,
0, NULL, NULL, gabble_marshal_VOID__OBJECT_BOOL,
G_TYPE_NONE, 2, GABBLE_TYPE_JINGLE_SESSION, G_TYPE_BOOLEAN);
+
+ /*
+ * @contact: the peer in a call
+ * @cap: the XEP-0115 feature string the session is interested in.
+ *
+ * Emitted when a Jingle session wants to check whether the peer has a
+ * particular capability. The handler should return %TRUE if @contact has
+ * @cap.
+ */
+ signals[QUERY_CAP] = g_signal_new ("query-cap",
+ G_TYPE_FROM_CLASS (cls), G_SIGNAL_RUN_LAST,
+ 0, g_signal_accumulator_first_wins, NULL,
+ gabble_marshal_BOOLEAN__OBJECT_STRING,
+ G_TYPE_BOOLEAN, 2, WOCKY_TYPE_CONTACT, G_TYPE_STRING);
}
GabbleJingleFactory *
@@ -430,25 +444,15 @@ session_query_cap_cb (
gpointer user_data)
{
GabbleJingleFactory *self = GABBLE_JINGLE_FACTORY (user_data);
- GabbleJingleFactoryPrivate *priv = self->priv;
- GabblePresence *presence = gabble_presence_cache_get_for_contact (
- priv->conn->presence_cache, contact);
-
- if (presence == NULL)
- return FALSE;
+ gboolean ret;
- if (WOCKY_IS_RESOURCE_CONTACT (contact))
- {
- const gchar *peer_resource = wocky_resource_contact_get_resource (
- WOCKY_RESOURCE_CONTACT (contact));
-
- return gabble_presence_resource_has_caps (presence, peer_resource,
- gabble_capability_set_predicate_has, cap_or_quirk);
- }
- else
- {
- return gabble_presence_has_cap (presence, cap_or_quirk);
- }
+ /* Propagate the query out to the application. We can't depend on the
+ * application connecting to ::query-cap on the session because caps queries
+ * may happen while parsing the session-initiate stanza, which must happen
+ * before the session is announced to the application.
+ */
+ g_signal_emit (self, signals[QUERY_CAP], 0, contact, cap_or_quirk, &ret);
+ return ret;
}
/*
diff --git a/src/jingle-mint.c b/src/jingle-mint.c
index b990f0eda..1bda393c9 100644
--- a/src/jingle-mint.c
+++ b/src/jingle-mint.c
@@ -33,6 +33,7 @@
#include "conn-presence.h"
#include "jingle-factory.h"
#include "jingle-session.h"
+#include "presence-cache.h"
struct _GabbleJingleMintPrivate {
GabbleConnection *conn;
@@ -62,6 +63,11 @@ static void factory_new_session_cb (
GabbleJingleSession *session,
gboolean initiated_locally,
gpointer user_data);
+static gboolean factory_query_cap_cb (
+ GabbleJingleFactory *factory,
+ WockyContact *contact,
+ const gchar *cap_or_quirk,
+ gpointer user_data);
G_DEFINE_TYPE (GabbleJingleMint, gabble_jingle_mint, G_TYPE_OBJECT)
@@ -130,6 +136,8 @@ gabble_jingle_mint_constructed (GObject *object)
priv->factory = gabble_jingle_factory_new (priv->conn);
tp_g_signal_connect_object (priv->factory, "new-session",
(GCallback) factory_new_session_cb, self, 0);
+ tp_g_signal_connect_object (priv->factory, "query-cap",
+ (GCallback) factory_query_cap_cb, self, 0);
}
static void
@@ -271,6 +279,35 @@ factory_new_session_cb (
g_signal_emit (self, signals[NEW_SESSION], 0, session);
}
+static gboolean
+factory_query_cap_cb (
+ GabbleJingleFactory *factory,
+ WockyContact *contact,
+ const gchar *cap_or_quirk,
+ gpointer user_data)
+{
+ GabbleJingleMint *self = GABBLE_JINGLE_MINT (user_data);
+ GabbleJingleMintPrivate *priv = self->priv;
+ GabblePresence *presence = gabble_presence_cache_get_for_contact (
+ priv->conn->presence_cache, contact);
+
+ if (presence == NULL)
+ return FALSE;
+
+ if (WOCKY_IS_RESOURCE_CONTACT (contact))
+ {
+ const gchar *peer_resource = wocky_resource_contact_get_resource (
+ WOCKY_RESOURCE_CONTACT (contact));
+
+ return gabble_presence_resource_has_caps (presence, peer_resource,
+ gabble_capability_set_predicate_has, cap_or_quirk);
+ }
+ else
+ {
+ return gabble_presence_has_cap (presence, cap_or_quirk);
+ }
+}
+
GabbleJingleFactory *
gabble_jingle_mint_get_factory (
GabbleJingleMint *self)