diff options
author | Will Thompson <will.thompson@collabora.co.uk> | 2011-03-04 10:36:26 +0000 |
---|---|---|
committer | Will Thompson <will.thompson@collabora.co.uk> | 2012-01-31 17:14:46 +0000 |
commit | 43d93377facac1a7b9bae8e898c29b245ec476f5 (patch) | |
tree | 8ac997c96cf3c542324c27ce9925eb0c19a5f45d | |
parent | d1896284653c29577b3ecb037406a9ab84a810df (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.c | 64 | ||||
-rw-r--r-- | wocky/wocky-c2s-porter.c | 20 |
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); |