diff options
Diffstat (limited to 'bus/driver.c')
-rw-r--r-- | bus/driver.c | 250 |
1 files changed, 218 insertions, 32 deletions
diff --git a/bus/driver.c b/bus/driver.c index e0afd8ef..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> @@ -49,15 +50,17 @@ bus_driver_send_service_deleted (const char *service_name, _dbus_verbose ("sending service deleted: %s\n", service_name); - message = dbus_message_new (DBUS_MESSAGE_SERVICE_DELETED, - DBUS_SERVICE_BROADCAST); + message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS, + DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, + "ServiceDeleted"); + if (message == NULL) { BUS_SET_OOM (error); return FALSE; } - if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS) || + if (!dbus_message_set_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) || !dbus_message_append_args (message, DBUS_TYPE_STRING, service_name, DBUS_TYPE_INVALID)) @@ -67,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; @@ -83,15 +86,17 @@ bus_driver_send_service_created (const char *service_name, _DBUS_ASSERT_ERROR_IS_CLEAR (error); - message = dbus_message_new (DBUS_MESSAGE_SERVICE_CREATED, - DBUS_SERVICE_BROADCAST); + message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS, + DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, + "ServiceCreated"); + if (message == NULL) { BUS_SET_OOM (error); return FALSE; } - if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS)) + if (!dbus_message_set_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS)) { dbus_message_unref (message); BUS_SET_OOM (error); @@ -107,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; @@ -123,15 +128,18 @@ bus_driver_send_service_lost (DBusConnection *connection, _DBUS_ASSERT_ERROR_IS_CLEAR (error); - message = dbus_message_new (DBUS_MESSAGE_SERVICE_LOST, - bus_connection_get_name (connection)); + message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS, + DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, + "ServiceLost"); + if (message == NULL) { BUS_SET_OOM (error); return FALSE; } - if (!dbus_message_append_args (message, + if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) || + !dbus_message_append_args (message, DBUS_TYPE_STRING, service_name, DBUS_TYPE_INVALID)) { @@ -163,8 +171,9 @@ bus_driver_send_service_acquired (DBusConnection *connection, _DBUS_ASSERT_ERROR_IS_CLEAR (error); - message = dbus_message_new (DBUS_MESSAGE_SERVICE_ACQUIRED, - bus_connection_get_name (connection)); + message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS, + DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, + "ServiceAcquired"); if (message == NULL) { @@ -172,7 +181,8 @@ bus_driver_send_service_acquired (DBusConnection *connection, return FALSE; } - if (!dbus_message_append_args (message, + if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) || + !dbus_message_append_args (message, DBUS_TYPE_STRING, service_name, DBUS_TYPE_INVALID)) { @@ -322,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: @@ -343,7 +354,7 @@ bus_driver_send_welcome_message (DBusConnection *connection, name = bus_connection_get_name (connection); _dbus_assert (name != NULL); - welcome = dbus_message_new_reply (hello_message); + welcome = dbus_message_new_method_return (hello_message); if (welcome == NULL) { BUS_SET_OOM (error); @@ -387,7 +398,7 @@ bus_driver_handle_list_services (DBusConnection *connection, registry = bus_connection_get_registry (connection); - reply = dbus_message_new_reply (message); + reply = dbus_message_new_method_return (message); if (reply == NULL) { BUS_SET_OOM (error); @@ -463,7 +474,7 @@ bus_driver_handle_acquire_service (DBusConnection *connection, error)) goto out; - reply = dbus_message_new_reply (message); + reply = dbus_message_new_method_return (message); if (reply == NULL) { BUS_SET_OOM (error); @@ -518,7 +529,7 @@ bus_driver_handle_service_exists (DBusConnection *connection, _dbus_string_init_const (&service_name, name); service = bus_registry_lookup (registry, &service_name); - reply = dbus_message_new_reply (message); + reply = dbus_message_new_method_return (message); if (reply == NULL) { BUS_SET_OOM (error); @@ -591,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) @@ -603,11 +768,13 @@ struct DBusMessage *message, DBusError *error); } message_handlers[] = { - { DBUS_MESSAGE_ACQUIRE_SERVICE, bus_driver_handle_acquire_service }, - { DBUS_MESSAGE_ACTIVATE_SERVICE, bus_driver_handle_activate_service }, - { DBUS_MESSAGE_HELLO, bus_driver_handle_hello }, - { DBUS_MESSAGE_SERVICE_EXISTS, bus_driver_handle_service_exists }, - { DBUS_MESSAGE_LIST_SERVICES, bus_driver_handle_list_services } + { "AcquireService", bus_driver_handle_acquire_service }, + { "ActivateService", bus_driver_handle_activate_service }, + { "Hello", bus_driver_handle_hello }, + { "ServiceExists", bus_driver_handle_service_exists }, + { "ListServices", bus_driver_handle_list_services }, + { "AddMatch", bus_driver_handle_add_match }, + { "RemoveMatch", bus_driver_handle_remove_match } }; dbus_bool_t @@ -620,15 +787,32 @@ bus_driver_handle_message (DBusConnection *connection, int i; _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL) + { + _dbus_verbose ("Driver got a non-method-call message, ignoring\n"); + return TRUE; /* we just ignore this */ + } + + _dbus_assert (dbus_message_get_interface (message) != NULL); + _dbus_assert (dbus_message_get_member (message) != NULL); + + name = dbus_message_get_member (message); + sender = dbus_message_get_sender (message); - _dbus_verbose ("Driver got a message: %s\n", - dbus_message_get_name (message)); + if (strcmp (dbus_message_get_interface (message), + DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS) != 0) + { + _dbus_verbose ("Driver got message to unknown interface \"%s\"\n", + dbus_message_get_interface (message)); + goto unknown; + } + + _dbus_verbose ("Driver got a method call: %s\n", + dbus_message_get_member (message)); - name = dbus_message_get_name (message); - sender = dbus_message_get_sender (message); - /* security checks should have kept this from getting here */ - _dbus_assert (sender != NULL || strcmp (name, DBUS_MESSAGE_HELLO) == 0); + _dbus_assert (sender != NULL || strcmp (name, "Hello") == 0); if (dbus_message_get_reply_serial (message) == 0) { @@ -659,11 +843,13 @@ bus_driver_handle_message (DBusConnection *connection, ++i; } - _dbus_verbose ("No driver handler for %s\n", name); + unknown: + _dbus_verbose ("No driver handler for message \"%s\"\n", + name); - dbus_set_error (error, DBUS_ERROR_UNKNOWN_MESSAGE, + dbus_set_error (error, DBUS_ERROR_UNKNOWN_METHOD, "%s does not understand message %s", - DBUS_SERVICE_DBUS, name); + DBUS_SERVICE_ORG_FREEDESKTOP_DBUS, name); return FALSE; } |