summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Thompson <will.thompson@collabora.co.uk>2011-03-04 10:36:26 +0000
committerWill Thompson <will.thompson@collabora.co.uk>2012-01-31 17:14:46 +0000
commit43d93377facac1a7b9bae8e898c29b245ec476f5 (patch)
tree8ac997c96cf3c542324c27ce9925eb0c19a5f45d
parentd1896284653c29577b3ecb037406a9ab84a810df (diff)
C2SPorter: reply to unhandled IQ get/sets.
XMPP Core requires that we reply to all IQs we receive. If no handler claims responsibility for an incoming IQ, the porter should send back a <service-unavailable/> error. (Currently, Gabble does this.) https://bugs.freedesktop.org/show_bug.cgi?id=34975
-rw-r--r--tests/wocky-porter-test.c64
-rw-r--r--wocky/wocky-c2s-porter.c20
2 files changed, 79 insertions, 5 deletions
diff --git a/tests/wocky-porter-test.c b/tests/wocky-porter-test.c
index 7b25f09..4cd533b 100644
--- a/tests/wocky-porter-test.c
+++ b/tests/wocky-porter-test.c
@@ -2002,6 +2002,69 @@ test_handler_filter (void)
teardown_test (test);
}
+static void
+unhandled_iq_reply_cb (
+ GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ WockyPorter *porter = WOCKY_PORTER (source);
+ test_data_t *test = user_data;
+ GError *error = NULL;
+ WockyStanza *reply = wocky_porter_send_iq_finish (porter, result, &error);
+ gboolean is_error;
+ WockyXmppErrorType type;
+ GError *core = NULL;
+ GError *specialized = NULL;
+ WockyNode *specialized_node;
+
+ g_assert_no_error (error);
+ g_assert (reply != NULL);
+
+ is_error = wocky_stanza_extract_errors (reply, &type, &core, &specialized,
+ &specialized_node);
+
+ /* The reply should have type='error'. */
+ g_assert (is_error);
+
+ g_assert_cmpuint (type, ==, WOCKY_XMPP_ERROR_TYPE_CANCEL);
+ g_assert_error (core, WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_SERVICE_UNAVAILABLE);
+
+ /* There should be no non-XMPP Core error condition. */
+ g_assert_no_error (specialized);
+ g_assert (specialized_node == NULL);
+
+ g_clear_error (&core);
+ g_object_unref (reply);
+ test->outstanding--;
+ g_main_loop_quit (test->loop);
+}
+
+static void
+test_unhandled_iq (void)
+{
+ test_data_t *test = setup_test ();
+ WockyStanza *iq = wocky_stanza_build (
+ WOCKY_STANZA_TYPE_IQ, WOCKY_STANZA_SUB_TYPE_GET, NULL, NULL,
+ '(', "framed-photograph",
+ ':', "http://kimjongillookingatthings.tumblr.com",
+ ')', NULL);
+
+ test_open_both_connections (test);
+ wocky_porter_start (test->sched_out);
+ wocky_porter_start (test->sched_in);
+
+ wocky_porter_send_iq_async (test->sched_out, iq, NULL,
+ unhandled_iq_reply_cb, test);
+
+ test->outstanding++;
+ test_wait_pending (test);
+
+ g_object_unref (iq);
+ test_close_both_porters (test);
+ teardown_test (test);
+}
+
static gboolean
test_handler_filter_from_juliet_cb (WockyPorter *porter,
WockyStanza *stanza,
@@ -3494,6 +3557,7 @@ main (int argc, char **argv)
g_test_add_func ("/xmpp-porter/error-while-sending-iq",
test_error_while_sending_iq);
g_test_add_func ("/xmpp-porter/handler-filter", test_handler_filter);
+ g_test_add_func ("/xmpp-porter/unhandled-iq", test_unhandled_iq);
g_test_add_func ("/xmpp-porter/send-invalid-iq", test_send_invalid_iq);
g_test_add_func ("/xmpp-porter/handler-filter-from",
test_handler_filter_from);
diff --git a/wocky/wocky-c2s-porter.c b/wocky/wocky-c2s-porter.c
index 9f2ad30..1bd8010 100644
--- a/wocky/wocky-c2s-porter.c
+++ b/wocky/wocky-c2s-porter.c
@@ -942,6 +942,7 @@ handle_stanza (WockyC2SPorter *self,
WockyStanzaSubType sub_type;
gchar *node = NULL, *domain = NULL, *resource = NULL;
gboolean is_from_server;
+ gboolean handled = FALSE;
wocky_stanza_get_type_info (stanza, &type, &sub_type);
@@ -968,7 +969,7 @@ handle_stanza (WockyC2SPorter *self,
is_from_server = FALSE;
}
- for (l = priv->handlers; l != NULL; l = g_list_next (l))
+ for (l = priv->handlers; l != NULL && !handled; l = g_list_next (l))
{
StanzaHandler *handler = (StanzaHandler *) l->data;
@@ -1013,12 +1014,21 @@ handle_stanza (WockyC2SPorter *self,
wocky_stanza_get_top_node (handler->match)))
continue;
- if (handler->callback (WOCKY_PORTER (self), stanza, handler->user_data))
- goto out;
+ handled = handler->callback (WOCKY_PORTER (self), stanza,
+ handler->user_data);
+ }
+
+ if (!handled)
+ {
+ DEBUG ("Stanza not handled");
+
+ if (type == WOCKY_STANZA_TYPE_IQ &&
+ (sub_type == WOCKY_STANZA_SUB_TYPE_GET ||
+ sub_type == WOCKY_STANZA_SUB_TYPE_SET))
+ wocky_porter_send_iq_error (WOCKY_PORTER (self), stanza,
+ WOCKY_XMPP_ERROR_SERVICE_UNAVAILABLE, NULL);
}
- DEBUG ("Stanza not handled");
-out:
g_free (node);
g_free (domain);
g_free (resource);