diff options
author | Havoc Pennington <hp@redhat.com> | 2007-06-18 19:32:51 +0000 |
---|---|---|
committer | Havoc Pennington <hp@redhat.com> | 2007-06-18 19:32:51 +0000 |
commit | 54b943432c7c947db88066751dd36a372cc9a618 (patch) | |
tree | 9b3eb7bc94cc0058c3fbcf2dc361fac40561a210 | |
parent | ded479fda43da9dbe5780d0a2b287b5b1dcac64e (diff) |
2007-06-18 Havoc Pennington <hp@redhat.com>
* 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
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | bus/bus.c | 10 | ||||
-rw-r--r-- | bus/bus.h | 2 | ||||
-rw-r--r-- | bus/driver.c | 69 | ||||
-rw-r--r-- | dbus/dbus-bus.c | 79 | ||||
-rw-r--r-- | dbus/dbus-bus.h | 2 | ||||
-rw-r--r-- | dbus/dbus-connection.c | 45 | ||||
-rw-r--r-- | dbus/dbus-connection.h | 1 | ||||
-rw-r--r-- | dbus/dbus-server.c | 61 | ||||
-rw-r--r-- | dbus/dbus-server.h | 1 | ||||
-rw-r--r-- | dbus/dbus-transport.c | 16 | ||||
-rw-r--r-- | dbus/dbus-transport.h | 1 | ||||
-rw-r--r-- | doc/dbus-specification.xml | 36 | ||||
-rw-r--r-- | test/Makefile.am | 6 | ||||
-rw-r--r-- | test/name-test/Makefile.am | 8 | ||||
-rwxr-xr-x | test/name-test/run-test.sh | 11 | ||||
-rw-r--r-- | test/name-test/test-ids.c | 55 |
17 files changed, 397 insertions, 22 deletions
@@ -1,5 +1,19 @@ 2007-06-18 Havoc Pennington <hp@redhat.com> - + + * 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 + +2007-06-18 Havoc Pennington <hp@redhat.com> + * dbus/dbus-sysdeps-unix.c (_dbus_read_credentials_socket): clean this up a little bit, to try and understand why telnet'ing to a server and sending a non-nul byte didn't disconnect immediately; @@ -38,6 +38,7 @@ struct BusContext { int refcount; + DBusGUID uuid; char *config_file; char *type; char *address; @@ -552,6 +553,8 @@ bus_context_new (const DBusString *config_file, } context->refcount = 1; + _dbus_generate_uuid (&context->uuid); + if (!_dbus_string_copy_data (config_file, &context->config_file)) { BUS_SET_OOM (error); @@ -785,6 +788,13 @@ bus_context_new (const DBusString *config_file, } dbus_bool_t +bus_context_get_id (BusContext *context, + DBusString *uuid) +{ + return _dbus_uuid_encode (&context->uuid, uuid); +} + +dbus_bool_t bus_context_reload_config (BusContext *context, DBusError *error) { @@ -78,6 +78,8 @@ dbus_bool_t bus_context_reload_config (BusContext void bus_context_shutdown (BusContext *context); BusContext* bus_context_ref (BusContext *context); void bus_context_unref (BusContext *context); +dbus_bool_t bus_context_get_id (BusContext *context, + DBusString *uuid); const char* bus_context_get_type (BusContext *context); const char* bus_context_get_address (BusContext *context); BusRegistry* bus_context_get_registry (BusContext *context); diff --git a/bus/driver.c b/bus/driver.c index 69084330..ebe355cd 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -1382,6 +1382,61 @@ bus_driver_handle_reload_config (DBusConnection *connection, return FALSE; } +static dbus_bool_t +bus_driver_handle_get_id (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, + DBusError *error) +{ + BusContext *context; + DBusMessage *reply; + DBusString uuid; + const char *v_STRING; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + if (!_dbus_string_init (&uuid)) + { + BUS_SET_OOM (error); + return FALSE; + } + + reply = NULL; + + context = bus_connection_get_context (connection); + if (!bus_context_get_id (context, &uuid)) + goto oom; + + reply = dbus_message_new_method_return (message); + if (reply == NULL) + goto oom; + + v_STRING = _dbus_string_get_const_data (&uuid); + if (!dbus_message_append_args (reply, + DBUS_TYPE_STRING, &v_STRING, + DBUS_TYPE_INVALID)) + goto oom; + + _dbus_assert (dbus_message_has_signature (reply, "s")); + + if (! bus_transaction_send_from_driver (transaction, connection, reply)) + goto oom; + + _dbus_string_free (&uuid); + dbus_message_unref (reply); + return TRUE; + + oom: + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + BUS_SET_OOM (error); + + if (reply) + dbus_message_unref (reply); + _dbus_string_free (&uuid); + 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) @@ -1396,6 +1451,10 @@ struct DBusMessage *message, DBusError *error); } message_handlers[] = { + { "Hello", + "", + DBUS_TYPE_STRING_AS_STRING, + bus_driver_handle_hello }, { "RequestName", DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING, DBUS_TYPE_UINT32_AS_STRING, @@ -1408,10 +1467,6 @@ struct DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING, DBUS_TYPE_UINT32_AS_STRING, bus_driver_handle_activate_service }, - { "Hello", - "", - DBUS_TYPE_STRING_AS_STRING, - bus_driver_handle_hello }, { "NameHasOwner", DBUS_TYPE_STRING_AS_STRING, DBUS_TYPE_BOOLEAN_AS_STRING, @@ -1455,7 +1510,11 @@ struct { "ReloadConfig", "", "", - bus_driver_handle_reload_config } + bus_driver_handle_reload_config }, + { "GetId", + "", + DBUS_TYPE_STRING_AS_STRING, + bus_driver_handle_get_id } }; static dbus_bool_t 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 @@ -2845,6 +2845,51 @@ dbus_connection_get_is_anonymous (DBusConnection *connection) } /** + * 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 * the disconnect signal run; handlers can cancel the exit by calling 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 @@ -799,6 +799,43 @@ dbus_server_get_address (DBusServer *server) } /** + * 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 * created. If the new connection function increments the connection's @@ -1110,6 +1147,7 @@ dbus_server_get_data (DBusServer *server, #ifdef DBUS_BUILD_TESTS #include "dbus-test.h" +#include <string.h> 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 @@ -792,6 +792,22 @@ _dbus_transport_get_address (DBusTransport *transport) } /** + * 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); diff --git a/doc/dbus-specification.xml b/doc/dbus-specification.xml index 878c2fa4..39bb7723 100644 --- a/doc/dbus-specification.xml +++ b/doc/dbus-specification.xml @@ -3824,6 +3824,42 @@ </para> </sect3> + <sect3 id="bus-messages-get-id"> + <title><literal>org.freedesktop.DBus.GetId</literal></title> + <para> + As a method: + <programlisting> + GetId (out STRING id) + </programlisting> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Unique ID identifying the bus daemon</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Gets the unique ID of the bus. The unique ID here is shared among all addresses the + bus daemon is listening on (TCP, UNIX domain socket, etc.) and its format is described in + <xref linkend="uuids"/>. Each address the bus is listening on also has its own unique + ID, as described in <xref linkend="addresses"/>. The per-bus and per-address IDs are not related. + There is also a per-machine ID, described in <xref linkend="standard-interfaces-peer"/> and returned + by org.freedesktop.DBus.Peer.GetMachineId(). + For a desktop session bus, the bus ID can be used as a way to uniquely identify a user's session. + </para> + </sect3> + </sect2> </sect1> diff --git a/test/Makefile.am b/test/Makefile.am index b3c9773b..3420c741 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,3 +1,5 @@ +## the "name-test" subdir in fact contains a bunch of tests now that need a temporary bus +## to be running to do stuff with. The directory should be renamed. SUBDIRS=name-test DIST_SUBDIRS=name-test @@ -6,9 +8,11 @@ INCLUDES=-I$(top_srcdir) $(DBUS_TEST_CFLAGS) if DBUS_BUILD_TESTS ## break-loader removed for now +## most of these binaries are used in tests but are not themselves tests TEST_BINARIES=test-service test-names test-shell-service shell-test spawn-test test-segfault test-exit test-sleep-forever -#enable stand alone make check test +## these are the things to run in make check (i.e. they are actual tests) +## (binaries in here must also be in TEST_BINARIES) TESTS=shell-test else TEST_BINARIES= diff --git a/test/name-test/Makefile.am b/test/name-test/Makefile.am index eec358aa..fbc80c42 100644 --- a/test/name-test/Makefile.am +++ b/test/name-test/Makefile.am @@ -16,7 +16,7 @@ if DBUS_BUILD_TESTS ## we use noinst_PROGRAMS not check_PROGRAMS for TESTS so that we ## build even when not doing "make check" -noinst_PROGRAMS=test-names test-pending-call-dispatch test-threads-init +noinst_PROGRAMS=test-names test-pending-call-dispatch test-threads-init test-ids test_names_SOURCES= \ test-names.c @@ -36,5 +36,11 @@ test_threads_init_SOURCES = \ test_threads_init_LDADD=$(top_builddir)/dbus/libdbus-convenience.la $(DBUS_TEST_LIBS) test_threads_init_LDFLAGS=@R_DYNAMIC_LDFLAG@ +test_ids_SOURCES = \ + test-ids.c + +test_ids_LDADD=$(top_builddir)/dbus/libdbus-convenience.la $(DBUS_TEST_LIBS) +test_ids_LDFLAGS=@R_DYNAMIC_LDFLAG@ + endif diff --git a/test/name-test/run-test.sh b/test/name-test/run-test.sh index bad5ca2e..0a1f7112 100755 --- a/test/name-test/run-test.sh +++ b/test/name-test/run-test.sh @@ -1,6 +1,6 @@ #! /bin/sh -ie() +die() { if ! test -z "$DBUS_SESSION_BUS_PID" ; then echo "killing message bus "$DBUS_SESSION_BUS_PID >&2 @@ -24,11 +24,14 @@ if test -z "$DBUS_TEST_NAME_IN_RUN_TEST"; then export DBUS_TEST_NAME_IN_RUN_TEST exec $DBUS_TOP_SRCDIR/tools/run-with-tmp-session-bus.sh $SCRIPTNAME $MODE fi +echo "running test-ids" +libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-ids || die "test-ids failed" + echo "running test-names" -libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-names || die "test-client failed" +libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-names || die "test-names failed" echo "running test-pending-call-dispatch" -libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-pending-call-dispatch || die "test-client failed" +libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-pending-call-dispatch || die "test-pending-call-dispatch failed" echo "running test-threads-init" -libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-threads-init || die "test-client failed" +libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-threads-init || die "test-threads-init failed" diff --git a/test/name-test/test-ids.c b/test/name-test/test-ids.c new file mode 100644 index 00000000..f08d4ac9 --- /dev/null +++ b/test/name-test/test-ids.c @@ -0,0 +1,55 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dbus/dbus.h> +#include <dbus/dbus-connection-internal.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +static void +die (const char *message) +{ + fprintf (stderr, "*** test-ids: %s", message); + exit (1); +} + +int +main (int argc, + char **argv) +{ + DBusError error; + DBusConnection *connection; + char *id; + char *server_id; + + dbus_error_init (&error); + connection = dbus_bus_get (DBUS_BUS_SESSION, &error); + if (connection == NULL) + { + fprintf (stderr, "*** Failed to open connection to system bus: %s\n", + error.message); + dbus_error_free (&error); + return 1; + } + + server_id = dbus_connection_get_server_id (connection); + if (server_id == NULL) + die ("No bus server ID retrieved\n"); + /* printf("'%s'\n", server_id); */ + if (strlen (server_id) != 32) + die ("Bus server id should have length 32\n"); + dbus_free (server_id); + + id = dbus_bus_get_id (connection, NULL); + if (id == NULL) + die ("No bus ID retrieved\n"); + /* printf("'%s'\n", id); */ + if (strlen (id) != 32) + die ("Bus ID should have length 32\n"); + dbus_free (id); + + _dbus_verbose ("*** Test IDs exiting\n"); + + return 0; +} |