From 9e29632ee5d473cc0ffab440680568b8abce5ec6 Mon Sep 17 00:00:00 2001 From: Will Thompson Date: Mon, 27 Jun 2011 19:47:08 +0100 Subject: [PATCH] Porter: support matching STANZA_TYPE_NONE For really specialised cases, like an XML console in Gabble, you want to be able to match stanzas of any type. The docs claim you can do this, but they lie. I could be convinced that the correct way to do this is to add a fourth method, wocky_porter_register_handler_for_any_stanza (), and that the server/anyone/from variants are unnecessary. Thoughts? https://bugs.freedesktop.org/show_bug.cgi?id=38577 --- tests/wocky-porter-test.c | 100 +++++++++++++++++++++++++++++++++++++++++++++ wocky/wocky-c2s-porter.c | 43 +++++++++++++++----- wocky/wocky-meta-porter.c | 7 ++- wocky/wocky-porter.c | 56 ++++++++++++++++++++----- 4 files changed, 182 insertions(+), 24 deletions(-) diff --git a/tests/wocky-porter-test.c b/tests/wocky-porter-test.c index 9c6111a..34d574d 100644 --- a/tests/wocky-porter-test.c +++ b/tests/wocky-porter-test.c @@ -3282,6 +3282,105 @@ send_from_send_callback (void) teardown_test (test); } +/* Callbacks used in wildcard_handlers() */ +const gchar * const ROMEO = "romeo@montague.lit"; +const gchar * const JULIET = "juliet@montague.lit"; + +static gboolean +any_stanza_received_from_romeo_cb ( + WockyPorter *porter, + WockyStanza *stanza, + gpointer user_data) +{ + test_data_t *test = user_data; + + g_assert_cmpstr (wocky_stanza_get_from (stanza), ==, ROMEO); + + test->outstanding--; + g_main_loop_quit (test->loop); + return FALSE; +} + +static gboolean +any_stanza_received_from_server_cb ( + WockyPorter *porter, + WockyStanza *stanza, + gpointer user_data) +{ + test_data_t *test = user_data; + + g_assert_cmpstr (wocky_stanza_get_from (stanza), ==, NULL); + + test->outstanding--; + g_main_loop_quit (test->loop); + return FALSE; +} + +static gboolean +any_stanza_received_from_anyone_cb ( + WockyPorter *porter, + WockyStanza *stanza, + gpointer user_data) +{ + test_data_t *test = user_data; + + test->outstanding--; + g_main_loop_quit (test->loop); + return FALSE; +} + +static void +wildcard_handlers (void) +{ + test_data_t *test = setup_test (); + WockyStanza *stanza; + + test_open_both_connections (test); + wocky_porter_start (test->sched_in); + wocky_porter_start (test->sched_out); + + wocky_porter_register_handler_from_anyone (test->sched_out, + WOCKY_STANZA_TYPE_NONE, WOCKY_STANZA_SUB_TYPE_NONE, + WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, + any_stanza_received_from_anyone_cb, test, + NULL); + wocky_porter_register_handler_from (test->sched_out, + WOCKY_STANZA_TYPE_NONE, WOCKY_STANZA_SUB_TYPE_NONE, + ROMEO, + WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, + any_stanza_received_from_romeo_cb, test, + NULL); + wocky_c2s_porter_register_handler_from_server ( + WOCKY_C2S_PORTER (test->sched_out), + WOCKY_STANZA_TYPE_NONE, WOCKY_STANZA_SUB_TYPE_NONE, + WOCKY_PORTER_HANDLER_PRIORITY_NORMAL, + any_stanza_received_from_server_cb, test, + NULL); + + stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE, + WOCKY_STANZA_SUB_TYPE_HEADLINE, ROMEO, NULL, NULL); + wocky_porter_send (test->sched_in, stanza); + g_object_unref (stanza); + test->outstanding += 2; + + stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_IQ, + WOCKY_STANZA_SUB_TYPE_GET, JULIET, NULL, NULL); + wocky_porter_send (test->sched_in, stanza); + g_object_unref (stanza); + test->outstanding += 1; + + stanza = wocky_stanza_build (WOCKY_STANZA_TYPE_STREAM_FEATURES, + WOCKY_STANZA_SUB_TYPE_NONE, NULL, NULL, NULL); + wocky_porter_send (test->sched_in, stanza); + g_object_unref (stanza); + test->outstanding += 2; + + test_wait_pending (test); + + test_close_both_porters (test); + teardown_test (test); +} + int main (int argc, char **argv) { @@ -3344,6 +3443,7 @@ main (int argc, char **argv) close_from_send_callback); g_test_add_func ("/xmpp-porter/send-from-send-callback", send_from_send_callback); + g_test_add_func ("/xmpp-porter/wildcard-handlers", wildcard_handlers); result = g_test_run (); test_deinit (); diff --git a/wocky/wocky-c2s-porter.c b/wocky/wocky-c2s-porter.c index 4a786d5..999b8c3 100644 --- a/wocky/wocky-c2s-porter.c +++ b/wocky/wocky-c2s-porter.c @@ -195,9 +195,11 @@ stanza_handler_new ( result->priority = priority; result->callback = callback; result->user_data = user_data; - result->match = g_object_ref (stanza); result->sender_match = sender_match; + if (stanza != NULL) + result->match = g_object_ref (stanza); + if (sender_match == MATCH_JID) { gboolean from_valid; @@ -221,7 +223,10 @@ stanza_handler_free (StanzaHandler *handler) g_free (handler->node); g_free (handler->domain); g_free (handler->resource); - g_object_unref (handler->match); + + if (handler->match != NULL) + g_object_unref (handler->match); + g_slice_free (StanzaHandler, handler); } @@ -940,7 +945,8 @@ handle_stanza (WockyC2SPorter *self, { StanzaHandler *handler = (StanzaHandler *) l->data; - if (type != handler->type) + if (type != handler->type && + handler->type != WOCKY_STANZA_TYPE_NONE) continue; if (sub_type != handler->sub_type && @@ -975,8 +981,9 @@ handle_stanza (WockyC2SPorter *self, } /* Check if the stanza matches the pattern */ - if (!wocky_node_is_superset (wocky_stanza_get_top_node (stanza), - wocky_stanza_get_top_node (handler->match))) + if (handler->match != NULL && + !wocky_node_is_superset (wocky_stanza_get_top_node (stanza), + wocky_stanza_get_top_node (handler->match))) continue; if (handler->callback (WOCKY_PORTER (self), stanza, handler->user_data)) @@ -1568,14 +1575,26 @@ wocky_c2s_porter_register_handler_from_server_va ( g_return_val_if_fail (WOCKY_IS_C2S_PORTER (self), 0); - stanza = wocky_stanza_build_va (type, WOCKY_STANZA_SUB_TYPE_NONE, - NULL, NULL, ap); - g_assert (stanza != NULL); + if (type == WOCKY_STANZA_TYPE_NONE) + { + stanza = NULL; + g_assert ( + "If you're happy with any type of stanza, pattern-matching is not " + "supported because why would you do that?" && + va_arg (ap, WockyNodeBuildTag) == 0); + } + else + { + stanza = wocky_stanza_build_va (type, WOCKY_STANZA_SUB_TYPE_NONE, + NULL, NULL, ap); + g_assert (stanza != NULL); + } ret = wocky_c2s_porter_register_handler_from_server_by_stanza (self, type, sub_type, priority, callback, user_data, stanza); - g_object_unref (stanza); + if (stanza != NULL) + g_object_unref (stanza); return ret; } @@ -1616,7 +1635,11 @@ wocky_c2s_porter_register_handler_from_server_by_stanza ( WockyStanza *stanza) { g_return_val_if_fail (WOCKY_IS_C2S_PORTER (self), 0); - g_return_val_if_fail (WOCKY_IS_STANZA (stanza), 0); + + if (type == WOCKY_STANZA_TYPE_NONE) + g_return_val_if_fail (stanza == NULL, 0); + else + g_return_val_if_fail (WOCKY_IS_STANZA (stanza), 0); return wocky_c2s_porter_register_handler_internal (self, type, sub_type, MATCH_SERVER, NULL, diff --git a/wocky/wocky-meta-porter.c b/wocky/wocky-meta-porter.c index bb89e4d..2dad028 100644 --- a/wocky/wocky-meta-porter.c +++ b/wocky/wocky-meta-porter.c @@ -597,7 +597,8 @@ free_handler (gpointer data) g_hash_table_destroy (handler->porters); if (handler->contact != NULL) g_object_unref (handler->contact); - g_object_unref (handler->stanza); + if (handler->stanza != NULL) + g_object_unref (handler->stanza); g_slice_free (StanzaHandler, handler); } @@ -1250,7 +1251,9 @@ stanza_handler_new (WockyMetaPorter *self, out->priority = priority; out->callback = callback; out->user_data = user_data; - out->stanza = g_object_ref (stanza); + + if (stanza != NULL) + out->stanza = g_object_ref (stanza); return out; } diff --git a/wocky/wocky-porter.c b/wocky/wocky-porter.c index 08494bd..9fac71a 100644 --- a/wocky/wocky-porter.c +++ b/wocky/wocky-porter.c @@ -352,15 +352,27 @@ wocky_porter_register_handler_from_va (WockyPorter *self, g_return_val_if_fail (WOCKY_IS_PORTER (self), 0); g_return_val_if_fail (from != NULL, 0); - stanza = wocky_stanza_build_va (type, WOCKY_STANZA_SUB_TYPE_NONE, - NULL, NULL, ap); - g_assert (stanza != NULL); + if (type == WOCKY_STANZA_TYPE_NONE) + { + stanza = NULL; + g_assert ( + "If you're happy with any type of stanza, pattern-matching is not " + "supported because why would you do that?" && + va_arg (ap, WockyNodeBuildTag) == 0); + } + else + { + stanza = wocky_stanza_build_va (type, WOCKY_STANZA_SUB_TYPE_NONE, + NULL, NULL, ap); + g_assert (stanza != NULL); + } ret = wocky_porter_register_handler_from_by_stanza (self, type, sub_type, from, priority, callback, user_data, stanza); - g_object_unref (stanza); + if (stanza != NULL) + g_object_unref (stanza); return ret; } @@ -405,7 +417,11 @@ wocky_porter_register_handler_from_by_stanza (WockyPorter *self, g_return_val_if_fail (WOCKY_IS_PORTER (self), 0); g_return_val_if_fail (from != NULL, 0); - g_return_val_if_fail (WOCKY_IS_STANZA (stanza), 0); + + if (type == WOCKY_STANZA_TYPE_NONE) + g_return_val_if_fail (stanza == NULL, 0); + else + g_return_val_if_fail (WOCKY_IS_STANZA (stanza), 0); iface = WOCKY_PORTER_GET_INTERFACE (self); @@ -532,14 +548,26 @@ wocky_porter_register_handler_from_anyone_va ( g_return_val_if_fail (WOCKY_IS_PORTER (self), 0); - stanza = wocky_stanza_build_va (type, WOCKY_STANZA_SUB_TYPE_NONE, - NULL, NULL, ap); - g_assert (stanza != NULL); + if (type == WOCKY_STANZA_TYPE_NONE) + { + stanza = NULL; + g_assert ( + "If you're happy with any type of stanza, pattern-matching is not " + "supported because why would you do that?" && + va_arg (ap, WockyNodeBuildTag) == 0); + } + else + { + stanza = wocky_stanza_build_va (type, WOCKY_STANZA_SUB_TYPE_NONE, + NULL, NULL, ap); + g_assert (stanza != NULL); + } - ret = wocky_porter_register_handler_from_anyone_by_stanza (self, type, sub_type, - priority, callback, user_data, stanza); + ret = wocky_porter_register_handler_from_anyone_by_stanza (self, type, + sub_type, priority, callback, user_data, stanza); - g_object_unref (stanza); + if (stanza != NULL) + g_object_unref (stanza); return ret; } @@ -582,7 +610,11 @@ wocky_porter_register_handler_from_anyone_by_stanza ( WockyPorterInterface *iface; g_return_val_if_fail (WOCKY_IS_PORTER (self), 0); - g_return_val_if_fail (WOCKY_IS_STANZA (stanza), 0); + + if (type == WOCKY_STANZA_TYPE_NONE) + g_return_val_if_fail (stanza == NULL, 0); + else + g_return_val_if_fail (WOCKY_IS_STANZA (stanza), 0); iface = WOCKY_PORTER_GET_INTERFACE (self); -- 1.7.5.4