summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2013-05-30 16:38:35 +0100
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2013-05-30 20:33:34 +0100
commit0561059639160cbd11e1764ef861348c0c23831c (patch)
tree4cd286e12520400791a9e5bb05ff31ebd104ab3f
parentb7a89063d05ccdd361d309b8d9df845f186102d6 (diff)
Acknowledge Jingle IQs in a way that the Google webmail client likes
The Google webmail client currently starts calls like this: <iq type="set" ...> <jingle xmlns="urn:xmpp:jingle:1'" action="session-initiate" ...>...</jingle> <session xmlns="http://www.google.com/session" type="initiate" ...>...</session> </iq> (This isn't valid XMPP Core, because 'An IQ stanza of type "get" or "set" MUST contain exactly one child element', but we can tolerate it.) When called, it also echoes the contents of the sender's IQ back to the sender. It appears that this is how, when it makes an outgoing call, it determines which dialect the recipient wants to use: the recipient echoes the appropriate child element. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=65131 Reviewed-by: Xavier Claessens <xavier.claessens@collabora.co.uk>
-rw-r--r--wocky/wocky-jingle-factory.c2
-rw-r--r--wocky/wocky-jingle-session.c73
-rw-r--r--wocky/wocky-jingle-session.h3
3 files changed, 70 insertions, 8 deletions
diff --git a/wocky/wocky-jingle-factory.c b/wocky/wocky-jingle-factory.c
index 7d78ce6..f099df2 100644
--- a/wocky/wocky-jingle-factory.c
+++ b/wocky/wocky-jingle-factory.c
@@ -420,7 +420,7 @@ jingle_cb (
g_signal_emit (self, signals[NEW_SESSION], 0, sess, FALSE);
/* all went well, we can acknowledge the IQ */
- wocky_porter_acknowledge_iq (porter, msg, NULL);
+ wocky_jingle_session_acknowledge_iq (sess, msg);
return TRUE;
diff --git a/wocky/wocky-jingle-session.c b/wocky/wocky-jingle-session.c
index 3caa975..749a6d8 100644
--- a/wocky/wocky-jingle-session.c
+++ b/wocky/wocky-jingle-session.c
@@ -37,6 +37,7 @@
*/
#include "wocky-jingle-media-rtp.h"
#include "wocky-namespaces.h"
+#include "wocky-node-private.h"
#include "wocky-resource-contact.h"
#include "wocky-utils.h"
@@ -1566,11 +1567,12 @@ detect_google_dialect (WockyNode *session_node)
return WOCKY_JINGLE_DIALECT_GTALK4;
}
-const gchar *
-wocky_jingle_session_detect (
+static const gchar *
+wocky_jingle_session_detect_internal (
WockyStanza *stanza,
WockyJingleAction *action,
- WockyJingleDialect *dialect)
+ WockyJingleDialect *dialect,
+ WockyNode **session_node_out)
{
const gchar *actxt, *sid;
WockyNode *iq_node, *session_node;
@@ -1593,7 +1595,8 @@ wocky_jingle_session_detect (
if (session_node != NULL)
{
- *dialect = WOCKY_JINGLE_DIALECT_V032;
+ if (dialect != NULL)
+ *dialect = WOCKY_JINGLE_DIALECT_V032;
}
else
{
@@ -1602,7 +1605,8 @@ wocky_jingle_session_detect (
if (session_node != NULL)
{
- *dialect = WOCKY_JINGLE_DIALECT_V015;
+ if (dialect != NULL)
+ *dialect = WOCKY_JINGLE_DIALECT_V015;
}
else
{
@@ -1612,7 +1616,9 @@ wocky_jingle_session_detect (
if (session_node != NULL)
{
- *dialect = detect_google_dialect (session_node);
+ if (dialect != NULL)
+ *dialect = detect_google_dialect (session_node);
+
google_mode = TRUE;
}
else
@@ -1633,11 +1639,24 @@ wocky_jingle_session_detect (
sid = wocky_node_get_attribute (session_node, "sid");
}
- *action = parse_action (actxt);
+ if (session_node_out != NULL)
+ *session_node_out = session_node;
+
+ if (action != NULL)
+ *action = parse_action (actxt);
return sid;
}
+const gchar *
+wocky_jingle_session_detect (
+ WockyStanza *stanza,
+ WockyJingleAction *action,
+ WockyJingleDialect *dialect)
+{
+ return wocky_jingle_session_detect_internal (stanza, action, dialect, NULL);
+}
+
gboolean
wocky_jingle_session_parse (
WockyJingleSession *sess,
@@ -2513,3 +2532,43 @@ wocky_jingle_session_get_porter (WockyJingleSession *self)
{
return self->priv->porter;
}
+
+void
+wocky_jingle_session_acknowledge_iq (WockyJingleSession *self,
+ WockyStanza *stanza)
+{
+ if (wocky_jingle_session_peer_has_cap (self, WOCKY_QUIRK_GOOGLE_WEBMAIL_CLIENT))
+ {
+ WockyJingleAction action = WOCKY_JINGLE_ACTION_UNKNOWN;
+ WockyNode *used_node = NULL;
+
+ /* As of 2013-05-29, the Google webmail client sends a session-initiate
+ * IQ with two child nodes (which is not valid XMPP Core but never mind)
+ * and replies to session-initiate by echoing the child for the dialect
+ * it chose. We have to do the same echoing, otherwise it can't call us.
+ *
+ * It doesn't seem to reply to our other IQs at all; we still reply
+ * here (we'd be violating XMPP Core if we didn't), but we don't
+ * bother putting content in the IQ, to reduce bandwidth. */
+ if (wocky_jingle_session_detect_internal (stanza, &action, NULL,
+ &used_node) != NULL &&
+ action == WOCKY_JINGLE_ACTION_SESSION_INITIATE)
+ {
+ WockyStanza *reply = wocky_stanza_build_iq_result (stanza, NULL);
+
+ if (reply != NULL)
+ {
+ WockyNode *reply_node = wocky_stanza_get_top_node (reply);
+
+ reply_node->children = g_slist_append (reply_node->children,
+ _wocky_node_copy (used_node));
+ wocky_porter_send (self->priv->porter, reply);
+ g_object_unref (reply);
+ return;
+ }
+ }
+ }
+
+ /* normal Jingle just says "OK" without echoing */
+ wocky_porter_acknowledge_iq (self->priv->porter, stanza, NULL);
+}
diff --git a/wocky/wocky-jingle-session.h b/wocky/wocky-jingle-session.h
index 9a49a37..43c8db3 100644
--- a/wocky/wocky-jingle-session.h
+++ b/wocky/wocky-jingle-session.h
@@ -131,6 +131,9 @@ const gchar *wocky_jingle_session_get_reason_name (WockyJingleReason reason);
WockyJingleFactory *wocky_jingle_session_get_factory (WockyJingleSession *self);
WockyPorter *wocky_jingle_session_get_porter (WockyJingleSession *self);
+void wocky_jingle_session_acknowledge_iq (WockyJingleSession *self,
+ WockyStanza *stanza);
+
G_END_DECLS
#endif /* __JINGLE_SESSION_H__ */