From 54b943432c7c947db88066751dd36a372cc9a618 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Mon, 18 Jun 2007 19:32:51 +0000 Subject: 2007-06-18 Havoc Pennington * doc/dbus-specification.xml: document org.freedesktop.DBus.GetId() * bus/driver.c (bus_driver_handle_get_id): implement org.freedesktop.DBus.GetId() * bus/bus.c (bus_context_new): generate a unique ID for each bus context * dbus/dbus-connection.c (dbus_connection_get_server_id): new function * dbus/dbus-bus.c (dbus_bus_get_id): new function * dbus/dbus-server.c (dbus_server_get_id): new function --- dbus/dbus-bus.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++ dbus/dbus-bus.h | 2 ++ dbus/dbus-connection.c | 45 ++++++++++++++++++++++++++++ dbus/dbus-connection.h | 1 + dbus/dbus-server.c | 61 +++++++++++++++++++++++++++++++------- dbus/dbus-server.h | 1 + dbus/dbus-transport.c | 16 ++++++++++ dbus/dbus-transport.h | 1 + 8 files changed, 196 insertions(+), 10 deletions(-) (limited to 'dbus') diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c index 23428268..945f83d6 100644 --- a/dbus/dbus-bus.c +++ b/dbus/dbus-bus.c @@ -865,6 +865,85 @@ dbus_bus_get_unix_user (DBusConnection *connection, return (unsigned long) uid; } +/** + * Asks the bus to return its globally unique ID, as described in the + * D-Bus specification. For the session bus, this is useful as a way + * to uniquely identify each user session. For the system bus, + * probably the bus ID is not useful; instead, use the machine ID + * since it's accessible without necessarily connecting to the bus and + * may be persistent beyond a single bus instance (across reboots for + * example). See dbus_get_local_machine_id(). + * + * In addition to an ID for each bus and an ID for each machine, there is + * an ID for each address that the bus is listening on; that can + * be retrieved with dbus_connection_get_server_id(), though it is + * probably not very useful. + * + * @param connection the connection + * @param error location to store the error + * @returns the bus ID or #NULL if error is set + */ +char* +dbus_bus_get_id (DBusConnection *connection, + DBusError *error) +{ + DBusMessage *message, *reply; + char *id; + const char *v_STRING; + + _dbus_return_val_if_fail (connection != NULL, NULL); + _dbus_return_val_if_error_is_set (error, NULL); + + message = dbus_message_new_method_call (DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "GetId"); + + if (message == NULL) + { + _DBUS_SET_OOM (error); + return NULL; + } + + reply = dbus_connection_send_with_reply_and_block (connection, message, -1, + error); + + dbus_message_unref (message); + + if (reply == NULL) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + return NULL; + } + + if (dbus_set_error_from_message (error, reply)) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + dbus_message_unref (reply); + return NULL; + } + + v_STRING = NULL; + if (!dbus_message_get_args (reply, error, + DBUS_TYPE_STRING, &v_STRING, + DBUS_TYPE_INVALID)) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + dbus_message_unref (reply); + return NULL; + } + + id = _dbus_strdup (v_STRING); /* may be NULL */ + + dbus_message_unref (reply); + + if (id == NULL) + _DBUS_SET_OOM (error); + + /* FIXME it might be nice to cache the ID locally */ + + return id; +} /** * Asks the bus to assign the given name to this connection by invoking diff --git a/dbus/dbus-bus.h b/dbus/dbus-bus.h index e139254d..394de2cb 100644 --- a/dbus/dbus-bus.h +++ b/dbus/dbus-bus.h @@ -49,6 +49,8 @@ const char* dbus_bus_get_unique_name (DBusConnection *connection); unsigned long dbus_bus_get_unix_user (DBusConnection *connection, const char *name, DBusError *error); +char* dbus_bus_get_id (DBusConnection *connection, + DBusError *error); int dbus_bus_request_name (DBusConnection *connection, const char *name, unsigned int flags, diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 484873e6..62ef3dac 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -2844,6 +2844,51 @@ dbus_connection_get_is_anonymous (DBusConnection *connection) return res; } +/** + * Gets the ID of the server address we are authenticated to, if this + * connection is on the client side. If the connection is on the + * server side, this will always return #NULL - use dbus_server_get_id() + * to get the ID of your own server, if you are the server side. + * + * If a client-side connection is not authenticated yet, the ID may be + * available if it was included in the server address, but may not be + * available. The only way to be sure the server ID is available + * is to wait for authentication to complete. + * + * In general, each mode of connecting to a given server will have + * its own ID. So for example, if the session bus daemon is listening + * on UNIX domain sockets and on TCP, then each of those modalities + * will have its own server ID. + * + * If you want an ID that identifies an entire session bus, look at + * dbus_bus_get_id() instead (which is just a convenience wrapper + * around the org.freedesktop.DBus.GetId method invoked on the bus). + * + * You can also get a machine ID; see dbus_get_local_machine_id() to + * get the machine you are on. There isn't a convenience wrapper, but + * you can invoke org.freedesktop.DBus.Peer.GetMachineId on any peer + * to get the machine ID on the other end. + * + * The D-Bus specification describes the server ID and other IDs in a + * bit more detail. + * + * @param connection the connection + * @returns the server ID or #NULL if no memory or the connection is server-side + */ +char* +dbus_connection_get_server_id (DBusConnection *connection) +{ + char *id; + + _dbus_return_val_if_fail (connection != NULL, FALSE); + + CONNECTION_LOCK (connection); + id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport)); + CONNECTION_UNLOCK (connection); + + return id; +} + /** * Set whether _exit() should be called when the connection receives a * disconnect signal. The call to _exit() comes after any handlers for diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h index ec227604..3e074e33 100644 --- a/dbus/dbus-connection.h +++ b/dbus/dbus-connection.h @@ -179,6 +179,7 @@ void dbus_connection_close (DBusConnection dbus_bool_t dbus_connection_get_is_connected (DBusConnection *connection); dbus_bool_t dbus_connection_get_is_authenticated (DBusConnection *connection); dbus_bool_t dbus_connection_get_is_anonymous (DBusConnection *connection); +char* dbus_connection_get_server_id (DBusConnection *connection); void dbus_connection_set_exit_on_disconnect (DBusConnection *connection, dbus_bool_t exit_on_disconnect); void dbus_connection_flush (DBusConnection *connection); diff --git a/dbus/dbus-server.c b/dbus/dbus-server.c index 9fc5cace..7d18e615 100644 --- a/dbus/dbus-server.c +++ b/dbus/dbus-server.c @@ -798,6 +798,43 @@ dbus_server_get_address (DBusServer *server) return retval; } +/** + * Returns the unique ID of the server, as a newly-allocated + * string which must be freed by the caller. This ID is + * normally used by clients to tell when two #DBusConnection + * would be equivalent (because the server address passed + * to dbus_connection_open() will have the same guid in the + * two cases). dbus_connection_open() can re-use an existing + * connection with the same ID instead of opening a new + * connection. + * + * This is an ID unique to each #DBusServer. Remember that + * a #DBusServer represents only one mode of connecting, + * so e.g. a bus daemon can listen on multiple addresses + * which will mean it has multiple #DBusServer each with + * their own ID. + * + * The ID is not a UUID in the sense of RFC4122; the details + * are explained in the D-Bus specification. + * + * @param server the server + * @returns the id of the server or #NULL if no memory + */ +char* +dbus_server_get_id (DBusServer *server) +{ + char *retval; + + _dbus_return_val_if_fail (server != NULL, NULL); + + SERVER_LOCK (server); + retval = NULL; + _dbus_string_copy_data (&server->guid_hex, &retval); + SERVER_UNLOCK (server); + + return retval; +} + /** * Sets a function to be used for handling new connections. The given * function is passed each new connection as the connection is @@ -1110,6 +1147,7 @@ dbus_server_get_data (DBusServer *server, #ifdef DBUS_BUILD_TESTS #include "dbus-test.h" +#include dbus_bool_t _dbus_server_test (void) @@ -1130,8 +1168,8 @@ _dbus_server_test (void) for (i = 0; i < _DBUS_N_ELEMENTS (valid_addresses); i++) { DBusError error; - - /* FIXME um, how are the two tests here different? */ + char *address; + char *id; dbus_error_init (&error); server = dbus_server_listen (valid_addresses[i], &error); @@ -1142,18 +1180,21 @@ _dbus_server_test (void) _dbus_assert_not_reached ("Failed to listen for valid address."); } - dbus_server_disconnect (server); - dbus_server_unref (server); + id = dbus_server_get_id (server); + _dbus_assert (id != NULL); + address = dbus_server_get_address (server); + _dbus_assert (address != NULL); - /* Try disconnecting before unreffing */ - server = dbus_server_listen (valid_addresses[i], &error); - if (server == NULL) + if (strstr (address, id) == NULL) { - _dbus_warn ("server listen error: %s: %s\n", error.name, error.message); - dbus_error_free (&error); - _dbus_assert_not_reached ("Failed to listen for valid address."); + _dbus_warn ("server id '%s' is not in the server address '%s'\n", + id, address); + _dbus_assert_not_reached ("bad server id or address"); } + dbus_free (id); + dbus_free (address); + dbus_server_disconnect (server); dbus_server_unref (server); } diff --git a/dbus/dbus-server.h b/dbus/dbus-server.h index 58e00289..a1e84493 100644 --- a/dbus/dbus-server.h +++ b/dbus/dbus-server.h @@ -55,6 +55,7 @@ void dbus_server_unref (DBusServer *server); void dbus_server_disconnect (DBusServer *server); dbus_bool_t dbus_server_get_is_connected (DBusServer *server); char* dbus_server_get_address (DBusServer *server); +char* dbus_server_get_id (DBusServer *server); void dbus_server_set_new_connection_function (DBusServer *server, DBusNewConnectionFunction function, void *data, diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index 3edef937..d78727cf 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -791,6 +791,22 @@ _dbus_transport_get_address (DBusTransport *transport) return transport->address; } +/** + * Gets the id of the server we are connected to (see + * dbus_server_get_id()). Only works on client side. + * + * @param transport the transport + * @returns transport's server's id or #NULL if we are the server side + */ +const char* +_dbus_transport_get_server_id (DBusTransport *transport) +{ + if (transport->is_server) + return NULL; + else + return transport->expected_guid; +} + /** * Handles a watch by reading data, writing data, or disconnecting * the transport, as appropriate for the given condition. diff --git a/dbus/dbus-transport.h b/dbus/dbus-transport.h index 3335c46b..d6e414cb 100644 --- a/dbus/dbus-transport.h +++ b/dbus/dbus-transport.h @@ -41,6 +41,7 @@ dbus_bool_t _dbus_transport_get_is_connected (DBusTransport dbus_bool_t _dbus_transport_get_is_authenticated (DBusTransport *transport); dbus_bool_t _dbus_transport_get_is_anonymous (DBusTransport *transport); const char* _dbus_transport_get_address (DBusTransport *transport); +const char* _dbus_transport_get_server_id (DBusTransport *transport); dbus_bool_t _dbus_transport_handle_watch (DBusTransport *transport, DBusWatch *watch, unsigned int condition); -- cgit