diff options
author | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2013-05-30 16:38:35 +0100 |
---|---|---|
committer | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2013-05-30 20:33:34 +0100 |
commit | 0561059639160cbd11e1764ef861348c0c23831c (patch) | |
tree | 4cd286e12520400791a9e5bb05ff31ebd104ab3f | |
parent | b7a89063d05ccdd361d309b8d9df845f186102d6 (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.c | 2 | ||||
-rw-r--r-- | wocky/wocky-jingle-session.c | 73 | ||||
-rw-r--r-- | wocky/wocky-jingle-session.h | 3 |
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__ */ |