From 1915619b3f6e58a495bc74d9618f94b00d757f5e Mon Sep 17 00:00:00 2001 From: Christian Dywan Date: Wed, 12 May 2010 17:46:35 +0200 Subject: [PATCH 5/5] Implement optional DBUS_CAPABILITY_FLAGS Unix FD support is enabled automatically just like before. --- dbus/dbus-auth.c | 10 +++- dbus/dbus-bus.c | 106 +++++++++++++++++++++++++++++++-- dbus/dbus-bus.h | 9 +++ dbus/dbus-connection.c | 134 ++++++++++++++++++++++++++++++++++++++++-- dbus/dbus-connection.h | 20 ++++++ dbus/dbus-transport-socket.c | 5 +- dbus/dbus-transport.c | 18 ++++++ dbus/dbus-transport.h | 2 + 8 files changed, 287 insertions(+), 17 deletions(-) diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c index efaeafa..6bf7ac1 100644 --- a/dbus/dbus-auth.c +++ b/dbus/dbus-auth.c @@ -2141,13 +2141,15 @@ handle_client_state_waiting_for_agree_unix_fd(DBusAuth *auth, _dbus_assert(auth->unix_fd_possible); auth->unix_fd_negotiated = TRUE; _dbus_verbose("Sucessfully negotiated UNIX FD passing\n"); - return send_negotiate_maybe (auth); + return auth->maybe_possible + ? send_negotiate_maybe (auth) : send_begin (auth); case DBUS_AUTH_COMMAND_ERROR: _dbus_assert(auth->unix_fd_possible); auth->unix_fd_negotiated = FALSE; _dbus_verbose("Failed to negotiate UNIX FD passing\n"); - return send_negotiate_maybe (auth); + return auth->maybe_possible + ? send_negotiate_maybe (auth) : send_begin (auth); case DBUS_AUTH_COMMAND_OK: case DBUS_AUTH_COMMAND_DATA: @@ -2389,6 +2391,10 @@ _dbus_auth_server_new (const DBusString *guid) */ server_auth->failures = 0; server_auth->max_failures = 6; +#ifdef HAVE_UNIX_FD_PASSING + _dbus_auth_set_unix_fd_possible (auth, TRUE); +#endif + _dbus_auth_set_maybe_possible (auth, TRUE); return auth; } diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c index 92ec20e..964be1f 100644 --- a/dbus/dbus-bus.c +++ b/dbus/dbus-bus.c @@ -422,9 +422,10 @@ _dbus_bus_notify_shared_connection_disconnected_unlocked (DBusConnection *connec } static DBusConnection * -internal_bus_get (DBusBusType type, - dbus_bool_t private, - DBusError *error) +internal_bus_get (DBusBusType type, + DBusCapabilityFlags flags, + dbus_bool_t private, + DBusError *error) { const char *address; DBusConnection *connection; @@ -464,6 +465,8 @@ internal_bus_get (DBusBusType type, dbus_connection_ref (connection); _DBUS_UNLOCK (bus); + if (flags) + _dbus_verbose ("Ignoring specified capability flags"); return connection; } @@ -477,9 +480,9 @@ internal_bus_get (DBusBusType type, } if (private) - connection = dbus_connection_open_private (address, error); + connection = dbus_connection_open_private_with_flags (address, flags, error); else - connection = dbus_connection_open (address, error); + connection = dbus_connection_open_with_flags (address, flags, error); if (!connection) { @@ -552,6 +555,9 @@ internal_bus_get (DBusBusType type, * after you get the connection. * * dbus_bus_get() calls dbus_bus_register() for you. + * + * Use dbus_bus_get_with_flags() instead if you plan to use optional + * capabilities like Unix file descriptors or Maybe types. * * If returning a newly-created connection, this function will block * until authentication and bus registration are complete. @@ -564,7 +570,50 @@ DBusConnection * dbus_bus_get (DBusBusType type, DBusError *error) { - return internal_bus_get (type, FALSE, error); + return internal_bus_get (type, 0, FALSE, error); +} + +/** + * Connects to a bus daemon and registers the client with it. If a + * connection to the bus already exists, then that connection is + * returned. The caller of this function owns a reference to the bus. + * + * The caller may NOT call dbus_connection_close() on this connection; + * see dbus_connection_open() and dbus_connection_close() for details + * on that. + * + * If this function obtains a new connection object never before + * returned from dbus_bus_get(), it will call + * dbus_connection_set_exit_on_disconnect(), so the application + * will exit if the connection closes. You can undo this + * by calling dbus_connection_set_exit_on_disconnect() yourself + * after you get the connection. + * + * dbus_bus_get() calls dbus_bus_register() for you. + * + * The specified @flags indicate what optional capabilities should + * be enabled, such as Unix file descriptors or Maybe types. The + * flags are only meaningful if the connection is newly-created, + * otherwise they have no effect. You have to check the supported + * capabilities afterwards with dbus_connection_get_capabilities(). + * + * Unix file descriptors are automatically enabled on supported systems, + * the flag can be used to determine if they are available. + * + * If returning a newly-created connection, this function will block + * until authentication and bus registration are complete. + * + * @param type bus type + * @param flags the optional capabilities to enable + * @param error address where an error can be returned. + * @returns a #DBusConnection with new ref + */ +DBusConnection * +dbus_bus_get_with_flags (DBusBusType type, + DBusCapabilityFlags flags, + DBusError *error) +{ + return internal_bus_get (type, flags, FALSE, error); } /** @@ -596,7 +645,50 @@ DBusConnection * dbus_bus_get_private (DBusBusType type, DBusError *error) { - return internal_bus_get (type, TRUE, error); + return internal_bus_get (type, 0, TRUE, error); +} + +/** + * Connects to a bus daemon and registers the client with it as with + * dbus_bus_register(). Unlike dbus_bus_get(), always creates a new + * connection. This connection will not be saved or recycled by + * libdbus. Caller owns a reference to the bus and must either close + * it or know it to be closed prior to releasing this reference. + * + * See dbus_connection_open_private() for more details on when to + * close and unref this connection. + * + * This function calls + * dbus_connection_set_exit_on_disconnect() on the new connection, so the application + * will exit if the connection closes. You can undo this + * by calling dbus_connection_set_exit_on_disconnect() yourself + * after you get the connection. + * + * dbus_bus_get_private() calls dbus_bus_register() for you. + * + * The specified @flags indicate what optional capabilities should + * be enabled, such as Unix file descriptors or Maybe types. The + * flags are only meaningful if the connection is newly-created, + * otherwise they have no effect. You have to check the supported + * capabilities afterwards with dbus_connection_get_capabilities(). + * + * Unix file descriptors are automatically enabled on supported systems, + * the flag can be used to determine if they are available. + * + * This function will block until authentication and bus registration + * are complete. + * + * @param type bus type + * @param flags the optional capabilities to enable + * @param error address where an error can be returned. + * @returns a DBusConnection with new ref + */ +DBusConnection * +dbus_bus_get_private_with_flags (DBusBusType type, + DBusCapabilityFlags flags, + DBusError *error) +{ + return internal_bus_get (type, 0, TRUE, error); } /** diff --git a/dbus/dbus-bus.h b/dbus/dbus-bus.h index 02a9571..c204d38 100644 --- a/dbus/dbus-bus.h +++ b/dbus/dbus-bus.h @@ -40,8 +40,17 @@ DBUS_EXPORT DBusConnection *dbus_bus_get (DBusBusType type, DBusError *error); DBUS_EXPORT +DBusConnection *dbus_bus_get_with_flags (DBusBusType type, + DBusCapabilityFlags flags, + DBusError *error); + +DBUS_EXPORT DBusConnection *dbus_bus_get_private (DBusBusType type, DBusError *error); +DBUS_EXPORT +DBusConnection *dbus_bus_get_private_with_flags (DBusBusType type, + DBusCapabilityFlags flags, + DBusError *error); DBUS_EXPORT dbus_bool_t dbus_bus_register (DBusConnection *connection, diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index c5cf815..4aa1543 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -1774,13 +1774,15 @@ connection_forget_shared_unlocked (DBusConnection *connection) } static DBusConnection* -connection_try_from_address_entry (DBusAddressEntry *entry, - DBusError *error) +connection_try_from_address_entry (DBusAddressEntry *entry, + DBusCapabilityFlags flags, + DBusError *error) { DBusTransport *transport; DBusConnection *connection; transport = _dbus_transport_open (entry, error); + _dbus_transport_set_capabilities (transport, flags); if (transport == NULL) { @@ -1812,14 +1814,16 @@ connection_try_from_address_entry (DBusAddressEntry *entry, * never be returned to other callers. * * @param address the address + * @param flags the optional capabilities to enable * @param shared whether the connection is shared or private * @param error error return * @returns the connection or #NULL on error */ static DBusConnection* -_dbus_connection_open_internal (const char *address, - dbus_bool_t shared, - DBusError *error) +_dbus_connection_open_internal (const char *address, + DBusCapabilityFlags flags, + dbus_bool_t shared, + DBusError *error) { DBusConnection *connection; DBusAddressEntry **entries; @@ -1850,6 +1854,7 @@ _dbus_connection_open_internal (const char *address, if (connection == NULL) { connection = connection_try_from_address_entry (entries[i], + flags, &tmp_error); if (connection != NULL && shared) @@ -2572,6 +2577,54 @@ dbus_connection_open (const char *address, _dbus_return_val_if_error_is_set (error, NULL); connection = _dbus_connection_open_internal (address, + 0, + TRUE, + error); + + return connection; +} + +/** + * Gets a connection to a remote address. If a connection to the given + * address already exists, returns the existing connection with its + * reference count incremented. Otherwise, returns a new connection + * and saves the new connection for possible re-use if a future call + * to dbus_connection_open() asks to connect to the same server. + * + * Use dbus_connection_open_private() to get a dedicated connection + * not shared with other callers of dbus_connection_open(). + * + * If the open fails, the function returns #NULL, and provides a + * reason for the failure in the error parameter. Pass #NULL for the + * error parameter if you aren't interested in the reason for + * failure. + * + * Because this connection is shared, no user of the connection + * may call dbus_connection_close(). However, when you are done with the + * connection you should call dbus_connection_unref(). + * + * @note Prefer dbus_connection_open() to dbus_connection_open_private() + * unless you have good reason; connections are expensive enough + * that it's wasteful to create lots of connections to the same + * server. + * + * @param address the address. + * @param flags the optional capabilities to enable + * @param error address where an error can be returned. + * @returns new connection, or #NULL on failure. + */ +DBusConnection* +dbus_connection_open_with_flags (const char *address, + DBusCapabilityFlags flags, + DBusError *error) +{ + DBusConnection *connection; + + _dbus_return_val_if_fail (address != NULL, NULL); + _dbus_return_val_if_error_is_set (error, NULL); + + connection = _dbus_connection_open_internal (address, + flags, TRUE, error); @@ -2615,6 +2668,7 @@ dbus_connection_open_private (const char *address, _dbus_return_val_if_error_is_set (error, NULL); connection = _dbus_connection_open_internal (address, + 0, FALSE, error); @@ -2622,6 +2676,76 @@ dbus_connection_open_private (const char *address, } /** + * Opens a new, dedicated connection to a remote address. Unlike + * dbus_connection_open(), always creates a new connection. + * This connection will not be saved or recycled by libdbus. + * + * If the open fails, the function returns #NULL, and provides a + * reason for the failure in the error parameter. Pass #NULL for the + * error parameter if you aren't interested in the reason for + * failure. + * + * When you are done with this connection, you must + * dbus_connection_close() to disconnect it, + * and dbus_connection_unref() to free the connection object. + * + * (The dbus_connection_close() can be skipped if the + * connection is already known to be disconnected, for example + * if you are inside a handler for the Disconnected signal.) + * + * @note Prefer dbus_connection_open() to dbus_connection_open_private() + * unless you have good reason; connections are expensive enough + * that it's wasteful to create lots of connections to the same + * server. + * + * @param address the address. + * @param flags the optional capabilities to enable + * @param error address where an error can be returned. + * @returns new connection, or #NULL on failure. + */ +DBusConnection* +dbus_connection_open_private_with_flags (const char *address, + DBusCapabilityFlags flags, + DBusError *error) +{ + DBusConnection *connection; + + _dbus_return_val_if_fail (address != NULL, NULL); + _dbus_return_val_if_error_is_set (error, NULL); + + connection = _dbus_connection_open_internal (address, + flags, + FALSE, + error); + + return connection; +} + +/** + * Determines the optionally supported capabilities. The + * capabilities must have been previously enabled through + * dbus_connection_open_private_with_flags(), + * dbus_connection_open_private_with_flags() or + * dbus_bus_get_with_flags(). + * + * @param connection the connection. + * @returns the supported capabilities + */ +DBusCapabilityFlags +dbus_connection_get_flags (DBusConnection *connection) +{ + DBusCapabilityFlags flags = 0; + + _dbus_return_val_if_fail (connection != NULL, 0); + + if (_dbus_transport_can_pass_unix_fd (connection->transport)) + flags |= DBUS_CAPABILITY_UNIX_FD; + if (_dbus_transport_can_pass_maybe (connection->transport)) + flags |= DBUS_CAPABILITY_MAYBE; + return flags; +} + +/** * Increments the reference count of a DBusConnection. * * @param connection the connection. diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h index 3e2a7d8..710576e 100644 --- a/dbus/dbus-connection.h +++ b/dbus/dbus-connection.h @@ -53,6 +53,15 @@ typedef struct DBusConnection DBusConnection; typedef struct DBusObjectPathVTable DBusObjectPathVTable; /** + * Describes the optional capabilities the API user can handle. + */ +typedef enum +{ + DBUS_CAPABILITY_UNIX_FD = 1 << 0, /**< Unix file descriptors supported */ + DBUS_CAPABILITY_MAYBE = 1 << 1, /**< Maybe types supported */ +} DBusCapabilityFlags; + +/** * Indicates the status of a #DBusWatch. */ typedef enum @@ -172,9 +181,20 @@ DBUS_EXPORT DBusConnection* dbus_connection_open (const char *address, DBusError *error); DBUS_EXPORT +DBusConnection* dbus_connection_open_with_flags (const char *address, + DBusCapabilityFlags flags, + DBusError *error); + +DBUS_EXPORT DBusConnection* dbus_connection_open_private (const char *address, DBusError *error); DBUS_EXPORT +DBusConnection* dbus_connection_open_private_with_flags (const char *address, + DBusCapabilityFlags flags, + DBusError *error); +DBUS_EXPORT +DBusCapabilityFlags dbus_connection_get_flags (DBusConnection *connection); +DBUS_EXPORT DBusConnection* dbus_connection_ref (DBusConnection *connection); DBUS_EXPORT void dbus_connection_unref (DBusConnection *connection); diff --git a/dbus/dbus-transport-socket.c b/dbus/dbus-transport-socket.c index 28fd49b..3798561 100644 --- a/dbus/dbus-transport-socket.c +++ b/dbus/dbus-transport-socket.c @@ -1265,11 +1265,10 @@ _dbus_transport_new_for_socket (int fd, goto failed_4; #ifdef HAVE_UNIX_FD_PASSING - _dbus_auth_set_unix_fd_possible(socket_transport->base.auth, _dbus_socket_can_pass_unix_fd(fd)); + if (!_dbus_socket_can_pass_unix_fd (fd)) + _dbus_auth_set_unix_fd_possible(socket_transport->base.auth, FALSE); #endif - _dbus_auth_set_maybe_possible (socket_transport->base.auth, TRUE); - socket_transport->fd = fd; socket_transport->message_bytes_written = 0; diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index bb35529..29efee2 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -817,6 +817,24 @@ _dbus_transport_get_is_anonymous (DBusTransport *transport) } /** + * Enables sending of optional types via the transport. + * + * @param transport the transport + * @param flags the optional capabilities to enable + */ +void +_dbus_transport_set_capabilities (DBusTransport *transport, + DBusCapabilityFlags flags) +{ +#ifdef HAVE_UNIX_FD_PASSING + if (flags & DBUS_CAPABILITY_UNIX_FD) + _dbus_auth_set_unix_fd_possible (transport->auth, TRUE); +#endif + if (flags & DBUS_CAPABILITY_MAYBE) + _dbus_auth_set_maybe_possible (transport->auth, TRUE); +} + +/** * Returns TRUE if the transport supports sending unix fds. * * @param transport the transport diff --git a/dbus/dbus-transport.h b/dbus/dbus-transport.h index a0d3972..ba236b4 100644 --- a/dbus/dbus-transport.h +++ b/dbus/dbus-transport.h @@ -40,6 +40,8 @@ void _dbus_transport_disconnect (DBusTransport dbus_bool_t _dbus_transport_get_is_connected (DBusTransport *transport); dbus_bool_t _dbus_transport_get_is_authenticated (DBusTransport *transport); dbus_bool_t _dbus_transport_get_is_anonymous (DBusTransport *transport); +void _dbus_transport_set_capabilities (DBusTransport *transport, + DBusCapabilityFlags flags); dbus_bool_t _dbus_transport_can_pass_unix_fd (DBusTransport *transport); dbus_bool_t _dbus_transport_can_pass_maybe (DBusTransport *transport); -- 1.7.3.2