diff options
Diffstat (limited to 'bus/driver.c')
| -rw-r--r-- | bus/driver.c | 164 | 
1 files changed, 161 insertions, 3 deletions
diff --git a/bus/driver.c b/bus/driver.c index 61bfe1c5..791fcd69 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -27,6 +27,7 @@  #include "driver.h"  #include "dispatch.h"  #include "services.h" +#include "signals.h"  #include "utils.h"  #include <dbus/dbus-string.h>  #include <dbus/dbus-internals.h> @@ -69,7 +70,7 @@ bus_driver_send_service_deleted (const char     *service_name,        return FALSE;      } -  retval = bus_dispatch_broadcast_message (transaction, NULL, message, error); +  retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);    dbus_message_unref (message);    return retval; @@ -111,7 +112,7 @@ bus_driver_send_service_created (const char     *service_name,        return FALSE;      } -  retval = bus_dispatch_broadcast_message (transaction, NULL, message, error); +  retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);    dbus_message_unref (message);    return retval; @@ -331,6 +332,7 @@ bus_driver_handle_hello (DBusConnection *connection,    bus_service_set_prohibit_replacement (service, TRUE); +  _dbus_assert (bus_connection_is_active (connection));    retval = TRUE;   out_0: @@ -600,6 +602,160 @@ bus_driver_handle_activate_service (DBusConnection *connection,    return retval;  } +static dbus_bool_t +send_ack_reply (DBusConnection *connection, +                BusTransaction *transaction, +                DBusMessage    *message, +                DBusError      *error) +{ +  DBusMessage *reply; + +  reply = dbus_message_new_method_return (message); +  if (reply == NULL) +    { +      BUS_SET_OOM (error); +      return FALSE; +    } + +  if (!bus_transaction_send_from_driver (transaction, connection, reply)) +    { +      BUS_SET_OOM (error); +      dbus_message_unref (reply); +      return FALSE; +    } + +  dbus_message_unref (reply); +   +  return TRUE; +} + +static dbus_bool_t +bus_driver_handle_add_match (DBusConnection *connection, +                             BusTransaction *transaction, +                             DBusMessage    *message, +                             DBusError      *error) +{ +  BusMatchRule *rule; +  char *text; +  DBusString str; +  BusMatchmaker *matchmaker; +   +  _DBUS_ASSERT_ERROR_IS_CLEAR (error); + +  text = NULL; +  rule = NULL; + +  if (bus_connection_get_n_match_rules (connection) >= +      bus_context_get_max_match_rules_per_connection (bus_transaction_get_context (transaction))) +    { +      dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, +                      "Connection \"%s\" is not allowed to add more match rules " +                      "(increase limits in configuration file if required)", +                      bus_connection_is_active (connection) ? +                      bus_connection_get_name (connection) : +                      "(inactive)"); +      goto failed; +    } +   +  if (!dbus_message_get_args (message, error, +                              DBUS_TYPE_STRING, &text, +                              DBUS_TYPE_INVALID)) +    { +      _dbus_verbose ("No memory to get arguments to AddMatch\n"); +      goto failed; +    } + +  _dbus_string_init_const (&str, text); + +  rule = bus_match_rule_parse (connection, &str, error); +  if (rule == NULL) +    goto failed; + +  matchmaker = bus_connection_get_matchmaker (connection); + +  if (!bus_matchmaker_add_rule (matchmaker, rule)) +    { +      BUS_SET_OOM (error); +      goto failed; +    } + +  if (!send_ack_reply (connection, transaction, +                       message, error)) +    { +      bus_matchmaker_remove_rule (matchmaker, rule); +      goto failed; +    } +   +  bus_match_rule_unref (rule); +  dbus_free (text); +   +  return TRUE; + + failed: +  _DBUS_ASSERT_ERROR_IS_SET (error); +  if (rule) +    bus_match_rule_unref (rule); +  if (text) +    dbus_free (text); +  return FALSE; +} + +static dbus_bool_t +bus_driver_handle_remove_match (DBusConnection *connection, +                                BusTransaction *transaction, +                                DBusMessage    *message, +                                DBusError      *error) +{ +  BusMatchRule *rule; +  char *text; +  DBusString str; +  BusMatchmaker *matchmaker; +   +  _DBUS_ASSERT_ERROR_IS_CLEAR (error); + +  text = NULL; +  rule = NULL; +   +  if (!dbus_message_get_args (message, error, +                              DBUS_TYPE_STRING, &text, +                              DBUS_TYPE_INVALID)) +    { +      _dbus_verbose ("No memory to get arguments to RemoveMatch\n"); +      goto failed; +    } + +  _dbus_string_init_const (&str, text); + +  rule = bus_match_rule_parse (connection, &str, error); +  if (rule == NULL) +    goto failed; + +  /* Send the ack before we remove the rule, since the ack is undone +   * on transaction cancel, but rule removal isn't. +   */ +  if (!send_ack_reply (connection, transaction, +                       message, error)) +    goto failed; +   +  matchmaker = bus_connection_get_matchmaker (connection); + +  if (!bus_matchmaker_remove_rule_by_value (matchmaker, rule, error)) +    goto failed; + +  bus_match_rule_unref (rule); +  dbus_free (text); +   +  return TRUE; + + failed: +  _DBUS_ASSERT_ERROR_IS_SET (error); +  if (rule) +    bus_match_rule_unref (rule); +  if (text) +    dbus_free (text); +  return FALSE; +} +  /* For speed it might be useful to sort this in order of   * frequency of use (but doesn't matter with only a few items   * anyhow) @@ -616,7 +772,9 @@ struct    { "ActivateService", bus_driver_handle_activate_service },    { "Hello", bus_driver_handle_hello },    { "ServiceExists", bus_driver_handle_service_exists }, -  { "ListServices", bus_driver_handle_list_services } +  { "ListServices", bus_driver_handle_list_services }, +  { "AddMatch", bus_driver_handle_add_match }, +  { "RemoveMatch", bus_driver_handle_remove_match }  };  dbus_bool_t  | 
