From de83f66a6f6bfff028442b83fcdede551806ebda Mon Sep 17 00:00:00 2001 From: Alban Crequy Date: Mon, 30 Jun 2014 13:44:58 +0100 Subject: [PATCH] Implement GetConnectionMatchRules on the Stats interface Usage: $ dbus-send --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus \ org.freedesktop.DBus.Debug.Stats.GetConnectionMatchRules method return sender=org.freedesktop.DBus -> dest=:1.13 reply_serial=2 array [ dict entry( string ":1.4" array [ ] ) dict entry( string ":1.9" array [ string "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'" ] ) dict entry( string ":1.11" array [ string "eavesdrop='true'" ] ) ] https://bugs.freedesktop.org/show_bug.cgi?id=24307 --- bus/driver.c | 1 + bus/signals.c | 75 +++++++++++++++++++++++++++++++++++++- bus/signals.h | 6 ++++ bus/stats.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- bus/stats.h | 5 +++ 5 files changed, 199 insertions(+), 2 deletions(-) diff --git a/bus/driver.c b/bus/driver.c index e95a79d..fd52883 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -1789,6 +1789,7 @@ static const MessageHandler introspectable_message_handlers[] = { static const MessageHandler stats_message_handlers[] = { { "GetStats", "", "a{sv}", bus_stats_handle_get_stats }, { "GetConnectionStats", "s", "a{sv}", bus_stats_handle_get_connection_stats }, + { "GetConnectionMatchRules", "", "a{sas}", bus_stats_handle_get_connection_match_rules }, { NULL, NULL, NULL, NULL } }; #endif diff --git a/bus/signals.c b/bus/signals.c index 4c500c6..6bf33c9 100644 --- a/bus/signals.c +++ b/bus/signals.c @@ -119,6 +119,14 @@ bus_match_rule_unref (BusMatchRule *rule) } #ifdef DBUS_ENABLE_VERBOSE_MODE +#define MATCH_RULE_TO_STRING +#endif + +#ifdef DBUS_ENABLE_STATS +#define MATCH_RULE_TO_STRING +#endif + +#ifdef MATCH_RULE_TO_STRING /* Note this function does not do escaping, so it's only * good for debug spew at the moment */ @@ -279,7 +287,8 @@ match_rule_to_string (BusMatchRule *rule) return s; } } -#endif /* DBUS_ENABLE_VERBOSE_MODE */ +#undef MATCH_RULE_TO_STRING +#endif /* DBUS_ENABLE_VERBOSE_MODE || DBUS_ENABLE_STATS */ dbus_bool_t bus_match_rule_set_message_type (BusMatchRule *rule, @@ -1141,6 +1150,70 @@ struct BusMatchmaker RulePool rules_by_type[DBUS_NUM_MESSAGE_TYPES]; }; +#ifdef DBUS_ENABLE_STATS +dbus_bool_t +bus_match_rule_dump (BusMatchmaker *matchmaker, + DBusConnection *conn_filter, + DBusMessageIter *arr_iter) +{ + int i; + + for (i = 0 ; i < DBUS_NUM_MESSAGE_TYPES ; i++) + { + DBusHashIter iter; + DBusList *list; + DBusList *link; + + _dbus_hash_iter_init (matchmaker->rules_by_type[i].rules_by_iface, &iter); + while (_dbus_hash_iter_next (&iter)) + { + list = *((DBusList **)_dbus_hash_iter_get_value (&iter)); + link = _dbus_list_get_first_link (&list); + while (link != NULL) + { + DBusList *next = _dbus_list_get_next_link (&list, link); + BusMatchRule *rule = link->data; + + if (rule->matches_go_to == conn_filter) + { + char *s = match_rule_to_string (rule); + if (!dbus_message_iter_append_basic (arr_iter, DBUS_TYPE_STRING, &s)) + { + dbus_free (s); + return FALSE; + } + dbus_free (s); + } + + link = next; + } + } + list = matchmaker->rules_by_type[i].rules_without_iface; + link = _dbus_list_get_first_link (&list); + while (link != NULL) + { + DBusList *next = _dbus_list_get_next_link (&list, link); + BusMatchRule *rule = link->data; + + if (rule->matches_go_to == conn_filter) + { + char *s = match_rule_to_string (rule); + if (!dbus_message_iter_append_basic (arr_iter, DBUS_TYPE_STRING, &s)) + { + dbus_free (s); + return FALSE; + } + dbus_free (s); + } + + link = next; + } + } + + return TRUE; +} +#endif + static void rule_list_free (DBusList **rules) { diff --git a/bus/signals.h b/bus/signals.h index a71d2e4..d19fc7c 100644 --- a/bus/signals.h +++ b/bus/signals.h @@ -77,6 +77,12 @@ BusMatchRule* bus_match_rule_parse (DBusConnection *matches_go_to, const DBusString *rule_text, DBusError *error); +#ifdef DBUS_ENABLE_STATS +dbus_bool_t bus_match_rule_dump (BusMatchmaker *matchmaker, + DBusConnection *conn_filter, + DBusMessageIter *arr_iter); +#endif + BusMatchmaker* bus_matchmaker_new (void); BusMatchmaker* bus_matchmaker_ref (BusMatchmaker *matchmaker); void bus_matchmaker_unref (BusMatchmaker *matchmaker); diff --git a/bus/stats.c b/bus/stats.c index 2bf86d6..43d1520 100644 --- a/bus/stats.c +++ b/bus/stats.c @@ -30,6 +30,7 @@ #include "connection.h" #include "services.h" +#include "signals.h" #include "utils.h" #ifdef DBUS_ENABLE_STATS @@ -40,6 +41,7 @@ bus_stats_handle_get_stats (DBusConnection *connection, DBusMessage *message, DBusError *error) { + BusContext *context; BusConnections *connections; DBusMessage *reply = NULL; DBusMessageIter iter, arr_iter; @@ -48,7 +50,8 @@ bus_stats_handle_get_stats (DBusConnection *connection, _DBUS_ASSERT_ERROR_IS_CLEAR (error); - connections = bus_context_get_connections (transaction->context); + context = bus_transaction_get_context (transaction); + connections = bus_context_get_connections (context); reply = _dbus_asv_new_method_return (message, &iter, &arr_iter); @@ -215,4 +218,113 @@ oom: return FALSE; } + +dbus_bool_t +bus_stats_handle_get_connection_match_rules (DBusConnection *caller_connection, + BusTransaction *transaction, + DBusMessage *message, + DBusError *error) +{ + BusContext *context; + DBusString bus_name_str; + DBusMessage *reply = NULL; + DBusMessageIter iter, hash_iter, entry_iter, arr_iter; + BusRegistry *registry; + char **services = NULL; + int services_len; + DBusConnection *conn_filter = NULL; + BusMatchmaker *matchmaker; + int i; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + registry = bus_connection_get_registry (caller_connection); + context = bus_transaction_get_context (transaction); + matchmaker = bus_context_get_matchmaker (context); + + if (!bus_registry_list_services (registry, &services, &services_len)) + return FALSE; + + reply = dbus_message_new_method_return (message); + if (reply == NULL) + goto oom; + + dbus_message_iter_init_append (reply, &iter); + + if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{sas}", + &hash_iter)) + goto oom; + + for (i = 0 ; i < services_len ; i++) + { + BusService *service; + + /* To avoid duplicate entries, only look for unique names */ + if (services[i][0] != ':') + continue; + + _dbus_string_init_const (&bus_name_str, services[i]); + service = bus_registry_lookup (registry, &bus_name_str); + _dbus_assert (service != NULL); + + conn_filter = bus_service_get_primary_owners_connection (service); + _dbus_assert (conn_filter != NULL); + + if (!dbus_message_iter_open_container (&hash_iter, DBUS_TYPE_DICT_ENTRY, NULL, + &entry_iter)) + { + dbus_message_iter_abandon_container (&iter, &hash_iter); + goto oom; + } + + if (!dbus_message_iter_append_basic (&entry_iter, DBUS_TYPE_STRING, &services[i])) + { + dbus_message_iter_abandon_container (&hash_iter, &entry_iter); + dbus_message_iter_abandon_container (&iter, &hash_iter); + goto oom; + } + + if (!dbus_message_iter_open_container (&entry_iter, DBUS_TYPE_ARRAY, "s", + &arr_iter)) + { + dbus_message_iter_abandon_container (&hash_iter, &entry_iter); + dbus_message_iter_abandon_container (&iter, &hash_iter); + goto oom; + } + + if (!bus_match_rule_dump (matchmaker, conn_filter, &arr_iter)) + { + dbus_message_iter_abandon_container (&entry_iter, &arr_iter); + dbus_message_iter_abandon_container (&hash_iter, &entry_iter); + dbus_message_iter_abandon_container (&iter, &hash_iter); + goto oom; + } + + if (!dbus_message_iter_close_container (&entry_iter, &arr_iter)) + goto oom; + if (!dbus_message_iter_close_container (&hash_iter, &entry_iter)) + goto oom; + + } + + if (!dbus_message_iter_close_container (&iter, &hash_iter)) + goto oom; + + if (!bus_transaction_send_from_driver (transaction, caller_connection, + reply)) + goto oom; + + dbus_message_unref (reply); + return TRUE; + +oom: + if (reply != NULL) + dbus_message_unref (reply); + + dbus_free_string_array (services); + + BUS_SET_OOM (error); + return FALSE; +} + #endif diff --git a/bus/stats.h b/bus/stats.h index 0f843db..6d19cde 100644 --- a/bus/stats.h +++ b/bus/stats.h @@ -35,4 +35,9 @@ dbus_bool_t bus_stats_handle_get_connection_stats (DBusConnection *connection, DBusMessage *message, DBusError *error); +dbus_bool_t bus_stats_handle_get_connection_match_rules (DBusConnection *caller_connection, + BusTransaction *transaction, + DBusMessage *message, + DBusError *error); + #endif /* multiple-inclusion guard */ -- 1.8.5.3