diff options
author | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2015-02-02 19:45:17 +0000 |
---|---|---|
committer | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2015-02-04 17:15:17 +0000 |
commit | 9fce7380331d24e8dd5fb9203eb8275ebb49e1d8 (patch) | |
tree | 6f655086533c73df8b24166c0e7b39f38b7939f3 /bus/driver.c | |
parent | 00af6389be46d65afcce8cdfd060f278aaaa9466 (diff) | |
download | dbus-9fce7380331d24e8dd5fb9203eb8275ebb49e1d8.tar.gz |
Capture all messages received or sent, and send them to monitors
Unlike eavesdropping, the point of capture is when the message is
received, except for messages originating inside the dbus-daemon.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=46787
Reviewed-by: Philip Withnall <philip.withnall@collabora.co.uk>
Diffstat (limited to 'bus/driver.c')
-rw-r--r-- | bus/driver.c | 99 |
1 files changed, 92 insertions, 7 deletions
diff --git a/bus/driver.c b/bus/driver.c index ac29b9f1..793dbfb0 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -217,6 +217,9 @@ bus_driver_send_service_owner_changed (const char *service_name, _dbus_assert (dbus_message_has_signature (message, "sss")); + if (!bus_transaction_capture (transaction, NULL, message)) + goto oom; + retval = bus_dispatch_matches (transaction, NULL, NULL, message, error); dbus_message_unref (message); @@ -1794,27 +1797,109 @@ bus_driver_handle_become_monitor (DBusConnection *connection, DBusMessage *message, DBusError *error) { + char **match_rules = NULL; + BusMatchRule *rule; + DBusList *rules = NULL; + DBusList *iter; + DBusString str; + int i; + int n_match_rules; + dbus_uint32_t flags; + dbus_bool_t ret = FALSE; + _DBUS_ASSERT_ERROR_IS_CLEAR (error); if (!bus_driver_check_message_is_for_us (message, error)) - return FALSE; + goto out; if (!bus_driver_check_caller_is_privileged (connection, transaction, message, error)) - return FALSE; + goto out; + + if (!dbus_message_get_args (message, error, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &match_rules, &n_match_rules, + DBUS_TYPE_UINT32, &flags, + DBUS_TYPE_INVALID)) + goto out; + + if (flags != 0) + { + dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, + "BecomeMonitor does not support any flags yet"); + goto out; + } + + /* Special case: a zero-length array becomes [""] */ + if (n_match_rules == 0) + { + match_rules = dbus_malloc (2 * sizeof (char *)); + + if (match_rules == NULL) + { + BUS_SET_OOM (error); + goto out; + } + + match_rules[0] = _dbus_strdup (""); + + if (match_rules[0] == NULL) + { + BUS_SET_OOM (error); + goto out; + } + + match_rules[1] = NULL; + n_match_rules = 1; + } + + for (i = 0; i < n_match_rules; i++) + { + _dbus_string_init_const (&str, match_rules[i]); + rule = bus_match_rule_parse (connection, &str, error); + + if (rule == NULL) + { + BUS_SET_OOM (error); + goto out; + } + + /* monitors always eavesdrop */ + bus_match_rule_set_client_is_eavesdropping (rule, TRUE); + + if (!_dbus_list_append (&rules, rule)) + { + BUS_SET_OOM (error); + bus_match_rule_unref (rule); + goto out; + } + } /* Send the ack before we remove the rule, since the ack is undone * on transaction cancel, but becoming a monitor isn't. */ if (!send_ack_reply (connection, transaction, message, error)) - return FALSE; + goto out; - /* FIXME: use the array of filters from the message */ + if (!bus_connection_be_monitor (connection, transaction, &rules, error)) + goto out; - if (!bus_connection_be_monitor (connection, transaction, error)) - return FALSE; + ret = TRUE; - return TRUE; +out: + if (ret) + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + else + _DBUS_ASSERT_ERROR_IS_SET (error); + + for (iter = _dbus_list_get_first_link (&rules); + iter != NULL; + iter = _dbus_list_get_next_link (&rules, iter)) + bus_match_rule_unref (iter->data); + + _dbus_list_clear (&rules); + + dbus_free_string_array (match_rules); + return ret; } typedef struct |