summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Thompson <will.thompson@collabora.co.uk>2011-06-27 19:47:08 +0100
committerWill Thompson <will.thompson@collabora.co.uk>2011-11-18 10:40:59 +0000
commit502b3aa449dc9a2bfafd68eedf46531f31071432 (patch)
tree14e2eb01e1ac50bea1a8af677a6cf77e30bbc8e3
parentfb661a1c9edfd362cb367535c477650f50c50889 (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.c100
-rw-r--r--wocky/wocky-c2s-porter.c43
-rw-r--r--wocky/wocky-meta-porter.c7
-rw-r--r--wocky/wocky-porter.c56
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);