~ubuntu-branches/ubuntu/maverick/dbus/maverick-security

« back to all changes in this revision

Viewing changes to bus/signals.c

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2010-09-27 13:06:32 UTC
  • mfrom: (1.1.23 upstream)
  • Revision ID: james.westby@ubuntu.com-20100927130632-bqs145trvchd2lmf
Tags: 1.4.0-0ubuntu1
* New upstream release
 - Fixes https://bugs.freedesktop.org/show_bug.cgi?id=17754 Race condition in protected_change_timeout
 - Requested by various upstream KDE developers http://lists.kde.org/?t=128514970000004&r=1&w=2

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21
21
 *
22
22
 */
 
23
 
 
24
#include <config.h>
23
25
#include "signals.h"
24
26
#include "services.h"
25
27
#include "utils.h"
1018
1020
  return rule;
1019
1021
}
1020
1022
 
 
1023
typedef struct RulePool RulePool;
 
1024
struct RulePool
 
1025
{
 
1026
  /* Maps non-NULL interface names to non-NULL (DBusList **)s */
 
1027
  DBusHashTable *rules_by_iface;
 
1028
 
 
1029
  /* List of BusMatchRules which don't specify an interface */
 
1030
  DBusList *rules_without_iface;
 
1031
};
 
1032
 
1021
1033
struct BusMatchmaker
1022
1034
{
1023
1035
  int refcount;
1024
1036
 
1025
 
  DBusList *all_rules;
 
1037
  /* Pools of rules, grouped by the type of message they match. 0
 
1038
   * (DBUS_MESSAGE_TYPE_INVALID) represents rules that do not specify a message
 
1039
   * type.
 
1040
   */
 
1041
  RulePool rules_by_type[DBUS_NUM_MESSAGE_TYPES];
1026
1042
};
1027
1043
 
 
1044
static void
 
1045
rule_list_free (DBusList **rules)
 
1046
{
 
1047
  while (*rules != NULL)
 
1048
    {
 
1049
      BusMatchRule *rule;
 
1050
 
 
1051
      rule = (*rules)->data;
 
1052
      bus_match_rule_unref (rule);
 
1053
      _dbus_list_remove_link (rules, *rules);
 
1054
    }
 
1055
}
 
1056
 
 
1057
static void
 
1058
rule_list_ptr_free (DBusList **list)
 
1059
{
 
1060
  /* We have to cope with NULL because the hash table frees the "existing"
 
1061
   * value (which is NULL) when creating a new table entry...
 
1062
   */
 
1063
  if (list != NULL)
 
1064
    {
 
1065
      rule_list_free (list);
 
1066
      dbus_free (list);
 
1067
    }
 
1068
}
 
1069
 
1028
1070
BusMatchmaker*
1029
1071
bus_matchmaker_new (void)
1030
1072
{
1031
1073
  BusMatchmaker *matchmaker;
 
1074
  int i;
1032
1075
 
1033
1076
  matchmaker = dbus_new0 (BusMatchmaker, 1);
1034
1077
  if (matchmaker == NULL)
1035
1078
    return NULL;
1036
1079
 
1037
1080
  matchmaker->refcount = 1;
1038
 
  
 
1081
 
 
1082
  for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++)
 
1083
    {
 
1084
      RulePool *p = matchmaker->rules_by_type + i;
 
1085
 
 
1086
      p->rules_by_iface = _dbus_hash_table_new (DBUS_HASH_STRING,
 
1087
          dbus_free, (DBusFreeFunction) rule_list_ptr_free);
 
1088
 
 
1089
      if (p->rules_by_iface == NULL)
 
1090
        goto nomem;
 
1091
    }
 
1092
 
1039
1093
  return matchmaker;
 
1094
 
 
1095
 nomem:
 
1096
  for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++)
 
1097
    {
 
1098
      RulePool *p = matchmaker->rules_by_type + i;
 
1099
 
 
1100
      if (p->rules_by_iface == NULL)
 
1101
        break;
 
1102
      else
 
1103
        _dbus_hash_table_unref (p->rules_by_iface);
 
1104
    }
 
1105
 
 
1106
  return NULL;
 
1107
}
 
1108
 
 
1109
static DBusList **
 
1110
bus_matchmaker_get_rules (BusMatchmaker *matchmaker,
 
1111
                          int            message_type,
 
1112
                          const char    *interface,
 
1113
                          dbus_bool_t    create)
 
1114
{
 
1115
  RulePool *p;
 
1116
 
 
1117
  _dbus_assert (message_type >= 0);
 
1118
  _dbus_assert (message_type < DBUS_NUM_MESSAGE_TYPES);
 
1119
 
 
1120
  _dbus_verbose ("Looking up rules for message_type %d, interface %s\n",
 
1121
                 message_type,
 
1122
                 interface != NULL ? interface : "<null>");
 
1123
 
 
1124
  p = matchmaker->rules_by_type + message_type;
 
1125
 
 
1126
  if (interface == NULL)
 
1127
    {
 
1128
      return &p->rules_without_iface;
 
1129
    }
 
1130
  else
 
1131
    {
 
1132
      DBusList **list;
 
1133
 
 
1134
      list = _dbus_hash_table_lookup_string (p->rules_by_iface, interface);
 
1135
 
 
1136
      if (list == NULL && create)
 
1137
        {
 
1138
          char *dupped_interface;
 
1139
 
 
1140
          list = dbus_new0 (DBusList *, 1);
 
1141
          if (list == NULL)
 
1142
            return NULL;
 
1143
 
 
1144
          dupped_interface = _dbus_strdup (interface);
 
1145
          if (dupped_interface == NULL)
 
1146
            {
 
1147
              dbus_free (list);
 
1148
              return NULL;
 
1149
            }
 
1150
 
 
1151
          _dbus_verbose ("Adding list for type %d, iface %s\n", message_type,
 
1152
                         interface);
 
1153
 
 
1154
          if (!_dbus_hash_table_insert_string (p->rules_by_iface,
 
1155
                                               dupped_interface, list))
 
1156
            {
 
1157
              dbus_free (list);
 
1158
              dbus_free (dupped_interface);
 
1159
              return NULL;
 
1160
            }
 
1161
        }
 
1162
 
 
1163
      return list;
 
1164
    }
 
1165
}
 
1166
 
 
1167
static void
 
1168
bus_matchmaker_gc_rules (BusMatchmaker *matchmaker,
 
1169
                         int            message_type,
 
1170
                         const char    *interface,
 
1171
                         DBusList     **rules)
 
1172
{
 
1173
  RulePool *p;
 
1174
 
 
1175
  if (interface == NULL)
 
1176
    return;
 
1177
 
 
1178
  if (*rules != NULL)
 
1179
    return;
 
1180
 
 
1181
  _dbus_verbose ("GCing HT entry for message_type %u, interface %s\n",
 
1182
                 message_type, interface);
 
1183
 
 
1184
  p = matchmaker->rules_by_type + message_type;
 
1185
 
 
1186
  _dbus_assert (_dbus_hash_table_lookup_string (p->rules_by_iface, interface)
 
1187
      == rules);
 
1188
 
 
1189
  _dbus_hash_table_remove_string (p->rules_by_iface, interface);
1040
1190
}
1041
1191
 
1042
1192
BusMatchmaker *
1057
1207
  matchmaker->refcount -= 1;
1058
1208
  if (matchmaker->refcount == 0)
1059
1209
    {
1060
 
      while (matchmaker->all_rules != NULL)
 
1210
      int i;
 
1211
 
 
1212
      for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++)
1061
1213
        {
1062
 
          BusMatchRule *rule;
 
1214
          RulePool *p = matchmaker->rules_by_type + i;
1063
1215
 
1064
 
          rule = matchmaker->all_rules->data;
1065
 
          bus_match_rule_unref (rule);
1066
 
          _dbus_list_remove_link (&matchmaker->all_rules,
1067
 
                                  matchmaker->all_rules);
 
1216
          _dbus_hash_table_unref (p->rules_by_iface);
 
1217
          rule_list_free (&p->rules_without_iface);
1068
1218
        }
1069
1219
 
1070
1220
      dbus_free (matchmaker);
1076
1226
bus_matchmaker_add_rule (BusMatchmaker   *matchmaker,
1077
1227
                         BusMatchRule    *rule)
1078
1228
{
 
1229
  DBusList **rules;
 
1230
 
1079
1231
  _dbus_assert (bus_connection_is_active (rule->matches_go_to));
1080
1232
 
1081
 
  if (!_dbus_list_append (&matchmaker->all_rules, rule))
 
1233
  _dbus_verbose ("Adding rule with message_type %d, interface %s\n",
 
1234
                 rule->message_type,
 
1235
                 rule->interface != NULL ? rule->interface : "<null>");
 
1236
 
 
1237
  rules = bus_matchmaker_get_rules (matchmaker, rule->message_type,
 
1238
                                    rule->interface, TRUE);
 
1239
 
 
1240
  if (rules == NULL)
 
1241
    return FALSE;
 
1242
 
 
1243
  if (!_dbus_list_append (rules, rule))
1082
1244
    return FALSE;
1083
1245
 
1084
1246
  if (!bus_connection_add_match_rule (rule->matches_go_to, rule))
1085
1247
    {
1086
 
      _dbus_list_remove_last (&matchmaker->all_rules, rule);
 
1248
      _dbus_list_remove_last (rules, rule);
 
1249
      bus_matchmaker_gc_rules (matchmaker, rule->message_type,
 
1250
                               rule->interface, rules);
1087
1251
      return FALSE;
1088
1252
    }
1089
 
  
 
1253
 
1090
1254
  bus_match_rule_ref (rule);
1091
1255
 
1092
1256
#ifdef DBUS_ENABLE_VERBOSE_MODE
1171
1335
}
1172
1336
 
1173
1337
static void
1174
 
bus_matchmaker_remove_rule_link (BusMatchmaker   *matchmaker,
 
1338
bus_matchmaker_remove_rule_link (DBusList       **rules,
1175
1339
                                 DBusList        *link)
1176
1340
{
1177
1341
  BusMatchRule *rule = link->data;
1178
1342
  
1179
1343
  bus_connection_remove_match_rule (rule->matches_go_to, rule);
1180
 
  _dbus_list_remove_link (&matchmaker->all_rules, link);
 
1344
  _dbus_list_remove_link (rules, link);
1181
1345
 
1182
1346
#ifdef DBUS_ENABLE_VERBOSE_MODE
1183
1347
  {
1196
1360
bus_matchmaker_remove_rule (BusMatchmaker   *matchmaker,
1197
1361
                            BusMatchRule    *rule)
1198
1362
{
 
1363
  DBusList **rules;
 
1364
 
 
1365
  _dbus_verbose ("Removing rule with message_type %d, interface %s\n",
 
1366
                 rule->message_type,
 
1367
                 rule->interface != NULL ? rule->interface : "<null>");
 
1368
 
1199
1369
  bus_connection_remove_match_rule (rule->matches_go_to, rule);
1200
 
  _dbus_list_remove (&matchmaker->all_rules, rule);
 
1370
 
 
1371
  rules = bus_matchmaker_get_rules (matchmaker, rule->message_type,
 
1372
                                    rule->interface, FALSE);
 
1373
 
 
1374
  /* We should only be asked to remove a rule by identity right after it was
 
1375
   * added, so there should be a list for it.
 
1376
   */
 
1377
  _dbus_assert (rules != NULL);
 
1378
 
 
1379
  _dbus_list_remove (rules, rule);
 
1380
  bus_matchmaker_gc_rules (matchmaker, rule->message_type, rule->interface,
 
1381
      rules);
1201
1382
 
1202
1383
#ifdef DBUS_ENABLE_VERBOSE_MODE
1203
1384
  {
1218
1399
                                     BusMatchRule    *value,
1219
1400
                                     DBusError       *error)
1220
1401
{
1221
 
  /* FIXME this is an unoptimized linear scan */
1222
 
 
1223
 
  DBusList *link;
1224
 
 
1225
 
  /* we traverse backward because bus_connection_remove_match_rule()
1226
 
   * removes the most-recently-added rule
1227
 
   */
1228
 
  link = _dbus_list_get_last_link (&matchmaker->all_rules);
1229
 
  while (link != NULL)
 
1402
  DBusList **rules;
 
1403
  DBusList *link = NULL;
 
1404
 
 
1405
  _dbus_verbose ("Removing rule by value with message_type %d, interface %s\n",
 
1406
                 value->message_type,
 
1407
                 value->interface != NULL ? value->interface : "<null>");
 
1408
 
 
1409
  rules = bus_matchmaker_get_rules (matchmaker, value->message_type,
 
1410
      value->interface, FALSE);
 
1411
 
 
1412
  if (rules != NULL)
1230
1413
    {
1231
 
      BusMatchRule *rule;
1232
 
      DBusList *prev;
1233
 
 
1234
 
      rule = link->data;
1235
 
      prev = _dbus_list_get_prev_link (&matchmaker->all_rules, link);
1236
 
 
1237
 
      if (match_rule_equal (rule, value))
 
1414
      /* we traverse backward because bus_connection_remove_match_rule()
 
1415
       * removes the most-recently-added rule
 
1416
       */
 
1417
      link = _dbus_list_get_last_link (rules);
 
1418
      while (link != NULL)
1238
1419
        {
1239
 
          bus_matchmaker_remove_rule_link (matchmaker, link);
1240
 
          break;
 
1420
          BusMatchRule *rule;
 
1421
          DBusList *prev;
 
1422
 
 
1423
          rule = link->data;
 
1424
          prev = _dbus_list_get_prev_link (rules, link);
 
1425
 
 
1426
          if (match_rule_equal (rule, value))
 
1427
            {
 
1428
              bus_matchmaker_remove_rule_link (rules, link);
 
1429
              break;
 
1430
            }
 
1431
 
 
1432
          link = prev;
1241
1433
        }
1242
 
 
1243
 
      link = prev;
1244
1434
    }
1245
1435
 
1246
1436
  if (link == NULL)
1250
1440
      return FALSE;
1251
1441
    }
1252
1442
 
 
1443
  bus_matchmaker_gc_rules (matchmaker, value->message_type, value->interface,
 
1444
      rules);
 
1445
 
1253
1446
  return TRUE;
1254
1447
}
1255
1448
 
1256
 
void
1257
 
bus_matchmaker_disconnected (BusMatchmaker   *matchmaker,
1258
 
                             DBusConnection  *disconnected)
 
1449
static void
 
1450
rule_list_remove_by_connection (DBusList       **rules,
 
1451
                                DBusConnection  *connection)
1259
1452
{
1260
1453
  DBusList *link;
1261
1454
 
1262
 
  /* FIXME
1263
 
   *
1264
 
   * This scans all match rules on the bus. We could avoid that
1265
 
   * for the rules belonging to the connection, since we keep
1266
 
   * a list of those; but for the rules that just refer to
1267
 
   * the connection we'd need to do something more elaborate.
1268
 
   * 
1269
 
   */
1270
 
  
1271
 
  _dbus_assert (bus_connection_is_active (disconnected));
1272
 
 
1273
 
  link = _dbus_list_get_first_link (&matchmaker->all_rules);
 
1455
  link = _dbus_list_get_first_link (rules);
1274
1456
  while (link != NULL)
1275
1457
    {
1276
1458
      BusMatchRule *rule;
1277
1459
      DBusList *next;
1278
1460
 
1279
1461
      rule = link->data;
1280
 
      next = _dbus_list_get_next_link (&matchmaker->all_rules, link);
 
1462
      next = _dbus_list_get_next_link (rules, link);
1281
1463
 
1282
 
      if (rule->matches_go_to == disconnected)
 
1464
      if (rule->matches_go_to == connection)
1283
1465
        {
1284
 
          bus_matchmaker_remove_rule_link (matchmaker, link);
 
1466
          bus_matchmaker_remove_rule_link (rules, link);
1285
1467
        }
1286
1468
      else if (((rule->flags & BUS_MATCH_SENDER) && *rule->sender == ':') ||
1287
1469
               ((rule->flags & BUS_MATCH_DESTINATION) && *rule->destination == ':'))
1292
1474
           */
1293
1475
          const char *name;
1294
1476
 
1295
 
          name = bus_connection_get_name (disconnected);
 
1477
          name = bus_connection_get_name (connection);
1296
1478
          _dbus_assert (name != NULL); /* because we're an active connection */
1297
1479
 
1298
1480
          if (((rule->flags & BUS_MATCH_SENDER) &&
1300
1482
              ((rule->flags & BUS_MATCH_DESTINATION) &&
1301
1483
               strcmp (rule->destination, name) == 0))
1302
1484
            {
1303
 
              bus_matchmaker_remove_rule_link (matchmaker, link);
 
1485
              bus_matchmaker_remove_rule_link (rules, link);
1304
1486
            }
1305
1487
        }
1306
1488
 
1308
1490
    }
1309
1491
}
1310
1492
 
 
1493
void
 
1494
bus_matchmaker_disconnected (BusMatchmaker   *matchmaker,
 
1495
                             DBusConnection  *connection)
 
1496
{
 
1497
  int i;
 
1498
 
 
1499
  /* FIXME
 
1500
   *
 
1501
   * This scans all match rules on the bus. We could avoid that
 
1502
   * for the rules belonging to the connection, since we keep
 
1503
   * a list of those; but for the rules that just refer to
 
1504
   * the connection we'd need to do something more elaborate.
 
1505
   */
 
1506
 
 
1507
  _dbus_assert (bus_connection_is_active (connection));
 
1508
 
 
1509
  _dbus_verbose ("Removing all rules for connection %p\n", connection);
 
1510
 
 
1511
  for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++)
 
1512
    {
 
1513
      RulePool *p = matchmaker->rules_by_type + i;
 
1514
      DBusHashIter iter;
 
1515
 
 
1516
      rule_list_remove_by_connection (&p->rules_without_iface, connection);
 
1517
 
 
1518
      _dbus_hash_iter_init (p->rules_by_iface, &iter);
 
1519
      while (_dbus_hash_iter_next (&iter))
 
1520
        {
 
1521
          DBusList **items = _dbus_hash_iter_get_value (&iter);
 
1522
 
 
1523
          rule_list_remove_by_connection (items, connection);
 
1524
 
 
1525
          if (*items == NULL)
 
1526
            _dbus_hash_iter_remove_entry (&iter);
 
1527
        }
 
1528
    }
 
1529
}
 
1530
 
1311
1531
static dbus_bool_t
1312
1532
connection_is_primary_owner (DBusConnection *connection,
1313
1533
                             const char     *service_name)
1333
1553
match_rule_matches (BusMatchRule    *rule,
1334
1554
                    DBusConnection  *sender,
1335
1555
                    DBusConnection  *addressed_recipient,
1336
 
                    DBusMessage     *message)
 
1556
                    DBusMessage     *message,
 
1557
                    BusMatchFlags    already_matched)
1337
1558
{
 
1559
  int flags;
 
1560
 
1338
1561
  /* All features of the match rule are AND'd together,
1339
1562
   * so FALSE if any of them don't match.
1340
1563
   */
1343
1566
   * or for addressed_recipient may mean a message with no
1344
1567
   * specific recipient (i.e. a signal)
1345
1568
   */
1346
 
  
1347
 
  if (rule->flags & BUS_MATCH_MESSAGE_TYPE)
 
1569
 
 
1570
  /* Don't bother re-matching features we've already checked implicitly. */
 
1571
  flags = rule->flags & (~already_matched);
 
1572
 
 
1573
  if (flags & BUS_MATCH_MESSAGE_TYPE)
1348
1574
    {
1349
1575
      _dbus_assert (rule->message_type != DBUS_MESSAGE_TYPE_INVALID);
1350
1576
 
1352
1578
        return FALSE;
1353
1579
    }
1354
1580
 
1355
 
  if (rule->flags & BUS_MATCH_INTERFACE)
 
1581
  if (flags & BUS_MATCH_INTERFACE)
1356
1582
    {
1357
1583
      const char *iface;
1358
1584
 
1366
1592
        return FALSE;
1367
1593
    }
1368
1594
 
1369
 
  if (rule->flags & BUS_MATCH_MEMBER)
 
1595
  if (flags & BUS_MATCH_MEMBER)
1370
1596
    {
1371
1597
      const char *member;
1372
1598
 
1380
1606
        return FALSE;
1381
1607
    }
1382
1608
 
1383
 
  if (rule->flags & BUS_MATCH_SENDER)
 
1609
  if (flags & BUS_MATCH_SENDER)
1384
1610
    {
1385
1611
      _dbus_assert (rule->sender != NULL);
1386
1612
 
1397
1623
        }
1398
1624
    }
1399
1625
 
1400
 
  if (rule->flags & BUS_MATCH_DESTINATION)
 
1626
  if (flags & BUS_MATCH_DESTINATION)
1401
1627
    {
1402
1628
      const char *destination;
1403
1629
 
1420
1646
        }
1421
1647
    }
1422
1648
 
1423
 
  if (rule->flags & BUS_MATCH_PATH)
 
1649
  if (flags & BUS_MATCH_PATH)
1424
1650
    {
1425
1651
      const char *path;
1426
1652
 
1434
1660
        return FALSE;
1435
1661
    }
1436
1662
 
1437
 
  if (rule->flags & BUS_MATCH_ARGS)
 
1663
  if (flags & BUS_MATCH_ARGS)
1438
1664
    {
1439
1665
      int i;
1440
1666
      DBusMessageIter iter;
1504
1730
  return TRUE;
1505
1731
}
1506
1732
 
 
1733
static dbus_bool_t
 
1734
get_recipients_from_list (DBusList       **rules,
 
1735
                          DBusConnection  *sender,
 
1736
                          DBusConnection  *addressed_recipient,
 
1737
                          DBusMessage     *message,
 
1738
                          DBusList       **recipients_p)
 
1739
{
 
1740
  DBusList *link;
 
1741
 
 
1742
  if (rules == NULL)
 
1743
    return TRUE;
 
1744
 
 
1745
  link = _dbus_list_get_first_link (rules);
 
1746
  while (link != NULL)
 
1747
    {
 
1748
      BusMatchRule *rule;
 
1749
 
 
1750
      rule = link->data;
 
1751
 
 
1752
#ifdef DBUS_ENABLE_VERBOSE_MODE
 
1753
      {
 
1754
        char *s = match_rule_to_string (rule);
 
1755
 
 
1756
        _dbus_verbose ("Checking whether message matches rule %s for connection %p\n",
 
1757
                       s, rule->matches_go_to);
 
1758
        dbus_free (s);
 
1759
      }
 
1760
#endif
 
1761
 
 
1762
      if (match_rule_matches (rule,
 
1763
                              sender, addressed_recipient, message,
 
1764
                              BUS_MATCH_MESSAGE_TYPE | BUS_MATCH_INTERFACE))
 
1765
        {
 
1766
          _dbus_verbose ("Rule matched\n");
 
1767
 
 
1768
          /* Append to the list if we haven't already */
 
1769
          if (bus_connection_mark_stamp (rule->matches_go_to))
 
1770
            {
 
1771
              if (!_dbus_list_append (recipients_p, rule->matches_go_to))
 
1772
                return FALSE;
 
1773
            }
 
1774
#ifdef DBUS_ENABLE_VERBOSE_MODE
 
1775
          else
 
1776
            {
 
1777
              _dbus_verbose ("Connection already receiving this message, so not adding again\n");
 
1778
            }
 
1779
#endif /* DBUS_ENABLE_VERBOSE_MODE */
 
1780
        }
 
1781
 
 
1782
      link = _dbus_list_get_next_link (rules, link);
 
1783
    }
 
1784
 
 
1785
  return TRUE;
 
1786
}
 
1787
 
1507
1788
dbus_bool_t
1508
1789
bus_matchmaker_get_recipients (BusMatchmaker   *matchmaker,
1509
1790
                               BusConnections  *connections,
1512
1793
                               DBusMessage     *message,
1513
1794
                               DBusList       **recipients_p)
1514
1795
{
1515
 
  /* FIXME for now this is a wholly unoptimized linear search */
1516
 
  /* Guessing the important optimization is to skip the signal-related
1517
 
   * match lists when processing method call and exception messages.
1518
 
   * So separate match rule lists for signals?
1519
 
   */
1520
 
  
1521
 
  DBusList *link;
 
1796
  int type;
 
1797
  const char *interface;
 
1798
  DBusList **neither, **just_type, **just_iface, **both;
1522
1799
 
1523
1800
  _dbus_assert (*recipients_p == NULL);
1524
1801
 
1535
1812
  if (addressed_recipient != NULL)
1536
1813
    bus_connection_mark_stamp (addressed_recipient);
1537
1814
 
1538
 
  link = _dbus_list_get_first_link (&matchmaker->all_rules);
1539
 
  while (link != NULL)
1540
 
    {
1541
 
      BusMatchRule *rule;
1542
 
 
1543
 
      rule = link->data;
1544
 
 
1545
 
#ifdef DBUS_ENABLE_VERBOSE_MODE
1546
 
      {
1547
 
        char *s = match_rule_to_string (rule);
1548
 
        
1549
 
        _dbus_verbose ("Checking whether message matches rule %s for connection %p\n",
1550
 
                       s, rule->matches_go_to);
1551
 
        dbus_free (s);
1552
 
      }
1553
 
#endif
1554
 
      
1555
 
      if (match_rule_matches (rule,
1556
 
                              sender, addressed_recipient, message))
1557
 
        {
1558
 
          _dbus_verbose ("Rule matched\n");
1559
 
          
1560
 
          /* Append to the list if we haven't already */
1561
 
          if (bus_connection_mark_stamp (rule->matches_go_to))
1562
 
            {
1563
 
              if (!_dbus_list_append (recipients_p, rule->matches_go_to))
1564
 
                goto nomem;
1565
 
            }
1566
 
#ifdef DBUS_ENABLE_VERBOSE_MODE
1567
 
          else
1568
 
            {
1569
 
              _dbus_verbose ("Connection already receiving this message, so not adding again\n");
1570
 
            }
1571
 
#endif /* DBUS_ENABLE_VERBOSE_MODE */
1572
 
        }
1573
 
 
1574
 
      link = _dbus_list_get_next_link (&matchmaker->all_rules, link);
 
1815
  type = dbus_message_get_type (message);
 
1816
  interface = dbus_message_get_interface (message);
 
1817
 
 
1818
  neither = bus_matchmaker_get_rules (matchmaker, DBUS_MESSAGE_TYPE_INVALID,
 
1819
      NULL, FALSE);
 
1820
  just_type = just_iface = both = NULL;
 
1821
 
 
1822
  if (interface != NULL)
 
1823
    just_iface = bus_matchmaker_get_rules (matchmaker,
 
1824
        DBUS_MESSAGE_TYPE_INVALID, interface, FALSE);
 
1825
 
 
1826
  if (type > DBUS_MESSAGE_TYPE_INVALID && type < DBUS_NUM_MESSAGE_TYPES)
 
1827
    {
 
1828
      just_type = bus_matchmaker_get_rules (matchmaker, type, NULL, FALSE);
 
1829
 
 
1830
      if (interface != NULL)
 
1831
        both = bus_matchmaker_get_rules (matchmaker, type, interface, FALSE);
 
1832
    }
 
1833
 
 
1834
  if (!(get_recipients_from_list (neither, sender, addressed_recipient,
 
1835
                                  message, recipients_p) &&
 
1836
        get_recipients_from_list (just_iface, sender, addressed_recipient,
 
1837
                                  message, recipients_p) &&
 
1838
        get_recipients_from_list (just_type, sender, addressed_recipient,
 
1839
                                  message, recipients_p) &&
 
1840
        get_recipients_from_list (both, sender, addressed_recipient,
 
1841
                                  message, recipients_p)))
 
1842
    {
 
1843
      _dbus_list_clear (recipients_p);
 
1844
      return FALSE;
1575
1845
    }
1576
1846
 
1577
1847
  return TRUE;
1578
 
 
1579
 
 nomem:
1580
 
  _dbus_list_clear (recipients_p);
1581
 
  return FALSE;
1582
1848
}
1583
1849
 
1584
1850
#ifdef DBUS_BUILD_TESTS
1943
2209
  _dbus_assert (rule != NULL);
1944
2210
 
1945
2211
  /* We can't test sender/destination rules since we pass NULL here */
1946
 
  matched = match_rule_matches (rule, NULL, NULL, message);
 
2212
  matched = match_rule_matches (rule, NULL, NULL, message, 0);
1947
2213
 
1948
2214
  if (matched != expected_to_match)
1949
2215
    {