1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-transport.c DBusTransport object (internal to D-Bus implementation)
4 * Copyright (C) 2002, 2003 Red Hat Inc.
6 * Licensed under the Academic Free License version 2.1
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "dbus-transport-protected.h"
25 #include "dbus-transport-unix.h"
26 #include "dbus-transport-socket.h"
27 #include "dbus-connection-internal.h"
28 #include "dbus-watch.h"
29 #include "dbus-auth.h"
30 #include "dbus-address.h"
31 #include "dbus-credentials.h"
32 #include "dbus-message-private.h"
33 #include "dbus-marshal-header.h"
34 #ifdef DBUS_BUILD_TESTS
35 #include "dbus-server-debug-pipe.h"
39 * @defgroup DBusTransport DBusTransport object
40 * @ingroup DBusInternals
41 * @brief "Backend" for a DBusConnection.
43 * Types and functions related to DBusTransport. A transport is an
44 * abstraction that can send and receive data via various kinds of
45 * network connections or other IPC mechanisms.
51 * @typedef DBusTransport
53 * Opaque object representing a way message stream.
54 * DBusTransport abstracts various kinds of actual
55 * transport mechanism, such as different network protocols,
56 * or encryption schemes.
60 live_messages_size_notify (DBusCounter *counter,
63 DBusTransport *transport = user_data;
65 _dbus_transport_ref (transport);
68 _dbus_verbose ("Counter value is now %d\n",
69 (int) _dbus_counter_get_value (counter));
72 /* disable or re-enable the read watch for the transport if
75 if (transport->vtable->live_messages_changed)
76 (* transport->vtable->live_messages_changed) (transport);
78 _dbus_transport_unref (transport);
82 * Initializes the base class members of DBusTransport. Chained up to
83 * by subclasses in their constructor. The server GUID is the
84 * globally unique ID for the server creating this connection
85 * and will be #NULL for the client side of a connection. The GUID
88 * @param transport the transport being created.
89 * @param vtable the subclass vtable.
90 * @param server_guid non-#NULL if this transport is on the server side of a connection
91 * @param address the address of the transport
92 * @returns #TRUE on success.
95 _dbus_transport_init_base (DBusTransport *transport,
96 const DBusTransportVTable *vtable,
97 const DBusString *server_guid,
98 const DBusString *address)
100 DBusMessageLoader *loader;
102 DBusCounter *counter;
104 DBusCredentials *creds;
106 loader = _dbus_message_loader_new ();
111 auth = _dbus_auth_server_new (server_guid);
113 auth = _dbus_auth_client_new ();
116 _dbus_message_loader_unref (loader);
120 counter = _dbus_counter_new ();
123 _dbus_auth_unref (auth);
124 _dbus_message_loader_unref (loader);
128 creds = _dbus_credentials_new ();
131 _dbus_counter_unref (counter);
132 _dbus_auth_unref (auth);
133 _dbus_message_loader_unref (loader);
139 _dbus_assert (address == NULL);
144 _dbus_assert (address != NULL);
146 if (!_dbus_string_copy_data (address, &address_copy))
148 _dbus_credentials_unref (creds);
149 _dbus_counter_unref (counter);
150 _dbus_auth_unref (auth);
151 _dbus_message_loader_unref (loader);
156 transport->refcount = 1;
157 transport->vtable = vtable;
158 transport->loader = loader;
159 transport->auth = auth;
160 transport->live_messages_size = counter;
161 transport->authenticated = FALSE;
162 transport->disconnected = FALSE;
163 transport->is_server = (server_guid != NULL);
164 transport->send_credentials_pending = !transport->is_server;
165 transport->receive_credentials_pending = transport->is_server;
166 transport->address = address_copy;
168 transport->unix_user_function = NULL;
169 transport->unix_user_data = NULL;
170 transport->free_unix_user_data = NULL;
172 transport->windows_user_function = NULL;
173 transport->windows_user_data = NULL;
174 transport->free_windows_user_data = NULL;
176 transport->expected_guid = NULL;
178 /* Try to default to something that won't totally hose the system,
179 * but doesn't impose too much of a limitation.
181 transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
183 /* credentials read from socket if any */
184 transport->credentials = creds;
186 #ifdef HAVE_UNIX_FD_PASSING
187 transport->unix_fds = NULL;
188 transport->n_unix_fds = 0;
191 _dbus_counter_set_notify (transport->live_messages_size,
192 transport->max_live_messages_size,
193 live_messages_size_notify,
196 if (transport->address)
197 _dbus_verbose ("Initialized transport on address %s\n", transport->address);
203 * Finalizes base class members of DBusTransport.
204 * Chained up to from subclass finalizers.
206 * @param transport the transport.
209 _dbus_transport_finalize_base (DBusTransport *transport)
211 if (!transport->disconnected)
212 _dbus_transport_disconnect (transport);
214 if (transport->free_unix_user_data != NULL)
215 (* transport->free_unix_user_data) (transport->unix_user_data);
217 if (transport->free_windows_user_data != NULL)
218 (* transport->free_windows_user_data) (transport->windows_user_data);
220 _dbus_message_loader_unref (transport->loader);
221 _dbus_auth_unref (transport->auth);
222 _dbus_counter_set_notify (transport->live_messages_size,
224 _dbus_counter_unref (transport->live_messages_size);
225 dbus_free (transport->address);
226 dbus_free (transport->expected_guid);
227 if (transport->credentials)
228 _dbus_credentials_unref (transport->credentials);
233 * Verifies if a given D-Bus address is a valid address
234 * by attempting to connect to it. If it is, returns the
235 * opened DBusTransport object. If it isn't, returns #NULL
238 * @param error address where an error can be returned.
239 * @returns a new transport, or #NULL on failure.
241 static DBusTransport*
242 check_address (const char *address, DBusError *error)
244 DBusAddressEntry **entries;
245 DBusTransport *transport = NULL;
248 _dbus_assert (address != NULL);
249 _dbus_assert (*address != '\0');
251 if (!dbus_parse_address (address, &entries, &len, error))
252 return NULL; /* not a valid address */
254 for (i = 0; i < len; i++)
256 transport = _dbus_transport_open (entries[i], error);
257 if (transport != NULL)
261 dbus_address_entries_free (entries);
266 * Creates a new transport for the "autostart" method.
267 * This creates a client-side of a transport.
269 * @param error address where an error can be returned.
270 * @returns a new transport, or #NULL on failure.
272 static DBusTransport*
273 _dbus_transport_new_for_autolaunch (DBusError *error)
276 DBusTransport *result = NULL;
278 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
280 if (!_dbus_string_init (&address))
282 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
286 if (!_dbus_get_autolaunch_address (&address, error))
288 _DBUS_ASSERT_ERROR_IS_SET (error);
292 result = check_address (_dbus_string_get_const_data (&address), error);
294 _DBUS_ASSERT_ERROR_IS_SET (error);
296 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
299 _dbus_string_free (&address);
303 static DBusTransportOpenResult
304 _dbus_transport_open_autolaunch (DBusAddressEntry *entry,
305 DBusTransport **transport_p,
310 method = dbus_address_entry_get_method (entry);
311 _dbus_assert (method != NULL);
313 if (strcmp (method, "autolaunch") == 0)
315 *transport_p = _dbus_transport_new_for_autolaunch (error);
317 if (*transport_p == NULL)
319 _DBUS_ASSERT_ERROR_IS_SET (error);
320 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
324 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
325 return DBUS_TRANSPORT_OPEN_OK;
330 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
331 return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
335 static const struct {
336 DBusTransportOpenResult (* func) (DBusAddressEntry *entry,
337 DBusTransport **transport_p,
340 { _dbus_transport_open_socket },
341 { _dbus_transport_open_platform_specific },
342 { _dbus_transport_open_autolaunch }
343 #ifdef DBUS_BUILD_TESTS
344 , { _dbus_transport_open_debug_pipe }
349 * Try to open a new transport for the given address entry. (This
350 * opens a client-side-of-the-connection transport.)
352 * @param entry the address entry
353 * @param error location to store reason for failure.
354 * @returns new transport of #NULL on failure.
357 _dbus_transport_open (DBusAddressEntry *entry,
360 DBusTransport *transport;
361 const char *expected_guid_orig;
364 DBusError tmp_error = DBUS_ERROR_INIT;
366 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
369 expected_guid_orig = dbus_address_entry_get_value (entry, "guid");
370 expected_guid = _dbus_strdup (expected_guid_orig);
372 if (expected_guid_orig != NULL && expected_guid == NULL)
374 _DBUS_SET_OOM (error);
378 for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i)
380 DBusTransportOpenResult result;
382 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
383 result = (* open_funcs[i].func) (entry, &transport, &tmp_error);
387 case DBUS_TRANSPORT_OPEN_OK:
388 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
391 case DBUS_TRANSPORT_OPEN_NOT_HANDLED:
392 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
393 /* keep going through the loop of open funcs */
395 case DBUS_TRANSPORT_OPEN_BAD_ADDRESS:
396 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
399 case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT:
400 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
408 if (transport == NULL)
410 if (!dbus_error_is_set (&tmp_error))
411 _dbus_set_bad_address (&tmp_error,
413 "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")");
415 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
416 dbus_move_error(&tmp_error, error);
417 dbus_free (expected_guid);
421 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
423 /* In the case of autostart the initial guid is NULL
424 * and the autostart transport recursively calls
425 * _dbus_open_transport wich returns a transport
426 * with a guid. That guid is the definitive one.
428 * FIXME: if more transports are added they may have
429 * an effect on the expected_guid semantics (i.e.
430 * expected_guid and transport->expected_guid may
431 * both have values). This is very unlikely though
432 * we should either throw asserts here for those
433 * corner cases or refactor the code so it is
434 * clearer on what is expected and what is not
437 transport->expected_guid = expected_guid;
444 * Increments the reference count for the transport.
446 * @param transport the transport.
447 * @returns the transport.
450 _dbus_transport_ref (DBusTransport *transport)
452 _dbus_assert (transport->refcount > 0);
454 transport->refcount += 1;
460 * Decrements the reference count for the transport.
461 * Disconnects and finalizes the transport if
462 * the reference count reaches zero.
464 * @param transport the transport.
467 _dbus_transport_unref (DBusTransport *transport)
469 _dbus_assert (transport != NULL);
470 _dbus_assert (transport->refcount > 0);
472 transport->refcount -= 1;
473 if (transport->refcount == 0)
475 _dbus_verbose ("%s: finalizing\n", _DBUS_FUNCTION_NAME);
477 _dbus_assert (transport->vtable->finalize != NULL);
479 (* transport->vtable->finalize) (transport);
484 * Closes our end of the connection to a remote application. Further
485 * attempts to use this transport will fail. Only the first call to
486 * _dbus_transport_disconnect() will have an effect.
488 * @param transport the transport.
492 _dbus_transport_disconnect (DBusTransport *transport)
494 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
496 _dbus_assert (transport->vtable->disconnect != NULL);
498 if (transport->disconnected)
501 (* transport->vtable->disconnect) (transport);
503 transport->disconnected = TRUE;
505 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
509 * Returns #TRUE if the transport has not been disconnected.
510 * Disconnection can result from _dbus_transport_disconnect()
511 * or because the server drops its end of the connection.
513 * @param transport the transport.
514 * @returns whether we're connected
517 _dbus_transport_get_is_connected (DBusTransport *transport)
519 return !transport->disconnected;
523 auth_via_unix_user_function (DBusTransport *transport)
525 DBusCredentials *auth_identity;
527 DBusConnection *connection;
528 DBusAllowUnixUserFunction unix_user_function;
529 void *unix_user_data;
532 /* Dropping the lock here probably isn't that safe. */
534 auth_identity = _dbus_auth_get_identity (transport->auth);
535 _dbus_assert (auth_identity != NULL);
537 connection = transport->connection;
538 unix_user_function = transport->unix_user_function;
539 unix_user_data = transport->unix_user_data;
540 uid = _dbus_credentials_get_unix_uid (auth_identity);
542 _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME);
543 _dbus_connection_unlock (connection);
545 allow = (* unix_user_function) (connection,
549 _dbus_verbose ("lock %s post unix user function\n", _DBUS_FUNCTION_NAME);
550 _dbus_connection_lock (connection);
554 _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid);
558 _dbus_verbose ("Client UID "DBUS_UID_FORMAT
559 " was rejected, disconnecting\n",
560 _dbus_credentials_get_unix_uid (auth_identity));
561 _dbus_transport_disconnect (transport);
568 auth_via_windows_user_function (DBusTransport *transport)
570 DBusCredentials *auth_identity;
572 DBusConnection *connection;
573 DBusAllowWindowsUserFunction windows_user_function;
574 void *windows_user_data;
577 /* Dropping the lock here probably isn't that safe. */
579 auth_identity = _dbus_auth_get_identity (transport->auth);
580 _dbus_assert (auth_identity != NULL);
582 connection = transport->connection;
583 windows_user_function = transport->windows_user_function;
584 windows_user_data = transport->unix_user_data;
585 windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
587 if (windows_sid == NULL)
593 _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME);
594 _dbus_connection_unlock (connection);
596 allow = (* windows_user_function) (connection,
600 _dbus_verbose ("lock %s post windows user function\n", _DBUS_FUNCTION_NAME);
601 _dbus_connection_lock (connection);
605 _dbus_verbose ("Client SID '%s' authorized\n", windows_sid);
609 _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n",
610 _dbus_credentials_get_windows_sid (auth_identity));
611 _dbus_transport_disconnect (transport);
618 auth_via_default_rules (DBusTransport *transport)
620 DBusCredentials *auth_identity;
621 DBusCredentials *our_identity;
624 auth_identity = _dbus_auth_get_identity (transport->auth);
625 _dbus_assert (auth_identity != NULL);
627 /* By default, connection is allowed if the client is 1) root or 2)
628 * has the same UID as us or 3) anonymous is allowed.
631 our_identity = _dbus_credentials_new_from_current_process ();
632 if (our_identity == NULL)
638 if (transport->allow_anonymous ||
639 _dbus_credentials_get_unix_uid (auth_identity) == 0 ||
640 _dbus_credentials_same_user (our_identity,
643 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
644 _dbus_verbose ("Client authorized as SID '%s'"
645 "matching our SID '%s'\n",
646 _dbus_credentials_get_windows_sid(auth_identity),
647 _dbus_credentials_get_windows_sid(our_identity));
649 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
650 " matching our UID "DBUS_UID_FORMAT"\n",
651 _dbus_credentials_get_unix_uid(auth_identity),
652 _dbus_credentials_get_unix_uid(our_identity));
653 /* We have authenticated! */
658 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
659 _dbus_verbose ("Client authorized as SID '%s'"
660 " but our SID is '%s', disconnecting\n",
661 _dbus_credentials_get_windows_sid(our_identity),
662 _dbus_credentials_get_windows_sid(our_identity));
664 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
665 " but our UID is "DBUS_UID_FORMAT", disconnecting\n",
666 _dbus_credentials_get_unix_uid(our_identity),
667 _dbus_credentials_get_unix_uid(our_identity));
668 _dbus_transport_disconnect (transport);
672 _dbus_credentials_unref (our_identity);
679 * Returns #TRUE if we have been authenticated. Will return #TRUE
680 * even if the transport is disconnected.
682 * @todo we drop connection->mutex when calling the unix_user_function,
683 * and windows_user_function, which may not be safe really.
685 * @param transport the transport
686 * @returns whether we're authenticated
689 _dbus_transport_get_is_authenticated (DBusTransport *transport)
691 if (transport->authenticated)
695 dbus_bool_t maybe_authenticated;
697 if (transport->disconnected)
700 /* paranoia ref since we call user callbacks sometimes */
701 _dbus_connection_ref_unlocked (transport->connection);
703 maybe_authenticated =
704 (!(transport->send_credentials_pending ||
705 transport->receive_credentials_pending));
707 if (maybe_authenticated)
709 switch (_dbus_auth_do_work (transport->auth))
711 case DBUS_AUTH_STATE_AUTHENTICATED:
712 /* leave as maybe_authenticated */
715 maybe_authenticated = FALSE;
719 /* If we're the client, verify the GUID
721 if (maybe_authenticated && !transport->is_server)
723 const char *server_guid;
725 server_guid = _dbus_auth_get_guid_from_server (transport->auth);
726 _dbus_assert (server_guid != NULL);
728 if (transport->expected_guid &&
729 strcmp (transport->expected_guid, server_guid) != 0)
731 _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n",
732 transport->expected_guid, server_guid);
733 _dbus_transport_disconnect (transport);
734 _dbus_connection_unref_unlocked (transport->connection);
738 if (transport->expected_guid == NULL)
740 transport->expected_guid = _dbus_strdup (server_guid);
742 if (transport->expected_guid == NULL)
744 _dbus_verbose ("No memory to complete auth in %s\n", _DBUS_FUNCTION_NAME);
750 /* If we're the server, see if we want to allow this identity to proceed.
752 if (maybe_authenticated && transport->is_server)
755 DBusCredentials *auth_identity;
757 auth_identity = _dbus_auth_get_identity (transport->auth);
758 _dbus_assert (auth_identity != NULL);
760 /* If we have an auth'd user and a user function, delegate
761 * deciding whether auth credentials are good enough to the
762 * app; otherwise, use our default decision process.
764 if (transport->unix_user_function != NULL &&
765 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID))
767 allow = auth_via_unix_user_function (transport);
769 else if (transport->windows_user_function != NULL &&
770 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID))
772 allow = auth_via_windows_user_function (transport);
776 allow = auth_via_default_rules (transport);
780 maybe_authenticated = FALSE;
783 transport->authenticated = maybe_authenticated;
785 _dbus_connection_unref_unlocked (transport->connection);
786 return maybe_authenticated;
791 * See dbus_connection_get_is_anonymous().
793 * @param transport the transport
794 * @returns #TRUE if not authenticated or authenticated as anonymous
797 _dbus_transport_get_is_anonymous (DBusTransport *transport)
799 DBusCredentials *auth_identity;
801 if (!transport->authenticated)
804 auth_identity = _dbus_auth_get_identity (transport->auth);
806 if (_dbus_credentials_are_anonymous (auth_identity))
813 * Returns TRUE if the transport supports sending unix fds.
815 * @param transport the transport
816 * @returns #TRUE if TRUE it is possible to send unix fds across the transport.
819 _dbus_transport_can_pass_unix_fd(DBusTransport *transport)
821 return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport);
825 * Gets the address of a transport. It will be
826 * #NULL for a server-side transport.
828 * @param transport the transport
829 * @returns transport's address
832 _dbus_transport_get_address (DBusTransport *transport)
834 return transport->address;
838 * Gets the id of the server we are connected to (see
839 * dbus_server_get_id()). Only works on client side.
841 * @param transport the transport
842 * @returns transport's server's id or #NULL if we are the server side
845 _dbus_transport_get_server_id (DBusTransport *transport)
847 if (transport->is_server)
850 return transport->expected_guid;
854 * Handles a watch by reading data, writing data, or disconnecting
855 * the transport, as appropriate for the given condition.
857 * @param transport the transport.
858 * @param watch the watch.
859 * @param condition the current state of the watched file descriptor.
860 * @returns #FALSE if not enough memory to fully handle the watch
863 _dbus_transport_handle_watch (DBusTransport *transport,
865 unsigned int condition)
869 _dbus_assert (transport->vtable->handle_watch != NULL);
871 if (transport->disconnected)
874 if (dbus_watch_get_socket (watch) < 0)
876 _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n");
880 _dbus_watch_sanitize_condition (watch, &condition);
882 _dbus_transport_ref (transport);
883 _dbus_watch_ref (watch);
884 retval = (* transport->vtable->handle_watch) (transport, watch, condition);
885 _dbus_watch_unref (watch);
886 _dbus_transport_unref (transport);
892 * Sets the connection using this transport. Allows the transport
893 * to add watches to the connection, queue incoming messages,
894 * and pull outgoing messages.
896 * @param transport the transport.
897 * @param connection the connection.
898 * @returns #FALSE if not enough memory
901 _dbus_transport_set_connection (DBusTransport *transport,
902 DBusConnection *connection)
904 _dbus_assert (transport->vtable->connection_set != NULL);
905 _dbus_assert (transport->connection == NULL);
907 transport->connection = connection;
909 _dbus_transport_ref (transport);
910 if (!(* transport->vtable->connection_set) (transport))
911 transport->connection = NULL;
912 _dbus_transport_unref (transport);
914 return transport->connection != NULL;
918 * Get the socket file descriptor, if any.
920 * @param transport the transport
921 * @param fd_p pointer to fill in with the descriptor
922 * @returns #TRUE if a descriptor was available
925 _dbus_transport_get_socket_fd (DBusTransport *transport,
930 if (transport->vtable->get_socket_fd == NULL)
933 if (transport->disconnected)
936 _dbus_transport_ref (transport);
938 retval = (* transport->vtable->get_socket_fd) (transport,
941 _dbus_transport_unref (transport);
947 * Performs a single poll()/select() on the transport's file
948 * descriptors and then reads/writes data as appropriate,
949 * queueing incoming messages and sending outgoing messages.
950 * This is the backend for _dbus_connection_do_iteration().
951 * See _dbus_connection_do_iteration() for full details.
953 * @param transport the transport.
954 * @param flags indicates whether to read or write, and whether to block.
955 * @param timeout_milliseconds if blocking, timeout or -1 for no timeout.
958 _dbus_transport_do_iteration (DBusTransport *transport,
960 int timeout_milliseconds)
962 _dbus_assert (transport->vtable->do_iteration != NULL);
964 _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
965 flags, timeout_milliseconds, !transport->disconnected);
967 if ((flags & (DBUS_ITERATION_DO_WRITING |
968 DBUS_ITERATION_DO_READING)) == 0)
969 return; /* Nothing to do */
971 if (transport->disconnected)
974 _dbus_transport_ref (transport);
975 (* transport->vtable->do_iteration) (transport, flags,
976 timeout_milliseconds);
977 _dbus_transport_unref (transport);
979 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
983 recover_unused_bytes (DBusTransport *transport)
985 if (_dbus_auth_needs_decoding (transport->auth))
987 DBusString plaintext;
988 const DBusString *encoded;
992 if (!_dbus_string_init (&plaintext))
995 _dbus_auth_get_unused_bytes (transport->auth,
998 if (!_dbus_auth_decode_data (transport->auth,
999 encoded, &plaintext))
1001 _dbus_string_free (&plaintext);
1005 _dbus_message_loader_get_buffer (transport->loader,
1008 orig_len = _dbus_string_get_length (buffer);
1010 if (!_dbus_string_move (&plaintext, 0, buffer,
1013 _dbus_string_free (&plaintext);
1017 _dbus_verbose (" %d unused bytes sent to message loader\n",
1018 _dbus_string_get_length (buffer) -
1021 _dbus_message_loader_return_buffer (transport->loader,
1023 _dbus_string_get_length (buffer) -
1026 _dbus_auth_delete_unused_bytes (transport->auth);
1028 _dbus_string_free (&plaintext);
1032 const DBusString *bytes;
1035 dbus_bool_t succeeded;
1037 _dbus_message_loader_get_buffer (transport->loader,
1040 orig_len = _dbus_string_get_length (buffer);
1042 _dbus_auth_get_unused_bytes (transport->auth,
1046 if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
1049 _dbus_verbose (" %d unused bytes sent to message loader\n",
1050 _dbus_string_get_length (buffer) -
1053 _dbus_message_loader_return_buffer (transport->loader,
1055 _dbus_string_get_length (buffer) -
1059 _dbus_auth_delete_unused_bytes (transport->auth);
1067 _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
1072 * Reports our current dispatch status (whether there's buffered
1073 * data to be queued as messages, or not, or we need memory).
1075 * @param transport the transport
1076 * @returns current status
1079 _dbus_transport_get_dispatch_status (DBusTransport *transport)
1081 if (_dbus_counter_get_value (transport->live_messages_size) >= transport->max_live_messages_size)
1082 return DBUS_DISPATCH_COMPLETE; /* complete for now */
1084 if (!_dbus_transport_get_is_authenticated (transport))
1086 if (_dbus_auth_do_work (transport->auth) ==
1087 DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
1088 return DBUS_DISPATCH_NEED_MEMORY;
1089 else if (!_dbus_transport_get_is_authenticated (transport))
1090 return DBUS_DISPATCH_COMPLETE;
1093 if (!transport->unused_bytes_recovered &&
1094 !recover_unused_bytes (transport))
1095 return DBUS_DISPATCH_NEED_MEMORY;
1097 transport->unused_bytes_recovered = TRUE;
1099 if (!_dbus_message_loader_queue_messages (transport->loader))
1100 return DBUS_DISPATCH_NEED_MEMORY;
1102 if (_dbus_message_loader_peek_message (transport->loader) != NULL)
1103 return DBUS_DISPATCH_DATA_REMAINS;
1105 return DBUS_DISPATCH_COMPLETE;
1109 * Processes data we've read while handling a watch, potentially
1110 * converting some of it to messages and queueing those messages on
1113 * @param transport the transport
1114 * @returns #TRUE if we had enough memory to queue all messages
1117 _dbus_transport_queue_messages (DBusTransport *transport)
1119 DBusDispatchStatus status;
1122 _dbus_verbose ("_dbus_transport_queue_messages()\n");
1125 /* Queue any messages */
1126 while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
1128 DBusMessage *message;
1131 link = _dbus_message_loader_pop_message_link (transport->loader);
1132 _dbus_assert (link != NULL);
1134 message = link->data;
1136 _dbus_verbose ("queueing received message %p\n", message);
1138 if (!_dbus_message_add_size_counter (message, transport->live_messages_size))
1140 _dbus_message_loader_putback_message_link (transport->loader,
1142 status = DBUS_DISPATCH_NEED_MEMORY;
1147 /* pass ownership of link and message ref to connection */
1148 _dbus_connection_queue_received_message_link (transport->connection,
1153 if (_dbus_message_loader_get_is_corrupted (transport->loader))
1155 _dbus_verbose ("Corrupted message stream, disconnecting\n");
1156 _dbus_transport_disconnect (transport);
1159 return status != DBUS_DISPATCH_NEED_MEMORY;
1163 * See dbus_connection_set_max_message_size().
1165 * @param transport the transport
1166 * @param size the max size of a single message
1169 _dbus_transport_set_max_message_size (DBusTransport *transport,
1172 _dbus_message_loader_set_max_message_size (transport->loader, size);
1176 * See dbus_connection_get_max_message_size().
1178 * @param transport the transport
1179 * @returns max message size
1182 _dbus_transport_get_max_message_size (DBusTransport *transport)
1184 return _dbus_message_loader_get_max_message_size (transport->loader);
1188 * See dbus_connection_set_max_received_size().
1190 * @param transport the transport
1191 * @param size the max size of all incoming messages
1194 _dbus_transport_set_max_received_size (DBusTransport *transport,
1197 transport->max_live_messages_size = size;
1198 _dbus_counter_set_notify (transport->live_messages_size,
1199 transport->max_live_messages_size,
1200 live_messages_size_notify,
1206 * See dbus_connection_get_max_received_size().
1208 * @param transport the transport
1209 * @returns max bytes for all live messages
1212 _dbus_transport_get_max_received_size (DBusTransport *transport)
1214 return transport->max_live_messages_size;
1218 * See dbus_connection_get_unix_user().
1220 * @param transport the transport
1221 * @param uid return location for the user ID
1222 * @returns #TRUE if uid is filled in with a valid user ID
1225 _dbus_transport_get_unix_user (DBusTransport *transport,
1228 DBusCredentials *auth_identity;
1230 *uid = _DBUS_INT32_MAX; /* better than some root or system user in
1231 * case of bugs in the caller. Caller should
1232 * never use this value on purpose, however.
1235 if (!transport->authenticated)
1238 auth_identity = _dbus_auth_get_identity (transport->auth);
1240 if (_dbus_credentials_include (auth_identity,
1241 DBUS_CREDENTIAL_UNIX_USER_ID))
1243 *uid = _dbus_credentials_get_unix_uid (auth_identity);
1251 * See dbus_connection_get_unix_process_id().
1253 * @param transport the transport
1254 * @param pid return location for the process ID
1255 * @returns #TRUE if uid is filled in with a valid process ID
1258 _dbus_transport_get_unix_process_id (DBusTransport *transport,
1261 DBusCredentials *auth_identity;
1263 *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose,
1264 * but we set it to a safe number, INT_MAX,
1265 * just to root out possible bugs in bad callers.
1268 if (!transport->authenticated)
1271 auth_identity = _dbus_auth_get_identity (transport->auth);
1273 if (_dbus_credentials_include (auth_identity,
1274 DBUS_CREDENTIAL_UNIX_PROCESS_ID))
1276 *pid = _dbus_credentials_get_unix_pid (auth_identity);
1284 * See dbus_connection_get_adt_audit_session_data().
1286 * @param transport the transport
1287 * @param data return location for the ADT audit data
1288 * @param data_size return length of audit data
1289 * @returns #TRUE if audit data is filled in with a valid ucred
1292 _dbus_transport_get_adt_audit_session_data (DBusTransport *transport,
1296 DBusCredentials *auth_identity;
1301 if (!transport->authenticated)
1304 auth_identity = _dbus_auth_get_identity (transport->auth);
1306 if (_dbus_credentials_include (auth_identity,
1307 DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID))
1309 *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity);
1310 *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity);
1318 * See dbus_connection_set_unix_user_function().
1320 * @param transport the transport
1321 * @param function the predicate
1322 * @param data data to pass to the predicate
1323 * @param free_data_function function to free the data
1324 * @param old_data the old user data to be freed
1325 * @param old_free_data_function old free data function to free it with
1328 _dbus_transport_set_unix_user_function (DBusTransport *transport,
1329 DBusAllowUnixUserFunction function,
1331 DBusFreeFunction free_data_function,
1333 DBusFreeFunction *old_free_data_function)
1335 *old_data = transport->unix_user_data;
1336 *old_free_data_function = transport->free_unix_user_data;
1338 transport->unix_user_function = function;
1339 transport->unix_user_data = data;
1340 transport->free_unix_user_data = free_data_function;
1344 * See dbus_connection_get_windows_user().
1346 * @param transport the transport
1347 * @param windows_sid_p return location for the user ID
1348 * @returns #TRUE if user is available; the returned value may still be #NULL if no memory to copy it
1351 _dbus_transport_get_windows_user (DBusTransport *transport,
1352 char **windows_sid_p)
1354 DBusCredentials *auth_identity;
1356 *windows_sid_p = NULL;
1358 if (!transport->authenticated)
1361 auth_identity = _dbus_auth_get_identity (transport->auth);
1363 if (_dbus_credentials_include (auth_identity,
1364 DBUS_CREDENTIAL_WINDOWS_SID))
1366 /* If no memory, we are supposed to return TRUE and set NULL */
1367 *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
1376 * See dbus_connection_set_windows_user_function().
1378 * @param transport the transport
1379 * @param function the predicate
1380 * @param data data to pass to the predicate
1381 * @param free_data_function function to free the data
1382 * @param old_data the old user data to be freed
1383 * @param old_free_data_function old free data function to free it with
1387 _dbus_transport_set_windows_user_function (DBusTransport *transport,
1388 DBusAllowWindowsUserFunction function,
1390 DBusFreeFunction free_data_function,
1392 DBusFreeFunction *old_free_data_function)
1394 *old_data = transport->windows_user_data;
1395 *old_free_data_function = transport->free_windows_user_data;
1397 transport->windows_user_function = function;
1398 transport->windows_user_data = data;
1399 transport->free_windows_user_data = free_data_function;
1403 * Sets the SASL authentication mechanisms supported by this transport.
1405 * @param transport the transport
1406 * @param mechanisms the #NULL-terminated array of mechanisms
1408 * @returns #FALSE if no memory
1411 _dbus_transport_set_auth_mechanisms (DBusTransport *transport,
1412 const char **mechanisms)
1414 return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
1418 * See dbus_connection_set_allow_anonymous()
1420 * @param transport the transport
1421 * @param value #TRUE to allow anonymous connection
1424 _dbus_transport_set_allow_anonymous (DBusTransport *transport,
1427 transport->allow_anonymous = value != FALSE;