summaryrefslogtreecommitdiff
path: root/bus/driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'bus/driver.c')
-rw-r--r--bus/driver.c164
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