From a0cc21f8bb6752ffe0ee5f4f5b575dc50d6d46ae Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 22 Apr 2009 03:41:05 +0200 Subject: unix-fd: add message encoding/decoding for unix fds When appending unix fds to the message a new entry in the fd array will be allocated and the index to it will be written to the message payload. When parsing unix fds from the message the index will be read from the payload and then looked up in the fd array. When we read fds we put them in a queue first. Since each message knows how many fds are attached to it we will then pop enough fds from this queue each time we decode a message from the stream. This should make sending and receiving more portable since we don't make any strong requirements on the exact semantics of the SCM_RIGHTS implementation: as long as fds are recieved in order, none or lost and the arrive at the same time as at least one byte from the actual message dat we should be able to handle them correctly. --- dbus/dbus-transport.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'dbus/dbus-transport.c') diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index 35b7027d..97ee0e9b 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -29,6 +29,8 @@ #include "dbus-auth.h" #include "dbus-address.h" #include "dbus-credentials.h" +#include "dbus-message-private.h" +#include "dbus-marshal-header.h" #ifdef DBUS_BUILD_TESTS #include "dbus-server-debug-pipe.h" #endif @@ -180,7 +182,13 @@ _dbus_transport_init_base (DBusTransport *transport, /* credentials read from socket if any */ transport->credentials = creds; - + +#ifdef HAVE_UNIX_FD_PASSING + transport->can_pass_unix_fd = FALSE; + transport->unix_fds = NULL; + transport->n_unix_fds = 0; +#endif + _dbus_counter_set_notify (transport->live_messages_size, transport->max_live_messages_size, live_messages_size_notify, @@ -188,7 +196,7 @@ _dbus_transport_init_base (DBusTransport *transport, if (transport->address) _dbus_verbose ("Initialized transport on address %s\n", transport->address); - + return TRUE; } @@ -802,6 +810,18 @@ _dbus_transport_get_is_anonymous (DBusTransport *transport) return FALSE; } +/** + * Returns TRUE if the transport supports sending unix fds. + * + * @param transport the transport + * @returns #TRUE if TRUE it is possible to send unix fds across the transport. + */ +dbus_bool_t +_dbus_transport_can_pass_unix_fd(DBusTransport *transport) +{ + return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport); +} + /** * Gets the address of a transport. It will be * #NULL for a server-side transport. -- cgit From c200e0304d6f53a0fd47f524386b02b27c0c45f6 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Apr 2009 04:38:27 +0200 Subject: auth: add fd passing negotiation support This adds two new directives to the auth protocol: NEGOTIATE_UNIX_FD is sent by the client after the authentication was sucessful, i.e. OK was received. AGREE_UNIX_FD is then sent by the server if it can do unix fd passing as well. ERROR is returned when the server cannot or is unwilling to do unix fd passing. This should be compatible with existing D-Bus implementations which will naturally return ERROR on NEGOTIATE_UNIX_FD. --- dbus/dbus-transport.c | 1 - 1 file changed, 1 deletion(-) (limited to 'dbus/dbus-transport.c') diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index 97ee0e9b..7ba01357 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -184,7 +184,6 @@ _dbus_transport_init_base (DBusTransport *transport, transport->credentials = creds; #ifdef HAVE_UNIX_FD_PASSING - transport->can_pass_unix_fd = FALSE; transport->unix_fds = NULL; transport->n_unix_fds = 0; #endif -- cgit From bfad32422f1f78bce4de1e88a4afb5cc295bb877 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 20 May 2009 01:32:46 +0200 Subject: unix-fd: add logic to count unix fds the same way as allocated memory This make all counters count both bytes of memory and unix fds. --- dbus/dbus-transport.c | 94 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 76 insertions(+), 18 deletions(-) (limited to 'dbus/dbus-transport.c') diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index 7ba01357..11edc6a8 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -57,7 +57,7 @@ */ static void -live_messages_size_notify (DBusCounter *counter, +live_messages_notify (DBusCounter *counter, void *user_data) { DBusTransport *transport = user_data; @@ -65,8 +65,10 @@ live_messages_size_notify (DBusCounter *counter, _dbus_transport_ref (transport); #if 0 - _dbus_verbose ("Counter value is now %d\n", - (int) _dbus_counter_get_value (counter)); + _dbus_verbose ("Size counter value is now %d\n", + (int) _dbus_counter_get_size_value (counter)); + _dbus_verbose ("Unix FD counter value is now %d\n", + (int) _dbus_counter_get_unix_fd_value (counter)); #endif /* disable or re-enable the read watch for the transport if @@ -157,7 +159,7 @@ _dbus_transport_init_base (DBusTransport *transport, transport->vtable = vtable; transport->loader = loader; transport->auth = auth; - transport->live_messages_size = counter; + transport->live_messages = counter; transport->authenticated = FALSE; transport->disconnected = FALSE; transport->is_server = (server_guid != NULL); @@ -180,17 +182,17 @@ _dbus_transport_init_base (DBusTransport *transport, */ transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63; + /* On Linux RLIMIT_NOFILE defaults to 1024, so allowing 4096 fds live + should be more than enough */ + transport->max_live_messages_unix_fds = 4096; + /* credentials read from socket if any */ transport->credentials = creds; -#ifdef HAVE_UNIX_FD_PASSING - transport->unix_fds = NULL; - transport->n_unix_fds = 0; -#endif - - _dbus_counter_set_notify (transport->live_messages_size, + _dbus_counter_set_notify (transport->live_messages, transport->max_live_messages_size, - live_messages_size_notify, + transport->max_live_messages_unix_fds, + live_messages_notify, transport); if (transport->address) @@ -219,9 +221,9 @@ _dbus_transport_finalize_base (DBusTransport *transport) _dbus_message_loader_unref (transport->loader); _dbus_auth_unref (transport->auth); - _dbus_counter_set_notify (transport->live_messages_size, - 0, NULL, NULL); - _dbus_counter_unref (transport->live_messages_size); + _dbus_counter_set_notify (transport->live_messages, + 0, 0, NULL, NULL); + _dbus_counter_unref (transport->live_messages); dbus_free (transport->address); dbus_free (transport->expected_guid); if (transport->credentials) @@ -1078,7 +1080,8 @@ recover_unused_bytes (DBusTransport *transport) DBusDispatchStatus _dbus_transport_get_dispatch_status (DBusTransport *transport) { - if (_dbus_counter_get_value (transport->live_messages_size) >= transport->max_live_messages_size) + if (_dbus_counter_get_size_value (transport->live_messages) >= transport->max_live_messages_size || + _dbus_counter_get_unix_fd_value (transport->live_messages) >= transport->max_live_messages_unix_fds) return DBUS_DISPATCH_COMPLETE; /* complete for now */ if (!_dbus_transport_get_is_authenticated (transport)) @@ -1135,7 +1138,7 @@ _dbus_transport_queue_messages (DBusTransport *transport) _dbus_verbose ("queueing received message %p\n", message); - if (!_dbus_message_add_size_counter (message, transport->live_messages_size)) + if (!_dbus_message_add_counter (message, transport->live_messages)) { _dbus_message_loader_putback_message_link (transport->loader, link); @@ -1172,6 +1175,19 @@ _dbus_transport_set_max_message_size (DBusTransport *transport, _dbus_message_loader_set_max_message_size (transport->loader, size); } +/** + * See dbus_connection_set_max_message_unix_fds(). + * + * @param transport the transport + * @param n the max number of unix fds of a single message + */ +void +_dbus_transport_set_max_message_unix_fds (DBusTransport *transport, + long n) +{ + _dbus_message_loader_set_max_message_unix_fds (transport->loader, n); +} + /** * See dbus_connection_get_max_message_size(). * @@ -1184,6 +1200,18 @@ _dbus_transport_get_max_message_size (DBusTransport *transport) return _dbus_message_loader_get_max_message_size (transport->loader); } +/** + * See dbus_connection_get_max_message_unix_fds(). + * + * @param transport the transport + * @returns max message unix fds + */ +long +_dbus_transport_get_max_message_unix_fds (DBusTransport *transport) +{ + return _dbus_message_loader_get_max_message_unix_fds (transport->loader); +} + /** * See dbus_connection_set_max_received_size(). * @@ -1195,12 +1223,30 @@ _dbus_transport_set_max_received_size (DBusTransport *transport, long size) { transport->max_live_messages_size = size; - _dbus_counter_set_notify (transport->live_messages_size, + _dbus_counter_set_notify (transport->live_messages, transport->max_live_messages_size, - live_messages_size_notify, + transport->max_live_messages_unix_fds, + live_messages_notify, transport); } +/** + * See dbus_connection_set_max_received_unix_fds(). + * + * @param transport the transport + * @param n the max unix fds of all incoming messages + */ +void +_dbus_transport_set_max_received_unix_fds (DBusTransport *transport, + long n) +{ + transport->max_live_messages_unix_fds = n; + _dbus_counter_set_notify (transport->live_messages, + transport->max_live_messages_size, + transport->max_live_messages_unix_fds, + live_messages_notify, + transport); +} /** * See dbus_connection_get_max_received_size(). @@ -1214,6 +1260,18 @@ _dbus_transport_get_max_received_size (DBusTransport *transport) return transport->max_live_messages_size; } +/** + * See dbus_connection_set_max_received_unix_fds(). + * + * @param transport the transport + * @returns max unix fds for all live messages + */ +long +_dbus_transport_get_max_received_unix_fds (DBusTransport *transport) +{ + return transport->max_live_messages_unix_fds; +} + /** * See dbus_connection_get_unix_user(). * -- cgit