ofdbus/dbus/bus/signals.c
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 /* -*- mode: C; c-file-style: "gnu" -*- */
       
     2 /* signals.c  Bus signal connection implementation
       
     3  *
       
     4  * Copyright (C) 2003, 2005  Red Hat, Inc.
       
     5  * Portion Copyright © 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
       
     6  * Licensed under the Academic Free License version 2.1
       
     7  *
       
     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.
       
    12  *
       
    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.
       
    17  *
       
    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    21  *
       
    22  */
       
    23 #include "signals.h"
       
    24 #include "services.h"
       
    25 #include "utils.h"
       
    26 #ifndef __SYMBIAN32__
       
    27 #include <dbus/dbus-marshal-validate.h>
       
    28 #else
       
    29 #include "dbus-marshal-validate.h"
       
    30 #include "config.h"
       
    31 #endif //__SYMBIAN32__
       
    32 
       
    33 struct BusMatchRule
       
    34 {
       
    35   int refcount;       /**< reference count */
       
    36 
       
    37   DBusConnection *matches_go_to; /**< Owner of the rule */
       
    38 
       
    39   unsigned int flags; /**< BusMatchFlags */
       
    40 
       
    41   int   message_type;
       
    42   char *interface;
       
    43   char *member;
       
    44   char *sender;
       
    45   char *destination;
       
    46   char *path;
       
    47 
       
    48   char **args;
       
    49   int args_len;
       
    50 };
       
    51 
       
    52 BusMatchRule*
       
    53 bus_match_rule_new (DBusConnection *matches_go_to)
       
    54 {
       
    55   BusMatchRule *rule;
       
    56 
       
    57   rule = dbus_new0 (BusMatchRule, 1);
       
    58   if (rule == NULL)
       
    59     return NULL;
       
    60 
       
    61   rule->refcount = 1;
       
    62   rule->matches_go_to = matches_go_to;
       
    63 
       
    64 #ifndef DBUS_BUILD_TESTS
       
    65   _dbus_assert (rule->matches_go_to != NULL);
       
    66 #endif
       
    67   
       
    68   return rule;
       
    69 }
       
    70 
       
    71 BusMatchRule *
       
    72 bus_match_rule_ref (BusMatchRule *rule)
       
    73 {
       
    74   _dbus_assert (rule->refcount > 0);
       
    75 
       
    76   rule->refcount += 1;
       
    77 
       
    78   return rule;
       
    79 }
       
    80 
       
    81 void
       
    82 bus_match_rule_unref (BusMatchRule *rule)
       
    83 {
       
    84   _dbus_assert (rule->refcount > 0);
       
    85 
       
    86   rule->refcount -= 1;
       
    87   if (rule->refcount == 0)
       
    88     {
       
    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 
       
    95       /* can't use dbus_free_string_array() since there
       
    96        * are embedded NULL
       
    97        */
       
    98       if (rule->args)
       
    99         {
       
   100           int i;
       
   101 
       
   102           i = 0;
       
   103           while (i < rule->args_len)
       
   104             {
       
   105               if (rule->args[i])
       
   106                 dbus_free (rule->args[i]);
       
   107               ++i;
       
   108             }
       
   109 
       
   110           dbus_free (rule->args);
       
   111         }
       
   112       
       
   113       dbus_free (rule);
       
   114     }
       
   115 }
       
   116 
       
   117 #ifdef DBUS_ENABLE_VERBOSE_MODE
       
   118 /* Note this function does not do escaping, so it's only
       
   119  * good for debug spew at the moment
       
   120  */
       
   121 static char*
       
   122 match_rule_to_string (BusMatchRule *rule)
       
   123 {
       
   124   DBusString str;
       
   125   char *ret;
       
   126   
       
   127   if (!_dbus_string_init (&str))
       
   128     {
       
   129       char *s;
       
   130       while ((s = _dbus_strdup ("nomem")) == NULL)
       
   131         ; /* only OK for debug spew... */
       
   132       return s;
       
   133     }
       
   134   
       
   135   if (rule->flags & BUS_MATCH_MESSAGE_TYPE)
       
   136     {
       
   137       /* FIXME make type readable */
       
   138       if (!_dbus_string_append_printf (&str, "type='%d'", rule->message_type))
       
   139         goto nomem;
       
   140     }
       
   141 
       
   142   if (rule->flags & BUS_MATCH_INTERFACE)
       
   143     {
       
   144       if (_dbus_string_get_length (&str) > 0)
       
   145         {
       
   146           if (!_dbus_string_append (&str, ","))
       
   147             goto nomem;
       
   148         }
       
   149       
       
   150       if (!_dbus_string_append_printf (&str, "interface='%s'", rule->interface))
       
   151         goto nomem;
       
   152     }
       
   153 
       
   154   if (rule->flags & BUS_MATCH_MEMBER)
       
   155     {
       
   156       if (_dbus_string_get_length (&str) > 0)
       
   157         {
       
   158           if (!_dbus_string_append (&str, ","))
       
   159             goto nomem;
       
   160         }
       
   161       
       
   162       if (!_dbus_string_append_printf (&str, "member='%s'", rule->member))
       
   163         goto nomem;
       
   164     }
       
   165 
       
   166   if (rule->flags & BUS_MATCH_PATH)
       
   167     {
       
   168       if (_dbus_string_get_length (&str) > 0)
       
   169         {
       
   170           if (!_dbus_string_append (&str, ","))
       
   171             goto nomem;
       
   172         }
       
   173       
       
   174       if (!_dbus_string_append_printf (&str, "path='%s'", rule->path))
       
   175         goto nomem;
       
   176     }
       
   177 
       
   178   if (rule->flags & BUS_MATCH_SENDER)
       
   179     {
       
   180       if (_dbus_string_get_length (&str) > 0)
       
   181         {
       
   182           if (!_dbus_string_append (&str, ","))
       
   183             goto nomem;
       
   184         }
       
   185       
       
   186       if (!_dbus_string_append_printf (&str, "sender='%s'", rule->sender))
       
   187         goto nomem;
       
   188     }
       
   189 
       
   190   if (rule->flags & BUS_MATCH_DESTINATION)
       
   191     {
       
   192       if (_dbus_string_get_length (&str) > 0)
       
   193         {
       
   194           if (!_dbus_string_append (&str, ","))
       
   195             goto nomem;
       
   196         }
       
   197       
       
   198       if (!_dbus_string_append_printf (&str, "destination='%s'", rule->destination))
       
   199         goto nomem;
       
   200     }
       
   201 
       
   202   if (rule->flags & BUS_MATCH_ARGS)
       
   203     {
       
   204       int i;
       
   205       
       
   206       _dbus_assert (rule->args != NULL);
       
   207 
       
   208       i = 0;
       
   209       while (i < rule->args_len)
       
   210         {
       
   211           if (rule->args[i] != NULL)
       
   212             {
       
   213               if (_dbus_string_get_length (&str) > 0)
       
   214                 {
       
   215                   if (!_dbus_string_append (&str, ","))
       
   216                     goto nomem;
       
   217                 }
       
   218               
       
   219               if (!_dbus_string_append_printf (&str,
       
   220                                                "arg%d='%s'",
       
   221                                                i,
       
   222                                                rule->args[i]))
       
   223                 goto nomem;
       
   224             }
       
   225           
       
   226           ++i;
       
   227         }
       
   228     }
       
   229   
       
   230   if (!_dbus_string_steal_data (&str, &ret))
       
   231     goto nomem;
       
   232 
       
   233   _dbus_string_free (&str);
       
   234   return ret;
       
   235   
       
   236  nomem:
       
   237   _dbus_string_free (&str);
       
   238   {
       
   239     char *s;
       
   240     while ((s = _dbus_strdup ("nomem")) == NULL)
       
   241       ;  /* only OK for debug spew... */
       
   242     return s;
       
   243   }
       
   244 }
       
   245 #endif /* DBUS_ENABLE_VERBOSE_MODE */
       
   246 
       
   247 dbus_bool_t
       
   248 bus_match_rule_set_message_type (BusMatchRule *rule,
       
   249                                  int           type)
       
   250 {
       
   251   rule->flags |= BUS_MATCH_MESSAGE_TYPE;
       
   252 
       
   253   rule->message_type = type;
       
   254 
       
   255   return TRUE;
       
   256 }
       
   257 
       
   258 dbus_bool_t
       
   259 bus_match_rule_set_interface (BusMatchRule *rule,
       
   260                               const char   *interface)
       
   261 {
       
   262   char *new;
       
   263 
       
   264   _dbus_assert (interface != NULL);
       
   265 
       
   266   new = _dbus_strdup (interface);
       
   267   if (new == NULL)
       
   268     return FALSE;
       
   269 
       
   270   rule->flags |= BUS_MATCH_INTERFACE;
       
   271   dbus_free (rule->interface);
       
   272   rule->interface = new;
       
   273 
       
   274   return TRUE;
       
   275 }
       
   276 
       
   277 dbus_bool_t
       
   278 bus_match_rule_set_member (BusMatchRule *rule,
       
   279                            const char   *member)
       
   280 {
       
   281   char *new;
       
   282 
       
   283   _dbus_assert (member != NULL);
       
   284 
       
   285   new = _dbus_strdup (member);
       
   286   if (new == NULL)
       
   287     return FALSE;
       
   288 
       
   289   rule->flags |= BUS_MATCH_MEMBER;
       
   290   dbus_free (rule->member);
       
   291   rule->member = new;
       
   292 
       
   293   return TRUE;
       
   294 }
       
   295 
       
   296 dbus_bool_t
       
   297 bus_match_rule_set_sender (BusMatchRule *rule,
       
   298                            const char   *sender)
       
   299 {
       
   300   char *new;
       
   301 
       
   302   _dbus_assert (sender != NULL);
       
   303 
       
   304   new = _dbus_strdup (sender);
       
   305   if (new == NULL)
       
   306     return FALSE;
       
   307 
       
   308   rule->flags |= BUS_MATCH_SENDER;
       
   309   dbus_free (rule->sender);
       
   310   rule->sender = new;
       
   311 
       
   312   return TRUE;
       
   313 }
       
   314 
       
   315 dbus_bool_t
       
   316 bus_match_rule_set_destination (BusMatchRule *rule,
       
   317                                 const char   *destination)
       
   318 {
       
   319   char *new;
       
   320 
       
   321   _dbus_assert (destination != NULL);
       
   322 
       
   323   new = _dbus_strdup (destination);
       
   324   if (new == NULL)
       
   325     return FALSE;
       
   326 
       
   327   rule->flags |= BUS_MATCH_DESTINATION;
       
   328   dbus_free (rule->destination);
       
   329   rule->destination = new;
       
   330 
       
   331   return TRUE;
       
   332 }
       
   333 
       
   334 dbus_bool_t
       
   335 bus_match_rule_set_path (BusMatchRule *rule,
       
   336                          const char   *path)
       
   337 {
       
   338   char *new;
       
   339 
       
   340   _dbus_assert (path != NULL);
       
   341 
       
   342   new = _dbus_strdup (path);
       
   343   if (new == NULL)
       
   344     return FALSE;
       
   345 
       
   346   rule->flags |= BUS_MATCH_PATH;
       
   347   dbus_free (rule->path);
       
   348   rule->path = new;
       
   349 
       
   350   return TRUE;
       
   351 }
       
   352 
       
   353 dbus_bool_t
       
   354 bus_match_rule_set_arg (BusMatchRule *rule,
       
   355                         int           arg,
       
   356                         const char   *value)
       
   357 {
       
   358   char *new;
       
   359 
       
   360   _dbus_assert (value != NULL);
       
   361 
       
   362   new = _dbus_strdup (value);
       
   363   if (new == NULL)
       
   364     return FALSE;
       
   365 
       
   366   /* args_len is the number of args not including null termination
       
   367    * in the char**
       
   368    */
       
   369   if (arg >= rule->args_len)
       
   370     {
       
   371       char **new_args;
       
   372       int new_args_len;
       
   373       int i;
       
   374 
       
   375       new_args_len = arg + 1;
       
   376 
       
   377       /* add another + 1 here for null termination */
       
   378       new_args = dbus_realloc (rule->args,
       
   379                                sizeof(rule->args[0]) * (new_args_len + 1));
       
   380       if (new_args == NULL)
       
   381         {
       
   382           dbus_free (new);
       
   383           return FALSE;
       
   384         }
       
   385 
       
   386       /* NULL the new slots */
       
   387       i = rule->args_len;
       
   388       while (i <= new_args_len) /* <= for null termination */
       
   389         {
       
   390           new_args[i] = NULL;
       
   391           ++i;
       
   392         }
       
   393       
       
   394       rule->args = new_args;
       
   395       rule->args_len = new_args_len;
       
   396     }
       
   397 
       
   398   rule->flags |= BUS_MATCH_ARGS;
       
   399 
       
   400   dbus_free (rule->args[arg]);
       
   401   rule->args[arg] = new;
       
   402 
       
   403   /* NULL termination didn't get busted */
       
   404   _dbus_assert (rule->args[rule->args_len] == NULL);
       
   405 
       
   406   return TRUE;
       
   407 }
       
   408 
       
   409 #define ISWHITE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\n') || ((c) == '\r'))
       
   410 
       
   411 static dbus_bool_t
       
   412 find_key (const DBusString *str,
       
   413           int               start,
       
   414           DBusString       *key,
       
   415           int              *value_pos,
       
   416           DBusError        *error)
       
   417 {
       
   418   const char *p;
       
   419   const char *s;
       
   420   const char *key_start;
       
   421   const char *key_end;
       
   422 
       
   423   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
       
   424   
       
   425   s = _dbus_string_get_const_data (str);
       
   426 
       
   427   p = s + start;
       
   428 
       
   429   while (*p && ISWHITE (*p))
       
   430     ++p;
       
   431 
       
   432   key_start = p;
       
   433 
       
   434   while (*p && *p != '=' && !ISWHITE (*p))
       
   435     ++p;
       
   436 
       
   437   key_end = p;
       
   438 
       
   439   while (*p && ISWHITE (*p))
       
   440     ++p;
       
   441   
       
   442   if (key_start == key_end)
       
   443     {
       
   444       /* Empty match rules or trailing whitespace are OK */
       
   445       *value_pos = p - s;
       
   446       return TRUE;
       
   447     }
       
   448 
       
   449   if (*p != '=')
       
   450     {
       
   451       dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
       
   452                       "Match rule has a key with no subsequent '=' character");
       
   453       return FALSE;
       
   454     }
       
   455   ++p;
       
   456   
       
   457   if (!_dbus_string_append_len (key, key_start, key_end - key_start))
       
   458     {
       
   459       BUS_SET_OOM (error);
       
   460       return FALSE;
       
   461     }
       
   462 
       
   463   *value_pos = p - s;
       
   464   
       
   465   return TRUE;
       
   466 }
       
   467 
       
   468 static dbus_bool_t
       
   469 find_value (const DBusString *str,
       
   470             int               start,
       
   471             const char       *key,
       
   472             DBusString       *value,
       
   473             int              *value_end,
       
   474             DBusError        *error)
       
   475 {
       
   476   const char *p;
       
   477   const char *s;
       
   478   char quote_char;
       
   479   int orig_len;
       
   480 
       
   481   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
       
   482   
       
   483   orig_len = _dbus_string_get_length (value);
       
   484   
       
   485   s = _dbus_string_get_const_data (str);
       
   486 
       
   487   p = s + start;
       
   488 
       
   489   quote_char = '\0';
       
   490 
       
   491   while (*p)
       
   492     {
       
   493       if (quote_char == '\0')
       
   494         {
       
   495           switch (*p)
       
   496             {
       
   497             case '\0':
       
   498               goto done;
       
   499 
       
   500             case '\'':
       
   501               quote_char = '\'';
       
   502               goto next;
       
   503               
       
   504             case ',':
       
   505               ++p;
       
   506               goto done;
       
   507 
       
   508             case '\\':
       
   509               quote_char = '\\';
       
   510               goto next;
       
   511               
       
   512             default:
       
   513               if (!_dbus_string_append_byte (value, *p))
       
   514                 {
       
   515                   BUS_SET_OOM (error);
       
   516                   goto failed;
       
   517                 }
       
   518             }
       
   519         }
       
   520       else if (quote_char == '\\')
       
   521         {
       
   522           /* \ only counts as an escape if escaping a quote mark */
       
   523           if (*p != '\'')
       
   524             {
       
   525               if (!_dbus_string_append_byte (value, '\\'))
       
   526                 {
       
   527                   BUS_SET_OOM (error);
       
   528                   goto failed;
       
   529                 }
       
   530             }
       
   531 
       
   532           if (!_dbus_string_append_byte (value, *p))
       
   533             {
       
   534               BUS_SET_OOM (error);
       
   535               goto failed;
       
   536             }
       
   537           
       
   538           quote_char = '\0';
       
   539         }
       
   540       else
       
   541         {
       
   542           _dbus_assert (quote_char == '\'');
       
   543 
       
   544           if (*p == '\'')
       
   545             {
       
   546               quote_char = '\0';
       
   547             }
       
   548           else
       
   549             {
       
   550               if (!_dbus_string_append_byte (value, *p))
       
   551                 {
       
   552                   BUS_SET_OOM (error);
       
   553                   goto failed;
       
   554                 }
       
   555             }
       
   556         }
       
   557 
       
   558     next:
       
   559       ++p;
       
   560     }
       
   561 
       
   562  done:
       
   563 
       
   564   if (quote_char == '\\')
       
   565     {
       
   566       if (!_dbus_string_append_byte (value, '\\'))
       
   567         {
       
   568           BUS_SET_OOM (error);
       
   569           goto failed;
       
   570         }
       
   571     }
       
   572   else if (quote_char == '\'')
       
   573     {
       
   574       dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
       
   575                       "Unbalanced quotation marks in match rule");
       
   576       goto failed;
       
   577     }
       
   578   else
       
   579     _dbus_assert (quote_char == '\0');
       
   580 
       
   581   /* Zero-length values are allowed */
       
   582   
       
   583   *value_end = p - s;
       
   584   
       
   585   return TRUE;
       
   586 
       
   587  failed:
       
   588   _DBUS_ASSERT_ERROR_IS_SET (error);
       
   589   _dbus_string_set_length (value, orig_len);
       
   590   return FALSE;
       
   591 }
       
   592 
       
   593 /* duplicates aren't allowed so the real legitimate max is only 6 or
       
   594  * so. Leaving extra so we don't have to bother to update it.
       
   595  * FIXME this is sort of busted now with arg matching, but we let
       
   596  * you match on up to 10 args for now
       
   597  */
       
   598 #define MAX_RULE_TOKENS 16
       
   599 
       
   600 /* this is slightly too high level to be termed a "token"
       
   601  * but let's not be pedantic.
       
   602  */
       
   603 typedef struct
       
   604 {
       
   605   char *key;
       
   606   char *value;
       
   607 } RuleToken;
       
   608 
       
   609 static dbus_bool_t
       
   610 tokenize_rule (const DBusString *rule_text,
       
   611                RuleToken         tokens[MAX_RULE_TOKENS],
       
   612                DBusError        *error) 
       
   613 {
       
   614   int i;
       
   615   int pos;
       
   616   DBusString key;
       
   617   DBusString value;
       
   618   dbus_bool_t retval;
       
   619 
       
   620   retval = FALSE;
       
   621   
       
   622   if (!_dbus_string_init (&key))
       
   623     {
       
   624       BUS_SET_OOM (error);
       
   625       return FALSE;
       
   626     }
       
   627 
       
   628   if (!_dbus_string_init (&value))
       
   629     {
       
   630       _dbus_string_free (&key);
       
   631       BUS_SET_OOM (error);
       
   632       return FALSE;
       
   633     }
       
   634 
       
   635   i = 0;
       
   636   pos = 0;
       
   637   while (i < MAX_RULE_TOKENS &&
       
   638          pos < _dbus_string_get_length (rule_text))
       
   639     {
       
   640       _dbus_assert (tokens[i].key == NULL);
       
   641       _dbus_assert (tokens[i].value == NULL);
       
   642 
       
   643       if (!find_key (rule_text, pos, &key, &pos, error))
       
   644         goto out;
       
   645 
       
   646       if (_dbus_string_get_length (&key) == 0)
       
   647         goto next;
       
   648       
       
   649       if (!_dbus_string_steal_data (&key, &tokens[i].key))
       
   650         {
       
   651           BUS_SET_OOM (error);
       
   652           goto out;
       
   653         }
       
   654 
       
   655       if (!find_value (rule_text, pos, tokens[i].key, &value, &pos, error))
       
   656         goto out;
       
   657 
       
   658       if (!_dbus_string_steal_data (&value, &tokens[i].value))
       
   659         {
       
   660           BUS_SET_OOM (error);
       
   661           goto out;
       
   662         }
       
   663 
       
   664     next:
       
   665       ++i;
       
   666     }
       
   667 
       
   668   retval = TRUE;
       
   669   
       
   670  out:
       
   671   if (!retval)
       
   672     {
       
   673       i = 0;
       
   674       while (tokens[i].key || tokens[i].value)
       
   675         {
       
   676           dbus_free (tokens[i].key);
       
   677           dbus_free (tokens[i].value);
       
   678           tokens[i].key = NULL;
       
   679           tokens[i].value = NULL;
       
   680           ++i;
       
   681         }
       
   682     }
       
   683   
       
   684   _dbus_string_free (&key);
       
   685   _dbus_string_free (&value);
       
   686   
       
   687   return retval;
       
   688 }
       
   689 
       
   690 static dbus_bool_t
       
   691 bus_match_rule_parse_arg_match (BusMatchRule     *rule,
       
   692                                 const char       *key,
       
   693                                 const DBusString *value,
       
   694                                 DBusError        *error)
       
   695 {
       
   696   DBusString key_str;
       
   697   unsigned long arg;
       
   698   int end;
       
   699 
       
   700   /* For now, arg0='foo' always implies that 'foo' is a
       
   701    * DBUS_TYPE_STRING. Someday we could add an arg0type='int32' thing
       
   702    * if we wanted, which would specify another type, in which case
       
   703    * arg0='5' would have the 5 parsed as an int rather than string.
       
   704    */
       
   705   
       
   706   /* First we need to parse arg0 = 0, arg27 = 27 */
       
   707 
       
   708   _dbus_string_init_const (&key_str, key);
       
   709 
       
   710   if (_dbus_string_get_length (&key_str) < 4)
       
   711     {
       
   712       dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
       
   713                       "Key '%s' in match rule starts with 'arg' but lacks an arg number. Should be 'arg0' or 'arg7' for example.\n", key);
       
   714       goto failed;
       
   715     }
       
   716 
       
   717   if (!_dbus_string_parse_uint (&key_str, 3, &arg, &end) ||
       
   718       end != _dbus_string_get_length (&key_str))
       
   719     {
       
   720       dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
       
   721                       "Key '%s' in match rule starts with 'arg' but could not parse arg number. Should be 'arg0' or 'arg7' for example.\n", key);
       
   722       goto failed;
       
   723     }
       
   724 
       
   725   /* If we didn't check this we could allocate a huge amount of RAM */
       
   726   if (arg > DBUS_MAXIMUM_MATCH_RULE_ARG_NUMBER)
       
   727     {
       
   728       dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
       
   729                       "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);
       
   730       goto failed;
       
   731     }
       
   732   
       
   733   if ((rule->flags & BUS_MATCH_ARGS) &&
       
   734       rule->args_len > (int) arg &&
       
   735       rule->args[arg] != NULL)
       
   736     {
       
   737       dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
       
   738                       "Key '%s' specified twice in match rule\n", key);
       
   739       goto failed;
       
   740     }
       
   741   
       
   742   if (!bus_match_rule_set_arg (rule, arg,
       
   743                                _dbus_string_get_const_data (value)))
       
   744     {
       
   745       BUS_SET_OOM (error);
       
   746       goto failed;
       
   747     }
       
   748 
       
   749   return TRUE;
       
   750 
       
   751  failed:
       
   752   _DBUS_ASSERT_ERROR_IS_SET (error);
       
   753   return FALSE;
       
   754 }
       
   755 
       
   756 /*
       
   757  * The format is comma-separated with strings quoted with single quotes
       
   758  * as for the shell (to escape a literal single quote, use '\'').
       
   759  *
       
   760  * type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='Foo',
       
   761  * path='/bar/foo',destination=':452345.34'
       
   762  *
       
   763  */
       
   764 BusMatchRule*
       
   765 bus_match_rule_parse (DBusConnection   *matches_go_to,
       
   766                       const DBusString *rule_text,
       
   767                       DBusError        *error)
       
   768 {
       
   769   BusMatchRule *rule;
       
   770   RuleToken tokens[MAX_RULE_TOKENS+1]; /* NULL termination + 1 */
       
   771   int i;
       
   772   
       
   773   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
       
   774 
       
   775   if (_dbus_string_get_length (rule_text) > DBUS_MAXIMUM_MATCH_RULE_LENGTH)
       
   776     {
       
   777       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
       
   778                       "Match rule text is %d bytes, maximum is %d",
       
   779                       _dbus_string_get_length (rule_text),
       
   780                       DBUS_MAXIMUM_MATCH_RULE_LENGTH);
       
   781       return NULL;
       
   782     }
       
   783   
       
   784   memset (tokens, '\0', sizeof (tokens));
       
   785   
       
   786   rule = bus_match_rule_new (matches_go_to);
       
   787   if (rule == NULL)
       
   788     {
       
   789       BUS_SET_OOM (error);
       
   790       goto failed;
       
   791     }
       
   792   
       
   793   if (!tokenize_rule (rule_text, tokens, error))
       
   794     goto failed;
       
   795   
       
   796   i = 0;
       
   797   while (tokens[i].key != NULL)
       
   798     {
       
   799       DBusString tmp_str;
       
   800       int len;
       
   801       const char *key = tokens[i].key;
       
   802       const char *value = tokens[i].value;
       
   803       
       
   804       _dbus_string_init_const (&tmp_str, value);
       
   805       len = _dbus_string_get_length (&tmp_str);
       
   806 
       
   807       if (strcmp (key, "type") == 0)
       
   808         {
       
   809           int t;
       
   810 
       
   811           if (rule->flags & BUS_MATCH_MESSAGE_TYPE)
       
   812             {
       
   813               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
       
   814                               "Key %s specified twice in match rule\n", key);
       
   815               goto failed;
       
   816             }
       
   817           
       
   818           t = dbus_message_type_from_string (value);
       
   819           
       
   820           if (t == DBUS_MESSAGE_TYPE_INVALID)
       
   821             {
       
   822               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
       
   823                               "Invalid message type (%s) in match rule\n", value);
       
   824               goto failed;
       
   825             }
       
   826 
       
   827           if (!bus_match_rule_set_message_type (rule, t))
       
   828             {
       
   829               BUS_SET_OOM (error);
       
   830               goto failed;
       
   831             }
       
   832         }
       
   833       else if (strcmp (key, "sender") == 0)
       
   834         {
       
   835           if (rule->flags & BUS_MATCH_SENDER)
       
   836             {
       
   837               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
       
   838                               "Key %s specified twice in match rule\n", key);
       
   839               goto failed;
       
   840             }
       
   841 
       
   842           if (!_dbus_validate_bus_name (&tmp_str, 0, len))
       
   843             {
       
   844               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
       
   845                               "Sender name '%s' is invalid\n", value);
       
   846               goto failed;
       
   847             }
       
   848 
       
   849           if (!bus_match_rule_set_sender (rule, value))
       
   850             {
       
   851               BUS_SET_OOM (error);
       
   852               goto failed;
       
   853             }
       
   854         }
       
   855       else if (strcmp (key, "interface") == 0)
       
   856         {
       
   857           if (rule->flags & BUS_MATCH_INTERFACE)
       
   858             {
       
   859               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
       
   860                               "Key %s specified twice in match rule\n", key);
       
   861               goto failed;
       
   862             }
       
   863 
       
   864           if (!_dbus_validate_interface (&tmp_str, 0, len))
       
   865             {
       
   866               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
       
   867                               "Interface name '%s' is invalid\n", value);
       
   868               goto failed;
       
   869             }
       
   870 
       
   871           if (!bus_match_rule_set_interface (rule, value))
       
   872             {
       
   873               BUS_SET_OOM (error);
       
   874               goto failed;
       
   875             }
       
   876         }
       
   877       else if (strcmp (key, "member") == 0)
       
   878         {
       
   879           if (rule->flags & BUS_MATCH_MEMBER)
       
   880             {
       
   881               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
       
   882                               "Key %s specified twice in match rule\n", key);
       
   883               goto failed;
       
   884             }
       
   885 
       
   886           if (!_dbus_validate_member (&tmp_str, 0, len))
       
   887             {
       
   888               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
       
   889                               "Member name '%s' is invalid\n", value);
       
   890               goto failed;
       
   891             }
       
   892 
       
   893           if (!bus_match_rule_set_member (rule, value))
       
   894             {
       
   895               BUS_SET_OOM (error);
       
   896               goto failed;
       
   897             }
       
   898         }
       
   899       else if (strcmp (key, "path") == 0)
       
   900         {
       
   901           if (rule->flags & BUS_MATCH_PATH)
       
   902             {
       
   903               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
       
   904                               "Key %s specified twice in match rule\n", key);
       
   905               goto failed;
       
   906             }
       
   907 
       
   908           if (!_dbus_validate_path (&tmp_str, 0, len))
       
   909             {
       
   910               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
       
   911                               "Path '%s' is invalid\n", value);
       
   912               goto failed;
       
   913             }
       
   914 
       
   915           if (!bus_match_rule_set_path (rule, value))
       
   916             {
       
   917               BUS_SET_OOM (error);
       
   918               goto failed;
       
   919             }
       
   920         }
       
   921       else if (strcmp (key, "destination") == 0)
       
   922         {
       
   923           if (rule->flags & BUS_MATCH_DESTINATION)
       
   924             {
       
   925               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
       
   926                               "Key %s specified twice in match rule\n", key);
       
   927               goto failed;
       
   928             }
       
   929 
       
   930           if (!_dbus_validate_bus_name (&tmp_str, 0, len))
       
   931             {
       
   932               dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
       
   933                               "Destination name '%s' is invalid\n", value);
       
   934               goto failed;
       
   935             }
       
   936 
       
   937           if (!bus_match_rule_set_destination (rule, value))
       
   938             {
       
   939               BUS_SET_OOM (error);
       
   940               goto failed;
       
   941             }
       
   942         }
       
   943       else if (strncmp (key, "arg", 3) == 0)
       
   944         {
       
   945           if (!bus_match_rule_parse_arg_match (rule, key, &tmp_str, error))
       
   946             goto failed;
       
   947         }
       
   948       else
       
   949         {
       
   950           dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
       
   951                           "Unknown key \"%s\" in match rule",
       
   952                           key);
       
   953           goto failed;
       
   954         }
       
   955 
       
   956       ++i;
       
   957     }
       
   958   
       
   959 
       
   960   goto out;
       
   961   
       
   962  failed:
       
   963   _DBUS_ASSERT_ERROR_IS_SET (error);
       
   964   if (rule)
       
   965     {
       
   966       bus_match_rule_unref (rule);
       
   967       rule = NULL;
       
   968     }
       
   969 
       
   970  out:
       
   971   
       
   972   i = 0;
       
   973   while (tokens[i].key || tokens[i].value)
       
   974     {
       
   975       _dbus_assert (i < MAX_RULE_TOKENS);
       
   976       dbus_free (tokens[i].key);
       
   977       dbus_free (tokens[i].value);
       
   978       ++i;
       
   979     }
       
   980   
       
   981   return rule;
       
   982 }
       
   983 
       
   984 struct BusMatchmaker
       
   985 {
       
   986   int refcount;
       
   987 
       
   988   DBusList *all_rules;
       
   989 };
       
   990 
       
   991 BusMatchmaker*
       
   992 bus_matchmaker_new (void)
       
   993 {
       
   994   BusMatchmaker *matchmaker;
       
   995 
       
   996   matchmaker = dbus_new0 (BusMatchmaker, 1);
       
   997   if (matchmaker == NULL)
       
   998     return NULL;
       
   999 
       
  1000   matchmaker->refcount = 1;
       
  1001   
       
  1002   return matchmaker;
       
  1003 }
       
  1004 
       
  1005 BusMatchmaker *
       
  1006 bus_matchmaker_ref (BusMatchmaker *matchmaker)
       
  1007 {
       
  1008   _dbus_assert (matchmaker->refcount > 0);
       
  1009 
       
  1010   matchmaker->refcount += 1;
       
  1011 
       
  1012   return matchmaker;
       
  1013 }
       
  1014 
       
  1015 void
       
  1016 bus_matchmaker_unref (BusMatchmaker *matchmaker)
       
  1017 {
       
  1018   _dbus_assert (matchmaker->refcount > 0);
       
  1019 
       
  1020   matchmaker->refcount -= 1;
       
  1021   if (matchmaker->refcount == 0)
       
  1022     {
       
  1023       while (matchmaker->all_rules != NULL)
       
  1024         {
       
  1025           BusMatchRule *rule;
       
  1026 
       
  1027           rule = matchmaker->all_rules->data;
       
  1028           bus_match_rule_unref (rule);
       
  1029           _dbus_list_remove_link (&matchmaker->all_rules,
       
  1030                                   matchmaker->all_rules);
       
  1031         }
       
  1032 
       
  1033       dbus_free (matchmaker);
       
  1034     }
       
  1035 }
       
  1036 
       
  1037 /* The rule can't be modified after it's added. */
       
  1038 dbus_bool_t
       
  1039 bus_matchmaker_add_rule (BusMatchmaker   *matchmaker,
       
  1040                          BusMatchRule    *rule)
       
  1041 {
       
  1042   _dbus_assert (bus_connection_is_active (rule->matches_go_to));
       
  1043 
       
  1044   if (!_dbus_list_append (&matchmaker->all_rules, rule))
       
  1045     return FALSE;
       
  1046 
       
  1047   if (!bus_connection_add_match_rule (rule->matches_go_to, rule))
       
  1048     {
       
  1049       _dbus_list_remove_last (&matchmaker->all_rules, rule);
       
  1050       return FALSE;
       
  1051     }
       
  1052   
       
  1053   bus_match_rule_ref (rule);
       
  1054 
       
  1055 #ifdef DBUS_ENABLE_VERBOSE_MODE
       
  1056   {
       
  1057     char *s = match_rule_to_string (rule);
       
  1058 
       
  1059     _dbus_verbose ("Added match rule %s to connection %p\n",
       
  1060                    s, rule->matches_go_to);
       
  1061     dbus_free (s);
       
  1062   }
       
  1063 #endif
       
  1064   
       
  1065   return TRUE;
       
  1066 }
       
  1067 
       
  1068 static dbus_bool_t
       
  1069 match_rule_equal (BusMatchRule *a,
       
  1070                   BusMatchRule *b)
       
  1071 {
       
  1072   if (a->flags != b->flags)
       
  1073     return FALSE;
       
  1074 
       
  1075   if (a->matches_go_to != b->matches_go_to)
       
  1076     return FALSE;
       
  1077 
       
  1078   if ((a->flags & BUS_MATCH_MESSAGE_TYPE) &&
       
  1079       a->message_type != b->message_type)
       
  1080     return FALSE;
       
  1081 
       
  1082   if ((a->flags & BUS_MATCH_MEMBER) &&
       
  1083       strcmp (a->member, b->member) != 0)
       
  1084     return FALSE;
       
  1085 
       
  1086   if ((a->flags & BUS_MATCH_PATH) &&
       
  1087       strcmp (a->path, b->path) != 0)
       
  1088     return FALSE;
       
  1089   
       
  1090   if ((a->flags & BUS_MATCH_INTERFACE) &&
       
  1091       strcmp (a->interface, b->interface) != 0)
       
  1092     return FALSE;
       
  1093 
       
  1094   if ((a->flags & BUS_MATCH_SENDER) &&
       
  1095       strcmp (a->sender, b->sender) != 0)
       
  1096     return FALSE;
       
  1097 
       
  1098   if ((a->flags & BUS_MATCH_DESTINATION) &&
       
  1099       strcmp (a->destination, b->destination) != 0)
       
  1100     return FALSE;
       
  1101 
       
  1102   if (a->flags & BUS_MATCH_ARGS)
       
  1103     {
       
  1104       int i;
       
  1105       
       
  1106       if (a->args_len != b->args_len)
       
  1107         return FALSE;
       
  1108       
       
  1109       i = 0;
       
  1110       while (i < a->args_len)
       
  1111         {
       
  1112           if ((a->args[i] != NULL) != (b->args[i] != NULL))
       
  1113             return FALSE;
       
  1114 
       
  1115           if (a->args[i] != NULL)
       
  1116             {
       
  1117               _dbus_assert (b->args[i] != NULL);
       
  1118               if (strcmp (a->args[i], b->args[i]) != 0)
       
  1119                 return FALSE;
       
  1120             }
       
  1121           
       
  1122           ++i;
       
  1123         }
       
  1124     }
       
  1125   
       
  1126   return TRUE;
       
  1127 }
       
  1128 
       
  1129 static void
       
  1130 bus_matchmaker_remove_rule_link (BusMatchmaker   *matchmaker,
       
  1131                                  DBusList        *link)
       
  1132 {
       
  1133   BusMatchRule *rule = link->data;
       
  1134   
       
  1135   bus_connection_remove_match_rule (rule->matches_go_to, rule);
       
  1136   _dbus_list_remove_link (&matchmaker->all_rules, link);
       
  1137 
       
  1138 #ifdef DBUS_ENABLE_VERBOSE_MODE
       
  1139   {
       
  1140     char *s = match_rule_to_string (rule);
       
  1141 
       
  1142     _dbus_verbose ("Removed match rule %s for connection %p\n",
       
  1143                    s, rule->matches_go_to);
       
  1144     dbus_free (s);
       
  1145   }
       
  1146 #endif
       
  1147   
       
  1148   bus_match_rule_unref (rule);  
       
  1149 }
       
  1150 
       
  1151 void
       
  1152 bus_matchmaker_remove_rule (BusMatchmaker   *matchmaker,
       
  1153                             BusMatchRule    *rule)
       
  1154 {
       
  1155   bus_connection_remove_match_rule (rule->matches_go_to, rule);
       
  1156   _dbus_list_remove (&matchmaker->all_rules, rule);
       
  1157 
       
  1158 #ifdef DBUS_ENABLE_VERBOSE_MODE
       
  1159   {
       
  1160     char *s = match_rule_to_string (rule);
       
  1161 
       
  1162     _dbus_verbose ("Removed match rule %s for connection %p\n",
       
  1163                    s, rule->matches_go_to);
       
  1164     dbus_free (s);
       
  1165   }
       
  1166 #endif
       
  1167   
       
  1168   bus_match_rule_unref (rule);
       
  1169 }
       
  1170 
       
  1171 /* Remove a single rule which is equal to the given rule by value */
       
  1172 dbus_bool_t
       
  1173 bus_matchmaker_remove_rule_by_value (BusMatchmaker   *matchmaker,
       
  1174                                      BusMatchRule    *value,
       
  1175                                      DBusError       *error)
       
  1176 {
       
  1177   /* FIXME this is an unoptimized linear scan */
       
  1178 
       
  1179   DBusList *link;
       
  1180 
       
  1181   /* we traverse backward because bus_connection_remove_match_rule()
       
  1182    * removes the most-recently-added rule
       
  1183    */
       
  1184   link = _dbus_list_get_last_link (&matchmaker->all_rules);
       
  1185   while (link != NULL)
       
  1186     {
       
  1187       BusMatchRule *rule;
       
  1188       DBusList *prev;
       
  1189 
       
  1190       rule = link->data;
       
  1191       prev = _dbus_list_get_prev_link (&matchmaker->all_rules, link);
       
  1192 
       
  1193       if (match_rule_equal (rule, value))
       
  1194         {
       
  1195           bus_matchmaker_remove_rule_link (matchmaker, link);
       
  1196           break;
       
  1197         }
       
  1198 
       
  1199       link = prev;
       
  1200     }
       
  1201 
       
  1202   if (link == NULL)
       
  1203     {
       
  1204       dbus_set_error (error, DBUS_ERROR_MATCH_RULE_NOT_FOUND,
       
  1205                       "The given match rule wasn't found and can't be removed");
       
  1206       return FALSE;
       
  1207     }
       
  1208 
       
  1209   return TRUE;
       
  1210 }
       
  1211 
       
  1212 void
       
  1213 bus_matchmaker_disconnected (BusMatchmaker   *matchmaker,
       
  1214                              DBusConnection  *disconnected)
       
  1215 {
       
  1216   DBusList *link;
       
  1217 
       
  1218   /* FIXME
       
  1219    *
       
  1220    * This scans all match rules on the bus. We could avoid that
       
  1221    * for the rules belonging to the connection, since we keep
       
  1222    * a list of those; but for the rules that just refer to
       
  1223    * the connection we'd need to do something more elaborate.
       
  1224    * 
       
  1225    */
       
  1226   
       
  1227   _dbus_assert (bus_connection_is_active (disconnected));
       
  1228 
       
  1229   link = _dbus_list_get_first_link (&matchmaker->all_rules);
       
  1230   while (link != NULL)
       
  1231     {
       
  1232       BusMatchRule *rule;
       
  1233       DBusList *next;
       
  1234 
       
  1235       rule = link->data;
       
  1236       next = _dbus_list_get_next_link (&matchmaker->all_rules, link);
       
  1237 
       
  1238       if (rule->matches_go_to == disconnected)
       
  1239         {
       
  1240           bus_matchmaker_remove_rule_link (matchmaker, link);
       
  1241         }
       
  1242       else if (((rule->flags & BUS_MATCH_SENDER) && *rule->sender == ':') ||
       
  1243                ((rule->flags & BUS_MATCH_DESTINATION) && *rule->destination == ':'))
       
  1244         {
       
  1245           /* The rule matches to/from a base service, see if it's the
       
  1246            * one being disconnected, since we know this service name
       
  1247            * will never be recycled.
       
  1248            */
       
  1249           const char *name;
       
  1250 
       
  1251           name = bus_connection_get_name (disconnected);
       
  1252           _dbus_assert (name != NULL); /* because we're an active connection */
       
  1253 
       
  1254           if (((rule->flags & BUS_MATCH_SENDER) &&
       
  1255                strcmp (rule->sender, name) == 0) ||
       
  1256               ((rule->flags & BUS_MATCH_DESTINATION) &&
       
  1257                strcmp (rule->destination, name) == 0))
       
  1258             {
       
  1259               bus_matchmaker_remove_rule_link (matchmaker, link);
       
  1260             }
       
  1261         }
       
  1262 
       
  1263       link = next;
       
  1264     }
       
  1265 }
       
  1266 
       
  1267 static dbus_bool_t
       
  1268 connection_is_primary_owner (DBusConnection *connection,
       
  1269                              const char     *service_name)
       
  1270 {
       
  1271   BusService *service;
       
  1272   DBusString str;
       
  1273   BusRegistry *registry;
       
  1274 
       
  1275   _dbus_assert (connection != NULL);
       
  1276   
       
  1277   registry = bus_connection_get_registry (connection);
       
  1278 
       
  1279   _dbus_string_init_const (&str, service_name);
       
  1280   service = bus_registry_lookup (registry, &str);
       
  1281 
       
  1282   if (service == NULL)
       
  1283     return FALSE; /* Service doesn't exist so connection can't own it. */
       
  1284 
       
  1285   return bus_service_get_primary_owners_connection (service) == connection;
       
  1286 }
       
  1287 
       
  1288 static dbus_bool_t
       
  1289 match_rule_matches (BusMatchRule    *rule,
       
  1290                     DBusConnection  *sender,
       
  1291                     DBusConnection  *addressed_recipient,
       
  1292                     DBusMessage     *message)
       
  1293 {
       
  1294   /* All features of the match rule are AND'd together,
       
  1295    * so FALSE if any of them don't match.
       
  1296    */
       
  1297 
       
  1298   /* sender/addressed_recipient of #NULL may mean bus driver,
       
  1299    * or for addressed_recipient may mean a message with no
       
  1300    * specific recipient (i.e. a signal)
       
  1301    */
       
  1302   
       
  1303   if (rule->flags & BUS_MATCH_MESSAGE_TYPE)
       
  1304     {
       
  1305       _dbus_assert (rule->message_type != DBUS_MESSAGE_TYPE_INVALID);
       
  1306 
       
  1307       if (rule->message_type != dbus_message_get_type (message))
       
  1308         return FALSE;
       
  1309     }
       
  1310 
       
  1311   if (rule->flags & BUS_MATCH_INTERFACE)
       
  1312     {
       
  1313       const char *iface;
       
  1314 
       
  1315       _dbus_assert (rule->interface != NULL);
       
  1316 
       
  1317       iface = dbus_message_get_interface (message);
       
  1318       if (iface == NULL)
       
  1319         return FALSE;
       
  1320 
       
  1321       if (strcmp (iface, rule->interface) != 0)
       
  1322         return FALSE;
       
  1323     }
       
  1324 
       
  1325   if (rule->flags & BUS_MATCH_MEMBER)
       
  1326     {
       
  1327       const char *member;
       
  1328 
       
  1329       _dbus_assert (rule->member != NULL);
       
  1330 
       
  1331       member = dbus_message_get_member (message);
       
  1332       if (member == NULL)
       
  1333         return FALSE;
       
  1334 
       
  1335       if (strcmp (member, rule->member) != 0)
       
  1336         return FALSE;
       
  1337     }
       
  1338 
       
  1339   if (rule->flags & BUS_MATCH_SENDER)
       
  1340     {
       
  1341       _dbus_assert (rule->sender != NULL);
       
  1342 
       
  1343       if (sender == NULL)
       
  1344         {
       
  1345           if (strcmp (rule->sender,
       
  1346                       DBUS_SERVICE_DBUS) != 0)
       
  1347             return FALSE;
       
  1348         }
       
  1349       else
       
  1350         {
       
  1351           if (!connection_is_primary_owner (sender, rule->sender))
       
  1352             return FALSE;
       
  1353         }
       
  1354     }
       
  1355 
       
  1356   if (rule->flags & BUS_MATCH_DESTINATION)
       
  1357     {
       
  1358       const char *destination;
       
  1359 
       
  1360       _dbus_assert (rule->destination != NULL);
       
  1361 
       
  1362       destination = dbus_message_get_destination (message);
       
  1363       if (destination == NULL)
       
  1364         return FALSE;
       
  1365 
       
  1366       if (addressed_recipient == NULL)
       
  1367         {          
       
  1368           if (strcmp (rule->destination,
       
  1369                       DBUS_SERVICE_DBUS) != 0)
       
  1370             return FALSE;
       
  1371         }
       
  1372       else
       
  1373         {
       
  1374           if (!connection_is_primary_owner (addressed_recipient, rule->destination))
       
  1375             return FALSE;
       
  1376         }
       
  1377     }
       
  1378 
       
  1379   if (rule->flags & BUS_MATCH_PATH)
       
  1380     {
       
  1381       const char *path;
       
  1382 
       
  1383       _dbus_assert (rule->path != NULL);
       
  1384 
       
  1385       path = dbus_message_get_path (message);
       
  1386       if (path == NULL)
       
  1387         return FALSE;
       
  1388 
       
  1389       if (strcmp (path, rule->path) != 0)
       
  1390         return FALSE;
       
  1391     }
       
  1392 
       
  1393   if (rule->flags & BUS_MATCH_ARGS)
       
  1394     {
       
  1395       int i;
       
  1396       DBusMessageIter iter;
       
  1397       
       
  1398       _dbus_assert (rule->args != NULL);
       
  1399 
       
  1400       dbus_message_iter_init (message, &iter);
       
  1401       
       
  1402       i = 0;
       
  1403       while (i < rule->args_len)
       
  1404         {
       
  1405           int current_type;
       
  1406           const char *expected_arg;
       
  1407 
       
  1408           expected_arg = rule->args[i];
       
  1409           
       
  1410           current_type = dbus_message_iter_get_arg_type (&iter);
       
  1411 
       
  1412           if (expected_arg != NULL)
       
  1413             {
       
  1414               const char *actual_arg;
       
  1415               
       
  1416               if (current_type != DBUS_TYPE_STRING)
       
  1417                 return FALSE;
       
  1418 
       
  1419               actual_arg = NULL;
       
  1420               dbus_message_iter_get_basic (&iter, &actual_arg);
       
  1421               _dbus_assert (actual_arg != NULL);
       
  1422 
       
  1423               if (strcmp (expected_arg, actual_arg) != 0)
       
  1424                 return FALSE;
       
  1425             }
       
  1426           
       
  1427           if (current_type != DBUS_TYPE_INVALID)
       
  1428             dbus_message_iter_next (&iter);
       
  1429 
       
  1430           ++i;
       
  1431         }
       
  1432     }
       
  1433   
       
  1434   return TRUE;
       
  1435 }
       
  1436 
       
  1437 dbus_bool_t
       
  1438 bus_matchmaker_get_recipients (BusMatchmaker   *matchmaker,
       
  1439                                BusConnections  *connections,
       
  1440                                DBusConnection  *sender,
       
  1441                                DBusConnection  *addressed_recipient,
       
  1442                                DBusMessage     *message,
       
  1443                                DBusList       **recipients_p)
       
  1444 {
       
  1445   /* FIXME for now this is a wholly unoptimized linear search */
       
  1446   /* Guessing the important optimization is to skip the signal-related
       
  1447    * match lists when processing method call and exception messages.
       
  1448    * So separate match rule lists for signals?
       
  1449    */
       
  1450   
       
  1451   DBusList *link;
       
  1452 
       
  1453   _dbus_assert (*recipients_p == NULL);
       
  1454 
       
  1455   /* This avoids sending same message to the same connection twice.
       
  1456    * Purpose of the stamp instead of a bool is to avoid iterating over
       
  1457    * all connections resetting the bool each time.
       
  1458    */
       
  1459   bus_connections_increment_stamp (connections);
       
  1460 
       
  1461   /* addressed_recipient is already receiving the message, don't add to list.
       
  1462    * NULL addressed_recipient means either bus driver, or this is a signal
       
  1463    * and thus lacks a specific addressed_recipient.
       
  1464    */
       
  1465   if (addressed_recipient != NULL)
       
  1466     bus_connection_mark_stamp (addressed_recipient);
       
  1467 
       
  1468   link = _dbus_list_get_first_link (&matchmaker->all_rules);
       
  1469   while (link != NULL)
       
  1470     {
       
  1471       BusMatchRule *rule;
       
  1472 
       
  1473       rule = link->data;
       
  1474 
       
  1475 #ifdef DBUS_ENABLE_VERBOSE_MODE
       
  1476       {
       
  1477         char *s = match_rule_to_string (rule);
       
  1478         
       
  1479         _dbus_verbose ("Checking whether message matches rule %s for connection %p\n",
       
  1480                        s, rule->matches_go_to);
       
  1481         dbus_free (s);
       
  1482       }
       
  1483 #endif
       
  1484       
       
  1485       if (match_rule_matches (rule,
       
  1486                               sender, addressed_recipient, message))
       
  1487         {
       
  1488           _dbus_verbose ("Rule matched\n");
       
  1489           
       
  1490           /* Append to the list if we haven't already */
       
  1491           if (bus_connection_mark_stamp (rule->matches_go_to))
       
  1492             {
       
  1493               if (!_dbus_list_append (recipients_p, rule->matches_go_to))
       
  1494                 goto nomem;
       
  1495             }
       
  1496 #ifdef DBUS_ENABLE_VERBOSE_MODE
       
  1497           else
       
  1498             {
       
  1499               _dbus_verbose ("Connection already receiving this message, so not adding again\n");
       
  1500             }
       
  1501 #endif /* DBUS_ENABLE_VERBOSE_MODE */
       
  1502         }
       
  1503 
       
  1504       link = _dbus_list_get_next_link (&matchmaker->all_rules, link);
       
  1505     }
       
  1506 
       
  1507   return TRUE;
       
  1508 
       
  1509  nomem:
       
  1510   _dbus_list_clear (recipients_p);
       
  1511   return FALSE;
       
  1512 }
       
  1513 
       
  1514 #ifdef DBUS_BUILD_TESTS
       
  1515 #include "test.h"
       
  1516 #include <stdlib.h>
       
  1517 
       
  1518 static BusMatchRule*
       
  1519 check_parse (dbus_bool_t should_succeed,
       
  1520              const char *text)
       
  1521 {
       
  1522   BusMatchRule *rule;
       
  1523   DBusString str;
       
  1524   DBusError error;
       
  1525 
       
  1526   dbus_error_init (&error);
       
  1527 
       
  1528   _dbus_string_init_const (&str, text);
       
  1529   
       
  1530   rule = bus_match_rule_parse (NULL, &str, &error);
       
  1531   if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
       
  1532     {
       
  1533       dbus_error_free (&error);
       
  1534       return NULL;
       
  1535     }
       
  1536 
       
  1537   if (should_succeed && rule == NULL)
       
  1538     {
       
  1539       _dbus_warn ("Failed to parse: %s: %s: \"%s\"\n",
       
  1540                   error.name, error.message,
       
  1541                   _dbus_string_get_const_data (&str));
       
  1542       exit (1);
       
  1543     }
       
  1544 
       
  1545   if (!should_succeed && rule != NULL)
       
  1546     {
       
  1547       _dbus_warn ("Failed to fail to parse: \"%s\"\n",
       
  1548                   _dbus_string_get_const_data (&str));
       
  1549       exit (1);
       
  1550     }
       
  1551 
       
  1552   dbus_error_free (&error);
       
  1553 
       
  1554   return rule;
       
  1555 }
       
  1556 
       
  1557 static void
       
  1558 assert_large_rule (BusMatchRule *rule)
       
  1559 {
       
  1560   _dbus_assert (rule->flags & BUS_MATCH_MESSAGE_TYPE);
       
  1561   _dbus_assert (rule->flags & BUS_MATCH_SENDER);
       
  1562   _dbus_assert (rule->flags & BUS_MATCH_INTERFACE);
       
  1563   _dbus_assert (rule->flags & BUS_MATCH_MEMBER);
       
  1564   _dbus_assert (rule->flags & BUS_MATCH_DESTINATION);
       
  1565   _dbus_assert (rule->flags & BUS_MATCH_PATH);
       
  1566 
       
  1567   _dbus_assert (rule->message_type == DBUS_MESSAGE_TYPE_SIGNAL);
       
  1568   _dbus_assert (rule->interface != NULL);
       
  1569   _dbus_assert (rule->member != NULL);
       
  1570   _dbus_assert (rule->sender != NULL);
       
  1571   _dbus_assert (rule->destination != NULL);
       
  1572   _dbus_assert (rule->path != NULL);
       
  1573 
       
  1574   _dbus_assert (strcmp (rule->interface, "org.freedesktop.DBusInterface") == 0);
       
  1575   _dbus_assert (strcmp (rule->sender, "org.freedesktop.DBusSender") == 0);
       
  1576   _dbus_assert (strcmp (rule->member, "Foo") == 0);
       
  1577   _dbus_assert (strcmp (rule->path, "/bar/foo") == 0);
       
  1578   _dbus_assert (strcmp (rule->destination, ":452345.34") == 0);
       
  1579 }
       
  1580 
       
  1581 static dbus_bool_t
       
  1582 test_parsing (void *data)
       
  1583 {
       
  1584   BusMatchRule *rule;
       
  1585 
       
  1586   rule = check_parse (TRUE, "type='signal',sender='org.freedesktop.DBusSender',interface='org.freedesktop.DBusInterface',member='Foo',path='/bar/foo',destination=':452345.34'");
       
  1587   if (rule != NULL)
       
  1588     {
       
  1589       assert_large_rule (rule);
       
  1590       bus_match_rule_unref (rule);
       
  1591     }
       
  1592 
       
  1593   /* With extra whitespace and useless quotes */
       
  1594   rule = check_parse (TRUE, "    type='signal',  \tsender='org.freedes''ktop.DBusSender',   interface='org.freedesktop.DBusInterface''''', \tmember='Foo',path='/bar/foo',destination=':452345.34'''''");
       
  1595   if (rule != NULL)
       
  1596     {
       
  1597       assert_large_rule (rule);
       
  1598       bus_match_rule_unref (rule);
       
  1599     }
       
  1600 
       
  1601 
       
  1602   /* A simple signal connection */
       
  1603   rule = check_parse (TRUE, "type='signal',path='/foo',interface='org.Bar'");
       
  1604   if (rule != NULL)
       
  1605     {
       
  1606       _dbus_assert (rule->flags & BUS_MATCH_MESSAGE_TYPE);
       
  1607       _dbus_assert (rule->flags & BUS_MATCH_INTERFACE);
       
  1608       _dbus_assert (rule->flags & BUS_MATCH_PATH);
       
  1609 
       
  1610       _dbus_assert (rule->message_type == DBUS_MESSAGE_TYPE_SIGNAL);
       
  1611       _dbus_assert (rule->interface != NULL);
       
  1612       _dbus_assert (rule->path != NULL);
       
  1613 
       
  1614       _dbus_assert (strcmp (rule->interface, "org.Bar") == 0);
       
  1615       _dbus_assert (strcmp (rule->path, "/foo") == 0);
       
  1616   
       
  1617       bus_match_rule_unref (rule);
       
  1618     }
       
  1619 
       
  1620   /* argN */
       
  1621   rule = check_parse (TRUE, "arg0='foo'");
       
  1622   if (rule != NULL)
       
  1623     {
       
  1624       _dbus_assert (rule->flags == BUS_MATCH_ARGS);
       
  1625       _dbus_assert (rule->args != NULL);
       
  1626       _dbus_assert (rule->args_len == 1);
       
  1627       _dbus_assert (rule->args[0] != NULL);
       
  1628       _dbus_assert (rule->args[1] == NULL);
       
  1629       _dbus_assert (strcmp (rule->args[0], "foo") == 0);
       
  1630 
       
  1631       bus_match_rule_unref (rule);
       
  1632     }
       
  1633   
       
  1634   rule = check_parse (TRUE, "arg1='foo'");
       
  1635   if (rule != NULL)
       
  1636     {
       
  1637       _dbus_assert (rule->flags == BUS_MATCH_ARGS);
       
  1638       _dbus_assert (rule->args != NULL);
       
  1639       _dbus_assert (rule->args_len == 2);
       
  1640       _dbus_assert (rule->args[0] == NULL);
       
  1641       _dbus_assert (rule->args[1] != NULL);
       
  1642       _dbus_assert (rule->args[2] == NULL);
       
  1643       _dbus_assert (strcmp (rule->args[1], "foo") == 0);
       
  1644 
       
  1645       bus_match_rule_unref (rule);
       
  1646     }
       
  1647 
       
  1648   rule = check_parse (TRUE, "arg2='foo'");
       
  1649   if (rule != NULL)
       
  1650     {
       
  1651       _dbus_assert (rule->flags == BUS_MATCH_ARGS);
       
  1652       _dbus_assert (rule->args != NULL);
       
  1653       _dbus_assert (rule->args_len == 3);
       
  1654       _dbus_assert (rule->args[0] == NULL);
       
  1655       _dbus_assert (rule->args[1] == NULL);
       
  1656       _dbus_assert (rule->args[2] != NULL);
       
  1657       _dbus_assert (rule->args[3] == NULL);
       
  1658       _dbus_assert (strcmp (rule->args[2], "foo") == 0);
       
  1659 
       
  1660       bus_match_rule_unref (rule);
       
  1661     }
       
  1662   
       
  1663   rule = check_parse (TRUE, "arg40='foo'");
       
  1664   if (rule != NULL)
       
  1665     {
       
  1666       _dbus_assert (rule->flags == BUS_MATCH_ARGS);
       
  1667       _dbus_assert (rule->args != NULL);
       
  1668       _dbus_assert (rule->args_len == 41);
       
  1669       _dbus_assert (rule->args[0] == NULL);
       
  1670       _dbus_assert (rule->args[1] == NULL);
       
  1671       _dbus_assert (rule->args[40] != NULL);
       
  1672       _dbus_assert (rule->args[41] == NULL);
       
  1673       _dbus_assert (strcmp (rule->args[40], "foo") == 0);
       
  1674 
       
  1675       bus_match_rule_unref (rule);
       
  1676     }
       
  1677   
       
  1678   rule = check_parse (TRUE, "arg63='foo'");
       
  1679   if (rule != NULL)
       
  1680     {
       
  1681       _dbus_assert (rule->flags == BUS_MATCH_ARGS);
       
  1682       _dbus_assert (rule->args != NULL);
       
  1683       _dbus_assert (rule->args_len == 64);
       
  1684       _dbus_assert (rule->args[0] == NULL);
       
  1685       _dbus_assert (rule->args[1] == NULL);
       
  1686       _dbus_assert (rule->args[63] != NULL);
       
  1687       _dbus_assert (rule->args[64] == NULL);
       
  1688       _dbus_assert (strcmp (rule->args[63], "foo") == 0);
       
  1689 
       
  1690       bus_match_rule_unref (rule);
       
  1691     }
       
  1692   
       
  1693   /* Too-large argN */
       
  1694   rule = check_parse (FALSE, "arg300='foo'");
       
  1695   _dbus_assert (rule == NULL);
       
  1696   rule = check_parse (FALSE, "arg64='foo'");
       
  1697   _dbus_assert (rule == NULL);
       
  1698 
       
  1699   /* No N in argN */
       
  1700   rule = check_parse (FALSE, "arg='foo'");
       
  1701   _dbus_assert (rule == NULL);
       
  1702   rule = check_parse (FALSE, "argv='foo'");
       
  1703   _dbus_assert (rule == NULL);
       
  1704   rule = check_parse (FALSE, "arg3junk='foo'");
       
  1705   _dbus_assert (rule == NULL);
       
  1706   rule = check_parse (FALSE, "argument='foo'");
       
  1707   _dbus_assert (rule == NULL);
       
  1708   
       
  1709   /* Reject duplicates */
       
  1710   rule = check_parse (FALSE, "type='signal',type='method_call'");
       
  1711   _dbus_assert (rule == NULL);
       
  1712 
       
  1713   /* Duplicates with the argN code */
       
  1714   rule = check_parse (FALSE, "arg0='foo',arg0='bar'");
       
  1715   _dbus_assert (rule == NULL);
       
  1716   rule = check_parse (FALSE, "arg3='foo',arg3='bar'");
       
  1717   _dbus_assert (rule == NULL);
       
  1718   rule = check_parse (FALSE, "arg30='foo',arg30='bar'");
       
  1719   _dbus_assert (rule == NULL);
       
  1720   
       
  1721   /* Reject broken keys */
       
  1722   rule = check_parse (FALSE, "blah='signal'");
       
  1723   _dbus_assert (rule == NULL);
       
  1724 
       
  1725   /* Reject broken values */
       
  1726   rule = check_parse (FALSE, "type='chouin'");
       
  1727   _dbus_assert (rule == NULL);
       
  1728   rule = check_parse (FALSE, "interface='abc@def++'");
       
  1729   _dbus_assert (rule == NULL);
       
  1730   rule = check_parse (FALSE, "service='youpi'");
       
  1731   _dbus_assert (rule == NULL);
       
  1732 
       
  1733   /* Allow empty rule */
       
  1734   rule = check_parse (TRUE, "");
       
  1735   if (rule != NULL)
       
  1736     {
       
  1737       _dbus_assert (rule->flags == 0);
       
  1738       
       
  1739       bus_match_rule_unref (rule);
       
  1740     }
       
  1741 
       
  1742   /* All-whitespace rule is the same as empty */
       
  1743   rule = check_parse (TRUE, "    \t");
       
  1744   if (rule != NULL)
       
  1745     {
       
  1746       _dbus_assert (rule->flags == 0);
       
  1747       
       
  1748       bus_match_rule_unref (rule);
       
  1749     }
       
  1750 
       
  1751   /* But with non-whitespace chars and no =value, it's not OK */
       
  1752   rule = check_parse (FALSE, "type");
       
  1753   _dbus_assert (rule == NULL);
       
  1754   
       
  1755   return TRUE;
       
  1756 }
       
  1757 
       
  1758 static struct {
       
  1759   const char *first;
       
  1760   const char *second;
       
  1761 } equality_tests[] = {
       
  1762   { "type='signal'", "type='signal'" },
       
  1763   { "type='signal',interface='foo.bar'", "interface='foo.bar',type='signal'" },
       
  1764   { "type='signal',member='bar'", "member='bar',type='signal'" },
       
  1765   { "type='method_call',sender=':1.0'", "sender=':1.0',type='method_call'" },
       
  1766   { "type='method_call',destination=':1.0'", "destination=':1.0',type='method_call'" },
       
  1767   { "type='method_call',path='/foo/bar'", "path='/foo/bar',type='method_call'" },
       
  1768   { "type='method_call',arg0='blah'", "arg0='blah',type='method_call'" },
       
  1769   { "type='method_call',arg0='boo'", "arg0='boo',type='method_call'" },
       
  1770   { "type='method_call',arg0='blah',arg1='baz'", "arg0='blah',arg1='baz',type='method_call'" },
       
  1771   { "type='method_call',arg3='foosh'", "arg3='foosh',type='method_call'" },
       
  1772   { "arg3='fool'", "arg3='fool'" },
       
  1773   { "member='food'", "member='food'" }
       
  1774 };
       
  1775 
       
  1776 static void
       
  1777 test_equality (void)
       
  1778 {
       
  1779   int i;
       
  1780   
       
  1781   i = 0;
       
  1782   while (i < _DBUS_N_ELEMENTS (equality_tests))
       
  1783     {
       
  1784       BusMatchRule *first;
       
  1785       BusMatchRule *second;
       
  1786       int j;
       
  1787       
       
  1788       first = check_parse (TRUE, equality_tests[i].first);
       
  1789       _dbus_assert (first != NULL);
       
  1790       second = check_parse (TRUE, equality_tests[i].second);
       
  1791       _dbus_assert (second != NULL);
       
  1792 
       
  1793       if (!match_rule_equal (first, second))
       
  1794         {
       
  1795           _dbus_warn ("rule %s and %s should have been equal\n",
       
  1796                       equality_tests[i].first,
       
  1797                       equality_tests[i].second);
       
  1798           exit (1);
       
  1799         }
       
  1800 
       
  1801       bus_match_rule_unref (second);
       
  1802 
       
  1803       /* Check that the rule is not equal to any of the
       
  1804        * others besides its pair match
       
  1805        */
       
  1806       j = 0;
       
  1807       while (j < _DBUS_N_ELEMENTS (equality_tests))
       
  1808         {
       
  1809           if (i != j)
       
  1810             {
       
  1811               second = check_parse (TRUE, equality_tests[j].second);
       
  1812 
       
  1813               if (match_rule_equal (first, second))
       
  1814                 {
       
  1815                   _dbus_warn ("rule %s and %s should not have been equal\n",
       
  1816                               equality_tests[i].first,
       
  1817                               equality_tests[j].second);
       
  1818                   exit (1);
       
  1819                 }
       
  1820               
       
  1821               bus_match_rule_unref (second);
       
  1822             }
       
  1823           
       
  1824           ++j;
       
  1825         }
       
  1826 
       
  1827       bus_match_rule_unref (first);
       
  1828 
       
  1829       ++i;
       
  1830     }
       
  1831 }
       
  1832 
       
  1833 static const char*
       
  1834 should_match_message_1[] = {
       
  1835   "type='signal'",
       
  1836   "member='Frobated'",
       
  1837   "arg0='foobar'",
       
  1838   "type='signal',member='Frobated'",
       
  1839   "type='signal',member='Frobated',arg0='foobar'",
       
  1840   "member='Frobated',arg0='foobar'",
       
  1841   "type='signal',arg0='foobar'",
       
  1842   NULL
       
  1843 };
       
  1844 
       
  1845 static const char*
       
  1846 should_not_match_message_1[] = {
       
  1847   "type='method_call'",
       
  1848   "type='error'",
       
  1849   "type='method_return'",
       
  1850   "type='signal',member='Oopsed'",
       
  1851   "arg0='blah'",
       
  1852   "arg1='foobar'",
       
  1853   "arg2='foobar'",
       
  1854   "arg3='foobar'",
       
  1855   "arg0='3'",
       
  1856   "arg1='3'",
       
  1857   "arg0='foobar',arg1='abcdef'",
       
  1858   "arg0='foobar',arg1='abcdef',arg2='abcdefghi',arg3='abcdefghi',arg4='abcdefghi'",
       
  1859   "arg0='foobar',arg1='abcdef',arg4='abcdefghi',arg3='abcdefghi',arg2='abcdefghi'",
       
  1860   NULL
       
  1861 };
       
  1862 
       
  1863 static void
       
  1864 check_matches (dbus_bool_t  expected_to_match,
       
  1865                int          number,
       
  1866                DBusMessage *message,
       
  1867                const char  *rule_text)
       
  1868 {
       
  1869   BusMatchRule *rule;
       
  1870   dbus_bool_t matched;
       
  1871 
       
  1872   rule = check_parse (TRUE, rule_text);
       
  1873   _dbus_assert (rule != NULL);
       
  1874 
       
  1875   /* We can't test sender/destination rules since we pass NULL here */
       
  1876   matched = match_rule_matches (rule, NULL, NULL, message);
       
  1877 
       
  1878   if (matched != expected_to_match)
       
  1879     {
       
  1880       _dbus_warn ("Expected rule %s to %s message %d, failed\n",
       
  1881                   rule_text, expected_to_match ?
       
  1882                   "match" : "not match", number);
       
  1883       exit (1);
       
  1884     }
       
  1885 
       
  1886   bus_match_rule_unref (rule);
       
  1887 }
       
  1888 
       
  1889 static void
       
  1890 check_matching (DBusMessage *message,
       
  1891                 int          number,
       
  1892                 const char **should_match,
       
  1893                 const char **should_not_match)
       
  1894 {
       
  1895   int i;
       
  1896 
       
  1897   i = 0;
       
  1898   while (should_match[i] != NULL)
       
  1899     {
       
  1900       check_matches (TRUE, number, message, should_match[i]);
       
  1901       ++i;
       
  1902     }
       
  1903 
       
  1904   i = 0;
       
  1905   while (should_not_match[i] != NULL)
       
  1906     {
       
  1907       check_matches (FALSE, number, message, should_not_match[i]);
       
  1908       ++i;
       
  1909     }
       
  1910 }
       
  1911 
       
  1912 static void
       
  1913 test_matching (void)
       
  1914 {
       
  1915   DBusMessage *message1;
       
  1916   const char *v_STRING;
       
  1917   dbus_int32_t v_INT32;
       
  1918 
       
  1919   message1 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL);
       
  1920   _dbus_assert (message1 != NULL);
       
  1921   if (!dbus_message_set_member (message1, "Frobated"))
       
  1922     _dbus_assert_not_reached ("oom");
       
  1923 
       
  1924   v_STRING = "foobar";
       
  1925   v_INT32 = 3;
       
  1926   if (!dbus_message_append_args (message1,
       
  1927                                  DBUS_TYPE_STRING, &v_STRING,
       
  1928                                  DBUS_TYPE_INT32, &v_INT32,
       
  1929                                  NULL))
       
  1930     _dbus_assert_not_reached ("oom");
       
  1931   
       
  1932   check_matching (message1, 1,
       
  1933                   should_match_message_1,
       
  1934                   should_not_match_message_1);
       
  1935   
       
  1936   dbus_message_unref (message1);
       
  1937 }
       
  1938 
       
  1939 dbus_bool_t
       
  1940 bus_signals_test (const DBusString *test_data_dir)
       
  1941 {
       
  1942   BusMatchmaker *matchmaker;
       
  1943 
       
  1944   matchmaker = bus_matchmaker_new ();
       
  1945   bus_matchmaker_ref (matchmaker);
       
  1946   bus_matchmaker_unref (matchmaker);
       
  1947   bus_matchmaker_unref (matchmaker);
       
  1948 
       
  1949   if (!_dbus_test_oom_handling ("parsing match rules", test_parsing, NULL))
       
  1950     _dbus_assert_not_reached ("Parsing match rules test failed");
       
  1951 
       
  1952   test_equality ();
       
  1953 
       
  1954   test_matching ();
       
  1955   
       
  1956   return TRUE;
       
  1957 }
       
  1958 
       
  1959 #endif /* DBUS_BUILD_TESTS */
       
  1960