1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* signals.c Bus signal connection implementation
4 * Copyright (C) 2003, 2005 Red Hat, Inc.
6 * Licensed under the Academic Free License version 2.1
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28 #include <dbus/dbus-marshal-validate.h>
32 int refcount; /**< reference count */
34 DBusConnection *matches_go_to; /**< Owner of the rule */
36 unsigned int flags; /**< BusMatchFlags */
45 unsigned int *arg_lens;
50 #define BUS_MATCH_ARG_IS_PATH 0x8000000u
53 bus_match_rule_new (DBusConnection *matches_go_to)
57 rule = dbus_new0 (BusMatchRule, 1);
62 rule->matches_go_to = matches_go_to;
64 #ifndef DBUS_BUILD_TESTS
65 _dbus_assert (rule->matches_go_to != NULL);
72 bus_match_rule_ref (BusMatchRule *rule)
74 _dbus_assert (rule->refcount > 0);
82 bus_match_rule_unref (BusMatchRule *rule)
84 _dbus_assert (rule->refcount > 0);
87 if (rule->refcount == 0)
89 dbus_free (rule->interface);
90 dbus_free (rule->member);
91 dbus_free (rule->sender);
92 dbus_free (rule->destination);
93 dbus_free (rule->path);
94 dbus_free (rule->arg_lens);
96 /* can't use dbus_free_string_array() since there
104 while (i < rule->args_len)
107 dbus_free (rule->args[i]);
111 dbus_free (rule->args);
118 #ifdef DBUS_ENABLE_VERBOSE_MODE
119 /* Note this function does not do escaping, so it's only
120 * good for debug spew at the moment
123 match_rule_to_string (BusMatchRule *rule)
128 if (!_dbus_string_init (&str))
131 while ((s = _dbus_strdup ("nomem")) == NULL)
132 ; /* only OK for debug spew... */
136 if (rule->flags & BUS_MATCH_MESSAGE_TYPE)
138 if (rule->message_type == DBUS_MESSAGE_TYPE_INVALID)
140 if (!_dbus_string_append_printf (&str, "type='INVALID'"))
143 else if (rule->message_type == DBUS_MESSAGE_TYPE_METHOD_CALL)
145 if (!_dbus_string_append_printf (&str, "type='method_call'"))
148 else if (rule->message_type == DBUS_MESSAGE_TYPE_METHOD_RETURN)
150 if (!_dbus_string_append_printf (&str, "type='method_return'"))
153 else if (rule->message_type == DBUS_MESSAGE_TYPE_ERROR)
155 if (!_dbus_string_append_printf (&str, "type='error'"))
158 else if (rule->message_type == DBUS_MESSAGE_TYPE_SIGNAL)
160 if (!_dbus_string_append_printf (&str, "type='signal'"))
165 if (!_dbus_string_append_printf (&str, "type='%d'", rule->message_type))
170 if (rule->flags & BUS_MATCH_INTERFACE)
172 if (_dbus_string_get_length (&str) > 0)
174 if (!_dbus_string_append (&str, ","))
178 if (!_dbus_string_append_printf (&str, "interface='%s'", rule->interface))
182 if (rule->flags & BUS_MATCH_MEMBER)
184 if (_dbus_string_get_length (&str) > 0)
186 if (!_dbus_string_append (&str, ","))
190 if (!_dbus_string_append_printf (&str, "member='%s'", rule->member))
194 if (rule->flags & BUS_MATCH_PATH)
196 if (_dbus_string_get_length (&str) > 0)
198 if (!_dbus_string_append (&str, ","))
202 if (!_dbus_string_append_printf (&str, "path='%s'", rule->path))
206 if (rule->flags & BUS_MATCH_SENDER)
208 if (_dbus_string_get_length (&str) > 0)
210 if (!_dbus_string_append (&str, ","))
214 if (!_dbus_string_append_printf (&str, "sender='%s'", rule->sender))
218 if (rule->flags & BUS_MATCH_DESTINATION)
220 if (_dbus_string_get_length (&str) > 0)
222 if (!_dbus_string_append (&str, ","))
226 if (!_dbus_string_append_printf (&str, "destination='%s'", rule->destination))
230 if (rule->flags & BUS_MATCH_ARGS)
234 _dbus_assert (rule->args != NULL);
237 while (i < rule->args_len)
239 if (rule->args[i] != NULL)
243 if (_dbus_string_get_length (&str) > 0)
245 if (!_dbus_string_append (&str, ","))
249 is_path = (rule->arg_lens[i] & BUS_MATCH_ARG_IS_PATH) != 0;
251 if (!_dbus_string_append_printf (&str,
253 i, is_path ? "path" : "",
262 if (!_dbus_string_steal_data (&str, &ret))
265 _dbus_string_free (&str);
269 _dbus_string_free (&str);
272 while ((s = _dbus_strdup ("nomem")) == NULL)
273 ; /* only OK for debug spew... */
277 #endif /* DBUS_ENABLE_VERBOSE_MODE */
280 bus_match_rule_set_message_type (BusMatchRule *rule,
283 rule->flags |= BUS_MATCH_MESSAGE_TYPE;
285 rule->message_type = type;
291 bus_match_rule_set_interface (BusMatchRule *rule,
292 const char *interface)
296 _dbus_assert (interface != NULL);
298 new = _dbus_strdup (interface);
302 rule->flags |= BUS_MATCH_INTERFACE;
303 dbus_free (rule->interface);
304 rule->interface = new;
310 bus_match_rule_set_member (BusMatchRule *rule,
315 _dbus_assert (member != NULL);
317 new = _dbus_strdup (member);
321 rule->flags |= BUS_MATCH_MEMBER;
322 dbus_free (rule->member);
329 bus_match_rule_set_sender (BusMatchRule *rule,
334 _dbus_assert (sender != NULL);
336 new = _dbus_strdup (sender);
340 rule->flags |= BUS_MATCH_SENDER;
341 dbus_free (rule->sender);
348 bus_match_rule_set_destination (BusMatchRule *rule,
349 const char *destination)
353 _dbus_assert (destination != NULL);
355 new = _dbus_strdup (destination);
359 rule->flags |= BUS_MATCH_DESTINATION;
360 dbus_free (rule->destination);
361 rule->destination = new;
367 bus_match_rule_set_path (BusMatchRule *rule,
372 _dbus_assert (path != NULL);
374 new = _dbus_strdup (path);
378 rule->flags |= BUS_MATCH_PATH;
379 dbus_free (rule->path);
386 bus_match_rule_set_arg (BusMatchRule *rule,
388 const DBusString *value,
394 _dbus_assert (value != NULL);
396 /* args_len is the number of args not including null termination
399 if (arg >= rule->args_len)
401 unsigned int *new_arg_lens;
406 new_args_len = arg + 1;
408 /* add another + 1 here for null termination */
409 new_args = dbus_realloc (rule->args,
410 sizeof (char *) * (new_args_len + 1));
411 if (new_args == NULL)
414 /* NULL the new slots */
416 while (i <= new_args_len) /* <= for null termination */
422 rule->args = new_args;
424 /* and now add to the lengths */
425 new_arg_lens = dbus_realloc (rule->arg_lens,
426 sizeof (int) * (new_args_len + 1));
428 if (new_arg_lens == NULL)
431 /* zero the new slots */
433 while (i <= new_args_len) /* <= for null termination */
439 rule->arg_lens = new_arg_lens;
440 rule->args_len = new_args_len;
443 length = _dbus_string_get_length (value);
444 if (!_dbus_string_copy_data (value, &new))
447 rule->flags |= BUS_MATCH_ARGS;
449 dbus_free (rule->args[arg]);
450 rule->arg_lens[arg] = length;
451 rule->args[arg] = new;
454 rule->arg_lens[arg] |= BUS_MATCH_ARG_IS_PATH;
456 /* NULL termination didn't get busted */
457 _dbus_assert (rule->args[rule->args_len] == NULL);
458 _dbus_assert (rule->arg_lens[rule->args_len] == 0);
463 #define ISWHITE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || ((c) == '\r'))
466 find_key (const DBusString *str,
474 const char *key_start;
477 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
479 s = _dbus_string_get_const_data (str);
483 while (*p && ISWHITE (*p))
488 while (*p && *p != '=' && !ISWHITE (*p))
493 while (*p && ISWHITE (*p))
496 if (key_start == key_end)
498 /* Empty match rules or trailing whitespace are OK */
505 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
506 "Match rule has a key with no subsequent '=' character");
511 if (!_dbus_string_append_len (key, key_start, key_end - key_start))
523 find_value (const DBusString *str,
535 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
537 orig_len = _dbus_string_get_length (value);
539 s = _dbus_string_get_const_data (str);
547 if (quote_char == '\0')
567 if (!_dbus_string_append_byte (value, *p))
574 else if (quote_char == '\\')
576 /* \ only counts as an escape if escaping a quote mark */
579 if (!_dbus_string_append_byte (value, '\\'))
586 if (!_dbus_string_append_byte (value, *p))
596 _dbus_assert (quote_char == '\'');
604 if (!_dbus_string_append_byte (value, *p))
618 if (quote_char == '\\')
620 if (!_dbus_string_append_byte (value, '\\'))
626 else if (quote_char == '\'')
628 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
629 "Unbalanced quotation marks in match rule");
633 _dbus_assert (quote_char == '\0');
635 /* Zero-length values are allowed */
642 _DBUS_ASSERT_ERROR_IS_SET (error);
643 _dbus_string_set_length (value, orig_len);
647 /* duplicates aren't allowed so the real legitimate max is only 6 or
648 * so. Leaving extra so we don't have to bother to update it.
649 * FIXME this is sort of busted now with arg matching, but we let
650 * you match on up to 10 args for now
652 #define MAX_RULE_TOKENS 16
654 /* this is slightly too high level to be termed a "token"
655 * but let's not be pedantic.
664 tokenize_rule (const DBusString *rule_text,
665 RuleToken tokens[MAX_RULE_TOKENS],
676 if (!_dbus_string_init (&key))
682 if (!_dbus_string_init (&value))
684 _dbus_string_free (&key);
691 while (i < MAX_RULE_TOKENS &&
692 pos < _dbus_string_get_length (rule_text))
694 _dbus_assert (tokens[i].key == NULL);
695 _dbus_assert (tokens[i].value == NULL);
697 if (!find_key (rule_text, pos, &key, &pos, error))
700 if (_dbus_string_get_length (&key) == 0)
703 if (!_dbus_string_steal_data (&key, &tokens[i].key))
709 if (!find_value (rule_text, pos, tokens[i].key, &value, &pos, error))
712 if (!_dbus_string_steal_data (&value, &tokens[i].value))
728 while (tokens[i].key || tokens[i].value)
730 dbus_free (tokens[i].key);
731 dbus_free (tokens[i].value);
732 tokens[i].key = NULL;
733 tokens[i].value = NULL;
738 _dbus_string_free (&key);
739 _dbus_string_free (&value);
745 bus_match_rule_parse_arg_match (BusMatchRule *rule,
747 const DBusString *value,
756 /* For now, arg0='foo' always implies that 'foo' is a
757 * DBUS_TYPE_STRING. Someday we could add an arg0type='int32' thing
758 * if we wanted, which would specify another type, in which case
759 * arg0='5' would have the 5 parsed as an int rather than string.
762 /* First we need to parse arg0 = 0, arg27 = 27 */
764 _dbus_string_init_const (&key_str, key);
765 length = _dbus_string_get_length (&key_str);
767 if (_dbus_string_get_length (&key_str) < 4)
769 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
770 "Key '%s' in match rule starts with 'arg' but lacks an arg number. Should be 'arg0' or 'arg7' for example.\n", key);
774 if (!_dbus_string_parse_uint (&key_str, 3, &arg, &end))
776 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
777 "Key '%s' in match rule starts with 'arg' but could not parse arg number. Should be 'arg0' or 'arg7' for example.\n", key);
782 ((end + 4) != length ||
783 !_dbus_string_ends_with_c_str (&key_str, "path")))
785 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
786 "Key '%s' in match rule contains junk after argument number. Only 'path' is optionally valid ('arg0path' for example).\n", key);
790 is_path = end != length;
792 /* If we didn't check this we could allocate a huge amount of RAM */
793 if (arg > DBUS_MAXIMUM_MATCH_RULE_ARG_NUMBER)
795 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
796 "Key '%s' in match rule has arg number %lu but the maximum is %d.\n", key, (unsigned long) arg, DBUS_MAXIMUM_MATCH_RULE_ARG_NUMBER);
800 if ((rule->flags & BUS_MATCH_ARGS) &&
801 rule->args_len > (int) arg &&
802 rule->args[arg] != NULL)
804 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
805 "Argument %d matched more than once in match rule\n", key);
809 if (!bus_match_rule_set_arg (rule, arg, value, is_path))
818 _DBUS_ASSERT_ERROR_IS_SET (error);
823 * The format is comma-separated with strings quoted with single quotes
824 * as for the shell (to escape a literal single quote, use '\'').
826 * type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='Foo',
827 * path='/bar/foo',destination=':452345.34'
831 bus_match_rule_parse (DBusConnection *matches_go_to,
832 const DBusString *rule_text,
836 RuleToken tokens[MAX_RULE_TOKENS+1]; /* NULL termination + 1 */
839 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
841 if (_dbus_string_get_length (rule_text) > DBUS_MAXIMUM_MATCH_RULE_LENGTH)
843 dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
844 "Match rule text is %d bytes, maximum is %d",
845 _dbus_string_get_length (rule_text),
846 DBUS_MAXIMUM_MATCH_RULE_LENGTH);
850 memset (tokens, '\0', sizeof (tokens));
852 rule = bus_match_rule_new (matches_go_to);
859 if (!tokenize_rule (rule_text, tokens, error))
863 while (tokens[i].key != NULL)
867 const char *key = tokens[i].key;
868 const char *value = tokens[i].value;
870 _dbus_string_init_const (&tmp_str, value);
871 len = _dbus_string_get_length (&tmp_str);
873 if (strcmp (key, "type") == 0)
877 if (rule->flags & BUS_MATCH_MESSAGE_TYPE)
879 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
880 "Key %s specified twice in match rule\n", key);
884 t = dbus_message_type_from_string (value);
886 if (t == DBUS_MESSAGE_TYPE_INVALID)
888 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
889 "Invalid message type (%s) in match rule\n", value);
893 if (!bus_match_rule_set_message_type (rule, t))
899 else if (strcmp (key, "sender") == 0)
901 if (rule->flags & BUS_MATCH_SENDER)
903 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
904 "Key %s specified twice in match rule\n", key);
908 if (!_dbus_validate_bus_name (&tmp_str, 0, len))
910 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
911 "Sender name '%s' is invalid\n", value);
915 if (!bus_match_rule_set_sender (rule, value))
921 else if (strcmp (key, "interface") == 0)
923 if (rule->flags & BUS_MATCH_INTERFACE)
925 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
926 "Key %s specified twice in match rule\n", key);
930 if (!_dbus_validate_interface (&tmp_str, 0, len))
932 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
933 "Interface name '%s' is invalid\n", value);
937 if (!bus_match_rule_set_interface (rule, value))
943 else if (strcmp (key, "member") == 0)
945 if (rule->flags & BUS_MATCH_MEMBER)
947 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
948 "Key %s specified twice in match rule\n", key);
952 if (!_dbus_validate_member (&tmp_str, 0, len))
954 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
955 "Member name '%s' is invalid\n", value);
959 if (!bus_match_rule_set_member (rule, value))
965 else if (strcmp (key, "path") == 0)
967 if (rule->flags & BUS_MATCH_PATH)
969 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
970 "Key %s specified twice in match rule\n", key);
974 if (!_dbus_validate_path (&tmp_str, 0, len))
976 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
977 "Path '%s' is invalid\n", value);
981 if (!bus_match_rule_set_path (rule, value))
987 else if (strcmp (key, "destination") == 0)
989 if (rule->flags & BUS_MATCH_DESTINATION)
991 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
992 "Key %s specified twice in match rule\n", key);
996 if (!_dbus_validate_bus_name (&tmp_str, 0, len))
998 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
999 "Destination name '%s' is invalid\n", value);
1003 if (!bus_match_rule_set_destination (rule, value))
1005 BUS_SET_OOM (error);
1009 else if (strncmp (key, "arg", 3) == 0)
1011 if (!bus_match_rule_parse_arg_match (rule, key, &tmp_str, error))
1016 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
1017 "Unknown key \"%s\" in match rule",
1029 _DBUS_ASSERT_ERROR_IS_SET (error);
1032 bus_match_rule_unref (rule);
1039 while (tokens[i].key || tokens[i].value)
1041 _dbus_assert (i < MAX_RULE_TOKENS);
1042 dbus_free (tokens[i].key);
1043 dbus_free (tokens[i].value);
1050 typedef struct RulePool RulePool;
1053 /* Maps non-NULL interface names to non-NULL (DBusList **)s */
1054 DBusHashTable *rules_by_iface;
1056 /* List of BusMatchRules which don't specify an interface */
1057 DBusList *rules_without_iface;
1060 struct BusMatchmaker
1064 /* Pools of rules, grouped by the type of message they match. 0
1065 * (DBUS_MESSAGE_TYPE_INVALID) represents rules that do not specify a message
1068 RulePool rules_by_type[DBUS_NUM_MESSAGE_TYPES];
1072 rule_list_free (DBusList **rules)
1074 while (*rules != NULL)
1078 rule = (*rules)->data;
1079 bus_match_rule_unref (rule);
1080 _dbus_list_remove_link (rules, *rules);
1085 rule_list_ptr_free (DBusList **list)
1087 /* We have to cope with NULL because the hash table frees the "existing"
1088 * value (which is NULL) when creating a new table entry...
1092 rule_list_free (list);
1098 bus_matchmaker_new (void)
1100 BusMatchmaker *matchmaker;
1103 matchmaker = dbus_new0 (BusMatchmaker, 1);
1104 if (matchmaker == NULL)
1107 matchmaker->refcount = 1;
1109 for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++)
1111 RulePool *p = matchmaker->rules_by_type + i;
1113 p->rules_by_iface = _dbus_hash_table_new (DBUS_HASH_STRING,
1114 dbus_free, (DBusFreeFunction) rule_list_ptr_free);
1116 if (p->rules_by_iface == NULL)
1123 for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++)
1125 RulePool *p = matchmaker->rules_by_type + i;
1127 if (p->rules_by_iface == NULL)
1130 _dbus_hash_table_unref (p->rules_by_iface);
1132 dbus_free (matchmaker);
1138 bus_matchmaker_get_rules (BusMatchmaker *matchmaker,
1140 const char *interface,
1145 _dbus_assert (message_type >= 0);
1146 _dbus_assert (message_type < DBUS_NUM_MESSAGE_TYPES);
1148 _dbus_verbose ("Looking up rules for message_type %d, interface %s\n",
1150 interface != NULL ? interface : "<null>");
1152 p = matchmaker->rules_by_type + message_type;
1154 if (interface == NULL)
1156 return &p->rules_without_iface;
1162 list = _dbus_hash_table_lookup_string (p->rules_by_iface, interface);
1164 if (list == NULL && create)
1166 char *dupped_interface;
1168 list = dbus_new0 (DBusList *, 1);
1172 dupped_interface = _dbus_strdup (interface);
1173 if (dupped_interface == NULL)
1179 _dbus_verbose ("Adding list for type %d, iface %s\n", message_type,
1182 if (!_dbus_hash_table_insert_string (p->rules_by_iface,
1183 dupped_interface, list))
1186 dbus_free (dupped_interface);
1196 bus_matchmaker_gc_rules (BusMatchmaker *matchmaker,
1198 const char *interface,
1203 if (interface == NULL)
1209 _dbus_verbose ("GCing HT entry for message_type %u, interface %s\n",
1210 message_type, interface);
1212 p = matchmaker->rules_by_type + message_type;
1214 _dbus_assert (_dbus_hash_table_lookup_string (p->rules_by_iface, interface)
1217 _dbus_hash_table_remove_string (p->rules_by_iface, interface);
1221 bus_matchmaker_ref (BusMatchmaker *matchmaker)
1223 _dbus_assert (matchmaker->refcount > 0);
1225 matchmaker->refcount += 1;
1231 bus_matchmaker_unref (BusMatchmaker *matchmaker)
1233 _dbus_assert (matchmaker->refcount > 0);
1235 matchmaker->refcount -= 1;
1236 if (matchmaker->refcount == 0)
1240 for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++)
1242 RulePool *p = matchmaker->rules_by_type + i;
1244 _dbus_hash_table_unref (p->rules_by_iface);
1245 rule_list_free (&p->rules_without_iface);
1248 dbus_free (matchmaker);
1252 /* The rule can't be modified after it's added. */
1254 bus_matchmaker_add_rule (BusMatchmaker *matchmaker,
1259 _dbus_assert (bus_connection_is_active (rule->matches_go_to));
1261 _dbus_verbose ("Adding rule with message_type %d, interface %s\n",
1263 rule->interface != NULL ? rule->interface : "<null>");
1265 rules = bus_matchmaker_get_rules (matchmaker, rule->message_type,
1266 rule->interface, TRUE);
1271 if (!_dbus_list_append (rules, rule))
1274 if (!bus_connection_add_match_rule (rule->matches_go_to, rule))
1276 _dbus_list_remove_last (rules, rule);
1277 bus_matchmaker_gc_rules (matchmaker, rule->message_type,
1278 rule->interface, rules);
1282 bus_match_rule_ref (rule);
1284 #ifdef DBUS_ENABLE_VERBOSE_MODE
1286 char *s = match_rule_to_string (rule);
1288 _dbus_verbose ("Added match rule %s to connection %p\n",
1289 s, rule->matches_go_to);
1298 match_rule_equal (BusMatchRule *a,
1301 if (a->flags != b->flags)
1304 if (a->matches_go_to != b->matches_go_to)
1307 if ((a->flags & BUS_MATCH_MESSAGE_TYPE) &&
1308 a->message_type != b->message_type)
1311 if ((a->flags & BUS_MATCH_MEMBER) &&
1312 strcmp (a->member, b->member) != 0)
1315 if ((a->flags & BUS_MATCH_PATH) &&
1316 strcmp (a->path, b->path) != 0)
1319 if ((a->flags & BUS_MATCH_INTERFACE) &&
1320 strcmp (a->interface, b->interface) != 0)
1323 if ((a->flags & BUS_MATCH_SENDER) &&
1324 strcmp (a->sender, b->sender) != 0)
1327 if ((a->flags & BUS_MATCH_DESTINATION) &&
1328 strcmp (a->destination, b->destination) != 0)
1331 if (a->flags & BUS_MATCH_ARGS)
1335 if (a->args_len != b->args_len)
1339 while (i < a->args_len)
1343 if ((a->args[i] != NULL) != (b->args[i] != NULL))
1346 if (a->arg_lens[i] != b->arg_lens[i])
1349 length = a->arg_lens[i] & ~BUS_MATCH_ARG_IS_PATH;
1351 if (a->args[i] != NULL)
1353 _dbus_assert (b->args[i] != NULL);
1354 if (memcmp (a->args[i], b->args[i], length) != 0)
1366 bus_matchmaker_remove_rule_link (DBusList **rules,
1369 BusMatchRule *rule = link->data;
1371 bus_connection_remove_match_rule (rule->matches_go_to, rule);
1372 _dbus_list_remove_link (rules, link);
1374 #ifdef DBUS_ENABLE_VERBOSE_MODE
1376 char *s = match_rule_to_string (rule);
1378 _dbus_verbose ("Removed match rule %s for connection %p\n",
1379 s, rule->matches_go_to);
1384 bus_match_rule_unref (rule);
1388 bus_matchmaker_remove_rule (BusMatchmaker *matchmaker,
1393 _dbus_verbose ("Removing rule with message_type %d, interface %s\n",
1395 rule->interface != NULL ? rule->interface : "<null>");
1397 bus_connection_remove_match_rule (rule->matches_go_to, rule);
1399 rules = bus_matchmaker_get_rules (matchmaker, rule->message_type,
1400 rule->interface, FALSE);
1402 /* We should only be asked to remove a rule by identity right after it was
1403 * added, so there should be a list for it.
1405 _dbus_assert (rules != NULL);
1407 _dbus_list_remove (rules, rule);
1408 bus_matchmaker_gc_rules (matchmaker, rule->message_type, rule->interface,
1411 #ifdef DBUS_ENABLE_VERBOSE_MODE
1413 char *s = match_rule_to_string (rule);
1415 _dbus_verbose ("Removed match rule %s for connection %p\n",
1416 s, rule->matches_go_to);
1421 bus_match_rule_unref (rule);
1424 /* Remove a single rule which is equal to the given rule by value */
1426 bus_matchmaker_remove_rule_by_value (BusMatchmaker *matchmaker,
1427 BusMatchRule *value,
1431 DBusList *link = NULL;
1433 _dbus_verbose ("Removing rule by value with message_type %d, interface %s\n",
1434 value->message_type,
1435 value->interface != NULL ? value->interface : "<null>");
1437 rules = bus_matchmaker_get_rules (matchmaker, value->message_type,
1438 value->interface, FALSE);
1442 /* we traverse backward because bus_connection_remove_match_rule()
1443 * removes the most-recently-added rule
1445 link = _dbus_list_get_last_link (rules);
1446 while (link != NULL)
1452 prev = _dbus_list_get_prev_link (rules, link);
1454 if (match_rule_equal (rule, value))
1456 bus_matchmaker_remove_rule_link (rules, link);
1466 dbus_set_error (error, DBUS_ERROR_MATCH_RULE_NOT_FOUND,
1467 "The given match rule wasn't found and can't be removed");
1471 bus_matchmaker_gc_rules (matchmaker, value->message_type, value->interface,
1478 rule_list_remove_by_connection (DBusList **rules,
1479 DBusConnection *connection)
1483 link = _dbus_list_get_first_link (rules);
1484 while (link != NULL)
1490 next = _dbus_list_get_next_link (rules, link);
1492 if (rule->matches_go_to == connection)
1494 bus_matchmaker_remove_rule_link (rules, link);
1496 else if (((rule->flags & BUS_MATCH_SENDER) && *rule->sender == ':') ||
1497 ((rule->flags & BUS_MATCH_DESTINATION) && *rule->destination == ':'))
1499 /* The rule matches to/from a base service, see if it's the
1500 * one being disconnected, since we know this service name
1501 * will never be recycled.
1505 name = bus_connection_get_name (connection);
1506 _dbus_assert (name != NULL); /* because we're an active connection */
1508 if (((rule->flags & BUS_MATCH_SENDER) &&
1509 strcmp (rule->sender, name) == 0) ||
1510 ((rule->flags & BUS_MATCH_DESTINATION) &&
1511 strcmp (rule->destination, name) == 0))
1513 bus_matchmaker_remove_rule_link (rules, link);
1522 bus_matchmaker_disconnected (BusMatchmaker *matchmaker,
1523 DBusConnection *connection)
1529 * This scans all match rules on the bus. We could avoid that
1530 * for the rules belonging to the connection, since we keep
1531 * a list of those; but for the rules that just refer to
1532 * the connection we'd need to do something more elaborate.
1535 _dbus_assert (bus_connection_is_active (connection));
1537 _dbus_verbose ("Removing all rules for connection %p\n", connection);
1539 for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++)
1541 RulePool *p = matchmaker->rules_by_type + i;
1544 rule_list_remove_by_connection (&p->rules_without_iface, connection);
1546 _dbus_hash_iter_init (p->rules_by_iface, &iter);
1547 while (_dbus_hash_iter_next (&iter))
1549 DBusList **items = _dbus_hash_iter_get_value (&iter);
1551 rule_list_remove_by_connection (items, connection);
1554 _dbus_hash_iter_remove_entry (&iter);
1560 connection_is_primary_owner (DBusConnection *connection,
1561 const char *service_name)
1563 BusService *service;
1565 BusRegistry *registry;
1567 _dbus_assert (connection != NULL);
1569 registry = bus_connection_get_registry (connection);
1571 _dbus_string_init_const (&str, service_name);
1572 service = bus_registry_lookup (registry, &str);
1574 if (service == NULL)
1575 return FALSE; /* Service doesn't exist so connection can't own it. */
1577 return bus_service_get_primary_owners_connection (service) == connection;
1581 match_rule_matches (BusMatchRule *rule,
1582 DBusConnection *sender,
1583 DBusConnection *addressed_recipient,
1584 DBusMessage *message,
1585 BusMatchFlags already_matched)
1589 /* All features of the match rule are AND'd together,
1590 * so FALSE if any of them don't match.
1593 /* sender/addressed_recipient of #NULL may mean bus driver,
1594 * or for addressed_recipient may mean a message with no
1595 * specific recipient (i.e. a signal)
1598 /* Don't bother re-matching features we've already checked implicitly. */
1599 flags = rule->flags & (~already_matched);
1601 if (flags & BUS_MATCH_MESSAGE_TYPE)
1603 _dbus_assert (rule->message_type != DBUS_MESSAGE_TYPE_INVALID);
1605 if (rule->message_type != dbus_message_get_type (message))
1609 if (flags & BUS_MATCH_INTERFACE)
1613 _dbus_assert (rule->interface != NULL);
1615 iface = dbus_message_get_interface (message);
1619 if (strcmp (iface, rule->interface) != 0)
1623 if (flags & BUS_MATCH_MEMBER)
1627 _dbus_assert (rule->member != NULL);
1629 member = dbus_message_get_member (message);
1633 if (strcmp (member, rule->member) != 0)
1637 if (flags & BUS_MATCH_SENDER)
1639 _dbus_assert (rule->sender != NULL);
1643 if (strcmp (rule->sender,
1644 DBUS_SERVICE_DBUS) != 0)
1649 if (!connection_is_primary_owner (sender, rule->sender))
1654 if (flags & BUS_MATCH_DESTINATION)
1656 const char *destination;
1658 _dbus_assert (rule->destination != NULL);
1660 destination = dbus_message_get_destination (message);
1661 if (destination == NULL)
1664 if (addressed_recipient == NULL)
1666 if (strcmp (rule->destination,
1667 DBUS_SERVICE_DBUS) != 0)
1672 if (!connection_is_primary_owner (addressed_recipient, rule->destination))
1677 if (flags & BUS_MATCH_PATH)
1681 _dbus_assert (rule->path != NULL);
1683 path = dbus_message_get_path (message);
1687 if (strcmp (path, rule->path) != 0)
1691 if (flags & BUS_MATCH_ARGS)
1694 DBusMessageIter iter;
1696 _dbus_assert (rule->args != NULL);
1698 dbus_message_iter_init (message, &iter);
1701 while (i < rule->args_len)
1704 const char *expected_arg;
1705 int expected_length;
1706 dbus_bool_t is_path;
1708 expected_arg = rule->args[i];
1709 expected_length = rule->arg_lens[i] & ~BUS_MATCH_ARG_IS_PATH;
1710 is_path = (rule->arg_lens[i] & BUS_MATCH_ARG_IS_PATH) != 0;
1712 current_type = dbus_message_iter_get_arg_type (&iter);
1714 if (expected_arg != NULL)
1716 const char *actual_arg;
1719 if (current_type != DBUS_TYPE_STRING)
1723 dbus_message_iter_get_basic (&iter, &actual_arg);
1724 _dbus_assert (actual_arg != NULL);
1726 actual_length = strlen (actual_arg);
1730 if (actual_length < expected_length &&
1731 actual_arg[actual_length - 1] != '/')
1734 if (expected_length < actual_length &&
1735 expected_arg[expected_length - 1] != '/')
1738 if (memcmp (actual_arg, expected_arg,
1739 MIN (actual_length, expected_length)) != 0)
1744 if (expected_length != actual_length ||
1745 memcmp (expected_arg, actual_arg, expected_length) != 0)
1751 if (current_type != DBUS_TYPE_INVALID)
1752 dbus_message_iter_next (&iter);
1762 get_recipients_from_list (DBusList **rules,
1763 DBusConnection *sender,
1764 DBusConnection *addressed_recipient,
1765 DBusMessage *message,
1766 DBusList **recipients_p)
1773 link = _dbus_list_get_first_link (rules);
1774 while (link != NULL)
1780 #ifdef DBUS_ENABLE_VERBOSE_MODE
1782 char *s = match_rule_to_string (rule);
1784 _dbus_verbose ("Checking whether message matches rule %s for connection %p\n",
1785 s, rule->matches_go_to);
1790 if (match_rule_matches (rule,
1791 sender, addressed_recipient, message,
1792 BUS_MATCH_MESSAGE_TYPE | BUS_MATCH_INTERFACE))
1794 _dbus_verbose ("Rule matched\n");
1796 /* Append to the list if we haven't already */
1797 if (bus_connection_mark_stamp (rule->matches_go_to))
1799 if (!_dbus_list_append (recipients_p, rule->matches_go_to))
1802 #ifdef DBUS_ENABLE_VERBOSE_MODE
1805 _dbus_verbose ("Connection already receiving this message, so not adding again\n");
1807 #endif /* DBUS_ENABLE_VERBOSE_MODE */
1810 link = _dbus_list_get_next_link (rules, link);
1817 bus_matchmaker_get_recipients (BusMatchmaker *matchmaker,
1818 BusConnections *connections,
1819 DBusConnection *sender,
1820 DBusConnection *addressed_recipient,
1821 DBusMessage *message,
1822 DBusList **recipients_p)
1825 const char *interface;
1826 DBusList **neither, **just_type, **just_iface, **both;
1828 _dbus_assert (*recipients_p == NULL);
1830 /* This avoids sending same message to the same connection twice.
1831 * Purpose of the stamp instead of a bool is to avoid iterating over
1832 * all connections resetting the bool each time.
1834 bus_connections_increment_stamp (connections);
1836 /* addressed_recipient is already receiving the message, don't add to list.
1837 * NULL addressed_recipient means either bus driver, or this is a signal
1838 * and thus lacks a specific addressed_recipient.
1840 if (addressed_recipient != NULL)
1841 bus_connection_mark_stamp (addressed_recipient);
1843 type = dbus_message_get_type (message);
1844 interface = dbus_message_get_interface (message);
1846 neither = bus_matchmaker_get_rules (matchmaker, DBUS_MESSAGE_TYPE_INVALID,
1848 just_type = just_iface = both = NULL;
1850 if (interface != NULL)
1851 just_iface = bus_matchmaker_get_rules (matchmaker,
1852 DBUS_MESSAGE_TYPE_INVALID, interface, FALSE);
1854 if (type > DBUS_MESSAGE_TYPE_INVALID && type < DBUS_NUM_MESSAGE_TYPES)
1856 just_type = bus_matchmaker_get_rules (matchmaker, type, NULL, FALSE);
1858 if (interface != NULL)
1859 both = bus_matchmaker_get_rules (matchmaker, type, interface, FALSE);
1862 if (!(get_recipients_from_list (neither, sender, addressed_recipient,
1863 message, recipients_p) &&
1864 get_recipients_from_list (just_iface, sender, addressed_recipient,
1865 message, recipients_p) &&
1866 get_recipients_from_list (just_type, sender, addressed_recipient,
1867 message, recipients_p) &&
1868 get_recipients_from_list (both, sender, addressed_recipient,
1869 message, recipients_p)))
1871 _dbus_list_clear (recipients_p);
1878 #ifdef DBUS_BUILD_TESTS
1882 static BusMatchRule*
1883 check_parse (dbus_bool_t should_succeed,
1890 dbus_error_init (&error);
1892 _dbus_string_init_const (&str, text);
1894 rule = bus_match_rule_parse (NULL, &str, &error);
1895 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1897 dbus_error_free (&error);
1901 if (should_succeed && rule == NULL)
1903 _dbus_warn ("Failed to parse: %s: %s: \"%s\"\n",
1904 error.name, error.message,
1905 _dbus_string_get_const_data (&str));
1909 if (!should_succeed && rule != NULL)
1911 _dbus_warn ("Failed to fail to parse: \"%s\"\n",
1912 _dbus_string_get_const_data (&str));
1916 dbus_error_free (&error);
1922 assert_large_rule (BusMatchRule *rule)
1924 _dbus_assert (rule->flags & BUS_MATCH_MESSAGE_TYPE);
1925 _dbus_assert (rule->flags & BUS_MATCH_SENDER);
1926 _dbus_assert (rule->flags & BUS_MATCH_INTERFACE);
1927 _dbus_assert (rule->flags & BUS_MATCH_MEMBER);
1928 _dbus_assert (rule->flags & BUS_MATCH_DESTINATION);
1929 _dbus_assert (rule->flags & BUS_MATCH_PATH);
1931 _dbus_assert (rule->message_type == DBUS_MESSAGE_TYPE_SIGNAL);
1932 _dbus_assert (rule->interface != NULL);
1933 _dbus_assert (rule->member != NULL);
1934 _dbus_assert (rule->sender != NULL);
1935 _dbus_assert (rule->destination != NULL);
1936 _dbus_assert (rule->path != NULL);
1938 _dbus_assert (strcmp (rule->interface, "org.freedesktop.DBusInterface") == 0);
1939 _dbus_assert (strcmp (rule->sender, "org.freedesktop.DBusSender") == 0);
1940 _dbus_assert (strcmp (rule->member, "Foo") == 0);
1941 _dbus_assert (strcmp (rule->path, "/bar/foo") == 0);
1942 _dbus_assert (strcmp (rule->destination, ":452345.34") == 0);
1946 test_parsing (void *data)
1950 rule = check_parse (TRUE, "type='signal',sender='org.freedesktop.DBusSender',interface='org.freedesktop.DBusInterface',member='Foo',path='/bar/foo',destination=':452345.34'");
1953 assert_large_rule (rule);
1954 bus_match_rule_unref (rule);
1957 /* With extra whitespace and useless quotes */
1958 rule = check_parse (TRUE, " type='signal', \tsender='org.freedes''ktop.DBusSender', interface='org.freedesktop.DBusInterface''''', \tmember='Foo',path='/bar/foo',destination=':452345.34'''''");
1961 assert_large_rule (rule);
1962 bus_match_rule_unref (rule);
1966 /* A simple signal connection */
1967 rule = check_parse (TRUE, "type='signal',path='/foo',interface='org.Bar'");
1970 _dbus_assert (rule->flags & BUS_MATCH_MESSAGE_TYPE);
1971 _dbus_assert (rule->flags & BUS_MATCH_INTERFACE);
1972 _dbus_assert (rule->flags & BUS_MATCH_PATH);
1974 _dbus_assert (rule->message_type == DBUS_MESSAGE_TYPE_SIGNAL);
1975 _dbus_assert (rule->interface != NULL);
1976 _dbus_assert (rule->path != NULL);
1978 _dbus_assert (strcmp (rule->interface, "org.Bar") == 0);
1979 _dbus_assert (strcmp (rule->path, "/foo") == 0);
1981 bus_match_rule_unref (rule);
1985 rule = check_parse (TRUE, "arg0='foo'");
1988 _dbus_assert (rule->flags == BUS_MATCH_ARGS);
1989 _dbus_assert (rule->args != NULL);
1990 _dbus_assert (rule->args_len == 1);
1991 _dbus_assert (rule->args[0] != NULL);
1992 _dbus_assert (rule->args[1] == NULL);
1993 _dbus_assert (strcmp (rule->args[0], "foo") == 0);
1995 bus_match_rule_unref (rule);
1998 rule = check_parse (TRUE, "arg1='foo'");
2001 _dbus_assert (rule->flags == BUS_MATCH_ARGS);
2002 _dbus_assert (rule->args != NULL);
2003 _dbus_assert (rule->args_len == 2);
2004 _dbus_assert (rule->args[0] == NULL);
2005 _dbus_assert (rule->args[1] != NULL);
2006 _dbus_assert (rule->args[2] == NULL);
2007 _dbus_assert (strcmp (rule->args[1], "foo") == 0);
2009 bus_match_rule_unref (rule);
2012 rule = check_parse (TRUE, "arg2='foo'");
2015 _dbus_assert (rule->flags == BUS_MATCH_ARGS);
2016 _dbus_assert (rule->args != NULL);
2017 _dbus_assert (rule->args_len == 3);
2018 _dbus_assert (rule->args[0] == NULL);
2019 _dbus_assert (rule->args[1] == NULL);
2020 _dbus_assert (rule->args[2] != NULL);
2021 _dbus_assert (rule->args[3] == NULL);
2022 _dbus_assert (strcmp (rule->args[2], "foo") == 0);
2024 bus_match_rule_unref (rule);
2027 rule = check_parse (TRUE, "arg40='foo'");
2030 _dbus_assert (rule->flags == BUS_MATCH_ARGS);
2031 _dbus_assert (rule->args != NULL);
2032 _dbus_assert (rule->args_len == 41);
2033 _dbus_assert (rule->args[0] == NULL);
2034 _dbus_assert (rule->args[1] == NULL);
2035 _dbus_assert (rule->args[40] != NULL);
2036 _dbus_assert (rule->args[41] == NULL);
2037 _dbus_assert (strcmp (rule->args[40], "foo") == 0);
2039 bus_match_rule_unref (rule);
2042 rule = check_parse (TRUE, "arg63='foo'");
2045 _dbus_assert (rule->flags == BUS_MATCH_ARGS);
2046 _dbus_assert (rule->args != NULL);
2047 _dbus_assert (rule->args_len == 64);
2048 _dbus_assert (rule->args[0] == NULL);
2049 _dbus_assert (rule->args[1] == NULL);
2050 _dbus_assert (rule->args[63] != NULL);
2051 _dbus_assert (rule->args[64] == NULL);
2052 _dbus_assert (strcmp (rule->args[63], "foo") == 0);
2054 bus_match_rule_unref (rule);
2057 /* Too-large argN */
2058 rule = check_parse (FALSE, "arg300='foo'");
2059 _dbus_assert (rule == NULL);
2060 rule = check_parse (FALSE, "arg64='foo'");
2061 _dbus_assert (rule == NULL);
2064 rule = check_parse (FALSE, "arg='foo'");
2065 _dbus_assert (rule == NULL);
2066 rule = check_parse (FALSE, "argv='foo'");
2067 _dbus_assert (rule == NULL);
2068 rule = check_parse (FALSE, "arg3junk='foo'");
2069 _dbus_assert (rule == NULL);
2070 rule = check_parse (FALSE, "argument='foo'");
2071 _dbus_assert (rule == NULL);
2073 /* Reject duplicates */
2074 rule = check_parse (FALSE, "type='signal',type='method_call'");
2075 _dbus_assert (rule == NULL);
2077 /* Duplicates with the argN code */
2078 rule = check_parse (FALSE, "arg0='foo',arg0='bar'");
2079 _dbus_assert (rule == NULL);
2080 rule = check_parse (FALSE, "arg3='foo',arg3='bar'");
2081 _dbus_assert (rule == NULL);
2082 rule = check_parse (FALSE, "arg30='foo',arg30='bar'");
2083 _dbus_assert (rule == NULL);
2085 /* Reject broken keys */
2086 rule = check_parse (FALSE, "blah='signal'");
2087 _dbus_assert (rule == NULL);
2089 /* Reject broken values */
2090 rule = check_parse (FALSE, "type='chouin'");
2091 _dbus_assert (rule == NULL);
2092 rule = check_parse (FALSE, "interface='abc@def++'");
2093 _dbus_assert (rule == NULL);
2094 rule = check_parse (FALSE, "service='youpi'");
2095 _dbus_assert (rule == NULL);
2097 /* Allow empty rule */
2098 rule = check_parse (TRUE, "");
2101 _dbus_assert (rule->flags == 0);
2103 bus_match_rule_unref (rule);
2106 /* All-whitespace rule is the same as empty */
2107 rule = check_parse (TRUE, " \t");
2110 _dbus_assert (rule->flags == 0);
2112 bus_match_rule_unref (rule);
2115 /* But with non-whitespace chars and no =value, it's not OK */
2116 rule = check_parse (FALSE, "type");
2117 _dbus_assert (rule == NULL);
2125 } equality_tests[] = {
2126 { "type='signal'", "type='signal'" },
2127 { "type='signal',interface='foo.bar'", "interface='foo.bar',type='signal'" },
2128 { "type='signal',member='bar'", "member='bar',type='signal'" },
2129 { "type='method_call',sender=':1.0'", "sender=':1.0',type='method_call'" },
2130 { "type='method_call',destination=':1.0'", "destination=':1.0',type='method_call'" },
2131 { "type='method_call',path='/foo/bar'", "path='/foo/bar',type='method_call'" },
2132 { "type='method_call',arg0='blah'", "arg0='blah',type='method_call'" },
2133 { "type='method_call',arg0='boo'", "arg0='boo',type='method_call'" },
2134 { "type='method_call',arg0='blah',arg1='baz'", "arg0='blah',arg1='baz',type='method_call'" },
2135 { "type='method_call',arg3='foosh'", "arg3='foosh',type='method_call'" },
2136 { "arg3='fool'", "arg3='fool'" },
2137 { "member='food'", "member='food'" }
2141 test_equality (void)
2146 while (i < _DBUS_N_ELEMENTS (equality_tests))
2148 BusMatchRule *first;
2149 BusMatchRule *second;
2152 first = check_parse (TRUE, equality_tests[i].first);
2153 _dbus_assert (first != NULL);
2154 second = check_parse (TRUE, equality_tests[i].second);
2155 _dbus_assert (second != NULL);
2157 if (!match_rule_equal (first, second))
2159 _dbus_warn ("rule %s and %s should have been equal\n",
2160 equality_tests[i].first,
2161 equality_tests[i].second);
2165 bus_match_rule_unref (second);
2167 /* Check that the rule is not equal to any of the
2168 * others besides its pair match
2171 while (j < _DBUS_N_ELEMENTS (equality_tests))
2175 second = check_parse (TRUE, equality_tests[j].second);
2177 if (match_rule_equal (first, second))
2179 _dbus_warn ("rule %s and %s should not have been equal\n",
2180 equality_tests[i].first,
2181 equality_tests[j].second);
2185 bus_match_rule_unref (second);
2191 bus_match_rule_unref (first);
2198 should_match_message_1[] = {
2200 "member='Frobated'",
2202 "type='signal',member='Frobated'",
2203 "type='signal',member='Frobated',arg0='foobar'",
2204 "member='Frobated',arg0='foobar'",
2205 "type='signal',arg0='foobar'",
2210 should_not_match_message_1[] = {
2211 "type='method_call'",
2213 "type='method_return'",
2214 "type='signal',member='Oopsed'",
2221 "arg0='foobar',arg1='abcdef'",
2222 "arg0='foobar',arg1='abcdef',arg2='abcdefghi',arg3='abcdefghi',arg4='abcdefghi'",
2223 "arg0='foobar',arg1='abcdef',arg4='abcdefghi',arg3='abcdefghi',arg2='abcdefghi'",
2228 check_matches (dbus_bool_t expected_to_match,
2230 DBusMessage *message,
2231 const char *rule_text)
2234 dbus_bool_t matched;
2236 rule = check_parse (TRUE, rule_text);
2237 _dbus_assert (rule != NULL);
2239 /* We can't test sender/destination rules since we pass NULL here */
2240 matched = match_rule_matches (rule, NULL, NULL, message, 0);
2242 if (matched != expected_to_match)
2244 _dbus_warn ("Expected rule %s to %s message %d, failed\n",
2245 rule_text, expected_to_match ?
2246 "match" : "not match", number);
2250 bus_match_rule_unref (rule);
2254 check_matching (DBusMessage *message,
2256 const char **should_match,
2257 const char **should_not_match)
2262 while (should_match[i] != NULL)
2264 check_matches (TRUE, number, message, should_match[i]);
2269 while (should_not_match[i] != NULL)
2271 check_matches (FALSE, number, message, should_not_match[i]);
2277 test_matching (void)
2279 DBusMessage *message1;
2280 const char *v_STRING;
2281 dbus_int32_t v_INT32;
2283 message1 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL);
2284 _dbus_assert (message1 != NULL);
2285 if (!dbus_message_set_member (message1, "Frobated"))
2286 _dbus_assert_not_reached ("oom");
2288 v_STRING = "foobar";
2290 if (!dbus_message_append_args (message1,
2291 DBUS_TYPE_STRING, &v_STRING,
2292 DBUS_TYPE_INT32, &v_INT32,
2294 _dbus_assert_not_reached ("oom");
2296 check_matching (message1, 1,
2297 should_match_message_1,
2298 should_not_match_message_1);
2300 dbus_message_unref (message1);
2304 bus_signals_test (const DBusString *test_data_dir)
2306 BusMatchmaker *matchmaker;
2308 matchmaker = bus_matchmaker_new ();
2309 bus_matchmaker_ref (matchmaker);
2310 bus_matchmaker_unref (matchmaker);
2311 bus_matchmaker_unref (matchmaker);
2313 if (!_dbus_test_oom_handling ("parsing match rules", test_parsing, NULL))
2314 _dbus_assert_not_reached ("Parsing match rules test failed");
2323 #endif /* DBUS_BUILD_TESTS */