diff options
author | Will Thompson <will.thompson@collabora.co.uk> | 2011-06-27 19:47:08 +0100 |
---|---|---|
committer | Will Thompson <will.thompson@collabora.co.uk> | 2011-11-18 10:40:59 +0000 |
commit | 502b3aa449dc9a2bfafd68eedf46531f31071432 (patch) | |
tree | 14e2eb01e1ac50bea1a8af677a6cf77e30bbc8e3 | |
parent | fb661a1c9edfd362cb367535c477650f50c50889 (diff) |
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
-rw-r--r-- | tests/wocky-porter-test.c | 100 | ||||
-rw-r--r-- | wocky/wocky-c2s-porter.c | 43 | ||||
-rw-r--r-- | wocky/wocky-meta-porter.c | 7 | ||||
-rw-r--r-- | 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 08e9d4d..7b25f09 100644 --- a/tests/wocky-porter-test.c +++ b/tests/wocky-porter-test.c @@ -3359,6 +3359,105 @@ test_reply_from_domain (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) { @@ -3424,6 +3523,7 @@ main (int argc, char **argv) send_from_send_callback); g_test_add_func ("/xmpp-porter/reply-from-domain", test_reply_from_domain); + 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 e0e92f7..bd9d68d 100644 --- a/wocky/wocky-c2s-porter.c +++ b/wocky/wocky-c2s-porter.c @@ -197,9 +197,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; @@ -223,7 +225,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); } @@ -967,7 +972,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 && @@ -1002,8 +1008,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)) @@ -1607,14 +1614,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_return_val_if_fail ( + (va_arg (ap, WockyNodeBuildTag) == 0) && + "Pattern-matching is not supported when matching stanzas " + "of any type", 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; } @@ -1655,7 +1674,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 97691c5..0d3516e 100644 --- a/wocky/wocky-meta-porter.c +++ b/wocky/wocky-meta-porter.c @@ -608,7 +608,8 @@ free_handler (gpointer data) g_hash_table_unref (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); } @@ -1261,7 +1262,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..26117f7 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_return_val_if_fail ( + (va_arg (ap, WockyNodeBuildTag) == 0) && + "Pattern-matching is not supported when matching stanzas " + "of any type", 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_return_val_if_fail ( + (va_arg (ap, WockyNodeBuildTag) == 0) && + "Pattern-matching is not supported when matching stanzas " + "of any type", 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); |