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.
5 * Copyright (C) 2013 Samsung Electronics
7 * Licensed under the Academic Free License version 2.1
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <../config.h>
26 #include "dbus-transport-protected.h"
27 #include "dbus-transport-unix.h"
28 #include "dbus-transport-socket.h"
29 #include "dbus-connection-internal.h"
30 #include "dbus-watch.h"
31 #include "dbus-auth.h"
32 #include "dbus-address.h"
33 #include "dbus-credentials.h"
34 #include "dbus-mainloop.h"
35 #include "dbus-message.h"
36 #include "dbus-transport-kdbus.h"
37 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
38 #include "dbus-server-debug-pipe.h"
42 * @defgroup DBusTransport DBusTransport object
43 * @ingroup DBusInternals
44 * @brief "Backend" for a DBusConnection.
46 * Types and functions related to DBusTransport. A transport is an
47 * abstraction that can send and receive data via various kinds of
48 * network connections or other IPC mechanisms.
54 * @typedef DBusTransport
56 * Opaque object representing a way message stream.
57 * DBusTransport abstracts various kinds of actual
58 * transport mechanism, such as different network protocols,
59 * or encryption schemes.
63 live_messages_notify (DBusCounter *counter,
66 DBusTransport *transport = user_data;
68 _dbus_transport_ref (transport);
71 _dbus_verbose ("Size counter value is now %d\n",
72 (int) _dbus_counter_get_size_value (counter));
73 _dbus_verbose ("Unix FD counter value is now %d\n",
74 (int) _dbus_counter_get_unix_fd_value (counter));
77 /* disable or re-enable the read watch for the transport if
80 if (transport->vtable->live_messages_changed)
82 _dbus_connection_lock (transport->connection);
83 (* transport->vtable->live_messages_changed) (transport);
84 _dbus_connection_unlock (transport->connection);
87 _dbus_transport_unref (transport);
91 * Initializes the base class members of DBusTransport. Chained up to
92 * by subclasses in their constructor. The server GUID is the
93 * globally unique ID for the server creating this connection
94 * and will be #NULL for the client side of a connection. The GUID
97 * @param transport the transport being created.
98 * @param vtable the subclass vtable.
99 * @param server_guid non-#NULL if this transport is on the server side of a connection
100 * @param address the address of the transport
101 * @returns #TRUE on success.
104 _dbus_transport_init_base (DBusTransport *transport,
105 const DBusTransportVTable *vtable,
106 const DBusString *server_guid,
107 const DBusString *address)
109 DBusMessageLoader *loader;
111 DBusCounter *counter;
113 DBusCredentials *creds;
115 loader = _dbus_message_loader_new ();
120 auth = _dbus_auth_server_new (server_guid);
123 _dbus_assert (address != NULL);
124 if (!_dbus_string_copy_data (address, &address_copy))
126 _dbus_message_loader_unref (loader);
129 if(address_copy == strstr(address_copy, "kdbus:path="))
130 auth = _dbus_auth_client_new_kdbus();
132 auth = _dbus_auth_client_new ();
137 _dbus_message_loader_unref (loader);
141 counter = _dbus_counter_new ();
144 _dbus_auth_unref (auth);
145 _dbus_message_loader_unref (loader);
149 creds = _dbus_credentials_new ();
152 _dbus_counter_unref (counter);
153 _dbus_auth_unref (auth);
154 _dbus_message_loader_unref (loader);
160 _dbus_assert (address == NULL);
164 transport->refcount = 1;
165 transport->vtable = vtable;
166 transport->loader = loader;
167 transport->auth = auth;
168 transport->live_messages = counter;
169 transport->authenticated = FALSE;
170 transport->disconnected = FALSE;
171 transport->is_server = (server_guid != NULL);
172 transport->send_credentials_pending = !transport->is_server;
173 transport->receive_credentials_pending = transport->is_server;
174 transport->address = address_copy;
176 transport->unix_user_function = NULL;
177 transport->unix_user_data = NULL;
178 transport->free_unix_user_data = NULL;
180 transport->windows_user_function = NULL;
181 transport->windows_user_data = NULL;
182 transport->free_windows_user_data = NULL;
184 transport->expected_guid = NULL;
186 /* Try to default to something that won't totally hose the system,
187 * but doesn't impose too much of a limitation.
189 transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
191 /* On Linux RLIMIT_NOFILE defaults to 1024, so allowing 4096 fds live
192 should be more than enough */
193 transport->max_live_messages_unix_fds = 4096;
195 /* credentials read from socket if any */
196 transport->credentials = creds;
198 _dbus_counter_set_notify (transport->live_messages,
199 transport->max_live_messages_size,
200 transport->max_live_messages_unix_fds,
201 live_messages_notify,
204 if (transport->address)
205 _dbus_verbose ("Initialized transport on address %s\n", transport->address);
211 * Finalizes base class members of DBusTransport.
212 * Chained up to from subclass finalizers.
214 * @param transport the transport.
217 _dbus_transport_finalize_base (DBusTransport *transport)
219 if (!transport->disconnected)
220 _dbus_transport_disconnect (transport);
222 if (transport->free_unix_user_data != NULL)
223 (* transport->free_unix_user_data) (transport->unix_user_data);
225 if (transport->free_windows_user_data != NULL)
226 (* transport->free_windows_user_data) (transport->windows_user_data);
228 _dbus_message_loader_unref (transport->loader);
229 _dbus_auth_unref (transport->auth);
230 _dbus_counter_set_notify (transport->live_messages,
232 _dbus_counter_unref (transport->live_messages);
233 dbus_free (transport->address);
234 dbus_free (transport->expected_guid);
235 if (transport->credentials)
236 _dbus_credentials_unref (transport->credentials);
241 * Verifies if a given D-Bus address is a valid address
242 * by attempting to connect to it. If it is, returns the
243 * opened DBusTransport object. If it isn't, returns #NULL
246 * @param address the address to be checked.
247 * @param error address where an error can be returned.
248 * @returns a new transport, or #NULL on failure.
250 static DBusTransport*
251 check_address (const char *address, DBusError *error)
253 DBusAddressEntry **entries;
254 DBusTransport *transport = NULL;
257 _dbus_assert (address != NULL);
259 if (!dbus_parse_address (address, &entries, &len, error))
260 return NULL; /* not a valid address */
262 for (i = 0; i < len; i++)
264 transport = _dbus_transport_open (entries[i], error);
265 if (transport != NULL)
269 dbus_address_entries_free (entries);
274 * Creates a new transport for the "autostart" method.
275 * This creates a client-side of a transport.
277 * @param scope scope of autolaunch (Windows only)
278 * @param error address where an error can be returned.
279 * @returns a new transport, or #NULL on failure.
281 static DBusTransport*
282 _dbus_transport_new_for_autolaunch (const char *scope, DBusError *error)
285 DBusTransport *result = NULL;
287 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
289 if (!_dbus_string_init (&address))
291 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
295 if (!_dbus_get_autolaunch_address (scope, &address, error))
297 _DBUS_ASSERT_ERROR_IS_SET (error);
301 result = check_address (_dbus_string_get_const_data (&address), error);
303 _DBUS_ASSERT_ERROR_IS_SET (error);
305 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
308 _dbus_string_free (&address);
312 static DBusTransportOpenResult
313 _dbus_transport_open_autolaunch (DBusAddressEntry *entry,
314 DBusTransport **transport_p,
319 method = dbus_address_entry_get_method (entry);
320 _dbus_assert (method != NULL);
322 if (strcmp (method, "autolaunch") == 0)
324 const char *scope = dbus_address_entry_get_value (entry, "scope");
326 *transport_p = _dbus_transport_new_for_autolaunch (scope, error);
328 if (*transport_p == NULL)
330 _DBUS_ASSERT_ERROR_IS_SET (error);
331 return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
335 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
336 return DBUS_TRANSPORT_OPEN_OK;
341 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
342 return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
346 static const struct {
347 DBusTransportOpenResult (* func) (DBusAddressEntry *entry,
348 DBusTransport **transport_p,
351 { _dbus_transport_open_kdbus },
352 { _dbus_transport_open_socket },
353 { _dbus_transport_open_platform_specific },
354 { _dbus_transport_open_autolaunch }
355 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
356 , { _dbus_transport_open_debug_pipe }
361 * Try to open a new transport for the given address entry. (This
362 * opens a client-side-of-the-connection transport.)
364 * @param entry the address entry
365 * @param error location to store reason for failure.
366 * @returns new transport of #NULL on failure.
369 _dbus_transport_open (DBusAddressEntry *entry,
372 DBusTransport *transport;
373 const char *expected_guid_orig;
376 DBusError tmp_error = DBUS_ERROR_INIT;
378 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
381 expected_guid_orig = dbus_address_entry_get_value (entry, "guid");
382 expected_guid = _dbus_strdup (expected_guid_orig);
384 if (expected_guid_orig != NULL && expected_guid == NULL)
386 _DBUS_SET_OOM (error);
390 for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i)
392 DBusTransportOpenResult result;
394 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
395 result = (* open_funcs[i].func) (entry, &transport, &tmp_error);
399 case DBUS_TRANSPORT_OPEN_OK:
400 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
403 case DBUS_TRANSPORT_OPEN_NOT_HANDLED:
404 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
405 /* keep going through the loop of open funcs */
407 case DBUS_TRANSPORT_OPEN_BAD_ADDRESS:
408 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
411 case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT:
412 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
420 if (transport == NULL)
422 if (!dbus_error_is_set (&tmp_error))
423 _dbus_set_bad_address (&tmp_error,
425 "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")");
427 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
428 dbus_move_error(&tmp_error, error);
429 dbus_free (expected_guid);
433 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
435 /* In the case of autostart the initial guid is NULL
436 * and the autostart transport recursively calls
437 * _dbus_open_transport wich returns a transport
438 * with a guid. That guid is the definitive one.
440 * FIXME: if more transports are added they may have
441 * an effect on the expected_guid semantics (i.e.
442 * expected_guid and transport->expected_guid may
443 * both have values). This is very unlikely though
444 * we should either throw asserts here for those
445 * corner cases or refactor the code so it is
446 * clearer on what is expected and what is not
449 transport->expected_guid = expected_guid;
456 * Increments the reference count for the transport.
458 * @param transport the transport.
459 * @returns the transport.
462 _dbus_transport_ref (DBusTransport *transport)
464 _dbus_assert (transport->refcount > 0);
466 transport->refcount += 1;
472 * Decrements the reference count for the transport.
473 * Disconnects and finalizes the transport if
474 * the reference count reaches zero.
476 * @param transport the transport.
479 _dbus_transport_unref (DBusTransport *transport)
481 _dbus_assert (transport != NULL);
482 _dbus_assert (transport->refcount > 0);
484 transport->refcount -= 1;
485 if (transport->refcount == 0)
487 _dbus_verbose ("finalizing\n");
489 _dbus_assert (transport->vtable->finalize != NULL);
491 (* transport->vtable->finalize) (transport);
496 * Closes our end of the connection to a remote application. Further
497 * attempts to use this transport will fail. Only the first call to
498 * _dbus_transport_disconnect() will have an effect.
500 * @param transport the transport.
504 _dbus_transport_disconnect (DBusTransport *transport)
506 _dbus_verbose ("start\n");
508 _dbus_assert (transport->vtable->disconnect != NULL);
510 if (transport->disconnected)
513 (* transport->vtable->disconnect) (transport);
515 transport->disconnected = TRUE;
517 _dbus_verbose ("end\n");
521 * Returns #TRUE if the transport has not been disconnected.
522 * Disconnection can result from _dbus_transport_disconnect()
523 * or because the server drops its end of the connection.
525 * @param transport the transport.
526 * @returns whether we're connected
529 _dbus_transport_get_is_connected (DBusTransport *transport)
531 return !transport->disconnected;
535 auth_via_unix_user_function (DBusTransport *transport)
537 DBusCredentials *auth_identity;
539 DBusConnection *connection;
540 DBusAllowUnixUserFunction unix_user_function;
541 void *unix_user_data;
544 /* Dropping the lock here probably isn't that safe. */
546 auth_identity = _dbus_auth_get_identity (transport->auth);
547 _dbus_assert (auth_identity != NULL);
549 connection = transport->connection;
550 unix_user_function = transport->unix_user_function;
551 unix_user_data = transport->unix_user_data;
552 uid = _dbus_credentials_get_unix_uid (auth_identity);
554 _dbus_verbose ("unlock\n");
555 _dbus_connection_unlock (connection);
557 allow = (* unix_user_function) (connection,
561 _dbus_verbose ("lock post unix user function\n");
562 _dbus_connection_lock (connection);
566 _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid);
570 _dbus_verbose ("Client UID "DBUS_UID_FORMAT
571 " was rejected, disconnecting\n",
572 _dbus_credentials_get_unix_uid (auth_identity));
573 _dbus_transport_disconnect (transport);
580 auth_via_windows_user_function (DBusTransport *transport)
582 DBusCredentials *auth_identity;
584 DBusConnection *connection;
585 DBusAllowWindowsUserFunction windows_user_function;
586 void *windows_user_data;
589 /* Dropping the lock here probably isn't that safe. */
591 auth_identity = _dbus_auth_get_identity (transport->auth);
592 _dbus_assert (auth_identity != NULL);
594 connection = transport->connection;
595 windows_user_function = transport->windows_user_function;
596 windows_user_data = transport->unix_user_data;
597 windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
599 if (windows_sid == NULL)
605 _dbus_verbose ("unlock\n");
606 _dbus_connection_unlock (connection);
608 allow = (* windows_user_function) (connection,
612 _dbus_verbose ("lock post windows user function\n");
613 _dbus_connection_lock (connection);
617 _dbus_verbose ("Client SID '%s' authorized\n", windows_sid);
621 _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n",
622 _dbus_credentials_get_windows_sid (auth_identity));
623 _dbus_transport_disconnect (transport);
630 auth_via_default_rules (DBusTransport *transport)
632 DBusCredentials *auth_identity;
633 DBusCredentials *our_identity;
636 auth_identity = _dbus_auth_get_identity (transport->auth);
637 _dbus_assert (auth_identity != NULL);
639 /* By default, connection is allowed if the client is 1) root or 2)
640 * has the same UID as us or 3) anonymous is allowed.
643 our_identity = _dbus_credentials_new_from_current_process ();
644 if (our_identity == NULL)
650 if (transport->allow_anonymous ||
651 _dbus_credentials_get_unix_uid (auth_identity) == 0 ||
652 _dbus_credentials_same_user (our_identity,
655 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
656 _dbus_verbose ("Client authorized as SID '%s'"
657 "matching our SID '%s'\n",
658 _dbus_credentials_get_windows_sid(auth_identity),
659 _dbus_credentials_get_windows_sid(our_identity));
661 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
662 " matching our UID "DBUS_UID_FORMAT"\n",
663 _dbus_credentials_get_unix_uid(auth_identity),
664 _dbus_credentials_get_unix_uid(our_identity));
665 /* We have authenticated! */
670 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
671 _dbus_verbose ("Client authorized as SID '%s'"
672 " but our SID is '%s', disconnecting\n",
673 (_dbus_credentials_get_windows_sid(auth_identity) ?
674 _dbus_credentials_get_windows_sid(auth_identity) : "<null>"),
675 (_dbus_credentials_get_windows_sid(our_identity) ?
676 _dbus_credentials_get_windows_sid(our_identity) : "<null>"));
678 _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
679 " but our UID is "DBUS_UID_FORMAT", disconnecting\n",
680 _dbus_credentials_get_unix_uid(auth_identity),
681 _dbus_credentials_get_unix_uid(our_identity));
682 _dbus_transport_disconnect (transport);
686 _dbus_credentials_unref (our_identity);
692 * Returns #TRUE if we have been authenticated. It will return #TRUE even if
693 * the transport is now disconnected, but was ever authenticated before
696 * This replaces the older _dbus_transport_get_is_authenticated() which
699 * @param transport the transport
700 * @returns whether we're authenticated
703 _dbus_transport_peek_is_authenticated (DBusTransport *transport)
705 return transport->authenticated;
709 * Returns #TRUE if we have been authenticated. It will return #TRUE even if
710 * the transport is now disconnected, but was ever authenticated before
713 * If we have not finished authenticating, but we have enough buffered input
714 * to finish the job, then this function will do so before it returns.
716 * This used to be called _dbus_transport_get_is_authenticated(), but that
717 * name seems inappropriate for a function with side-effects.
719 * @todo we drop connection->mutex when calling the unix_user_function,
720 * and windows_user_function, which may not be safe really.
722 * @param transport the transport
723 * @returns whether we're authenticated
726 _dbus_transport_try_to_authenticate (DBusTransport *transport)
728 if (transport->authenticated)
732 dbus_bool_t maybe_authenticated;
734 if (transport->disconnected)
737 /* paranoia ref since we call user callbacks sometimes */
738 _dbus_connection_ref_unlocked (transport->connection);
740 maybe_authenticated =
741 (!(transport->send_credentials_pending ||
742 transport->receive_credentials_pending));
744 if (maybe_authenticated)
746 switch (_dbus_auth_do_work (transport->auth))
748 case DBUS_AUTH_STATE_AUTHENTICATED:
749 /* leave as maybe_authenticated */
752 maybe_authenticated = FALSE;
756 /* If we're the client, verify the GUID
758 if (maybe_authenticated && !transport->is_server)
760 const char *server_guid;
762 server_guid = _dbus_auth_get_guid_from_server (transport->auth);
763 _dbus_assert (server_guid != NULL);
765 if (transport->expected_guid &&
766 strcmp (transport->expected_guid, server_guid) != 0)
768 _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n",
769 transport->expected_guid, server_guid);
770 _dbus_transport_disconnect (transport);
771 _dbus_connection_unref_unlocked (transport->connection);
776 /* If we're the server, see if we want to allow this identity to proceed.
778 if (maybe_authenticated && transport->is_server)
781 DBusCredentials *auth_identity;
783 auth_identity = _dbus_auth_get_identity (transport->auth);
784 _dbus_assert (auth_identity != NULL);
786 /* If we have an auth'd user and a user function, delegate
787 * deciding whether auth credentials are good enough to the
788 * app; otherwise, use our default decision process.
790 if (transport->unix_user_function != NULL &&
791 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID))
793 allow = auth_via_unix_user_function (transport);
795 else if (transport->windows_user_function != NULL &&
796 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID))
798 allow = auth_via_windows_user_function (transport);
802 allow = auth_via_default_rules (transport);
806 maybe_authenticated = FALSE;
809 transport->authenticated = maybe_authenticated;
811 _dbus_connection_unref_unlocked (transport->connection);
812 return maybe_authenticated;
817 * See dbus_connection_get_is_anonymous().
819 * @param transport the transport
820 * @returns #TRUE if not authenticated or authenticated as anonymous
823 _dbus_transport_get_is_anonymous (DBusTransport *transport)
825 DBusCredentials *auth_identity;
827 if (!transport->authenticated)
830 auth_identity = _dbus_auth_get_identity (transport->auth);
832 if (_dbus_credentials_are_anonymous (auth_identity))
839 * Returns TRUE if the transport supports sending unix fds.
841 * @param transport the transport
842 * @returns #TRUE if TRUE it is possible to send unix fds across the transport.
845 _dbus_transport_can_pass_unix_fd(DBusTransport *transport)
847 return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport);
851 * Gets the address of a transport. It will be
852 * #NULL for a server-side transport.
854 * @param transport the transport
855 * @returns transport's address
858 _dbus_transport_get_address (DBusTransport *transport)
860 return transport->address;
864 * Gets the id of the server we are connected to (see
865 * dbus_server_get_id()). Only works on client side.
867 * @param transport the transport
868 * @returns transport's server's id or #NULL if we are the server side
871 _dbus_transport_get_server_id (DBusTransport *transport)
873 if (transport->is_server)
875 else if (transport->authenticated)
876 return _dbus_auth_get_guid_from_server (transport->auth);
878 return transport->expected_guid;
882 * Handles a watch by reading data, writing data, or disconnecting
883 * the transport, as appropriate for the given condition.
885 * @param transport the transport.
886 * @param watch the watch.
887 * @param condition the current state of the watched file descriptor.
888 * @returns #FALSE if not enough memory to fully handle the watch
891 _dbus_transport_handle_watch (DBusTransport *transport,
893 unsigned int condition)
897 _dbus_assert (transport->vtable->handle_watch != NULL);
899 if (transport->disconnected)
902 if (dbus_watch_get_socket (watch) < 0)
904 _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n");
908 _dbus_watch_sanitize_condition (watch, &condition);
910 _dbus_transport_ref (transport);
911 _dbus_watch_ref (watch);
912 retval = (* transport->vtable->handle_watch) (transport, watch, condition);
913 _dbus_watch_unref (watch);
914 _dbus_transport_unref (transport);
920 * Sets the connection using this transport. Allows the transport
921 * to add watches to the connection, queue incoming messages,
922 * and pull outgoing messages.
924 * @param transport the transport.
925 * @param connection the connection.
926 * @returns #FALSE if not enough memory
929 _dbus_transport_set_connection (DBusTransport *transport,
930 DBusConnection *connection)
932 _dbus_assert (transport->vtable->connection_set != NULL);
933 _dbus_assert (transport->connection == NULL);
935 transport->connection = connection;
937 _dbus_transport_ref (transport);
938 if (!(* transport->vtable->connection_set) (transport))
939 transport->connection = NULL;
940 _dbus_transport_unref (transport);
942 return transport->connection != NULL;
946 * Get the socket file descriptor, if any.
948 * @param transport the transport
949 * @param fd_p pointer to fill in with the descriptor
950 * @returns #TRUE if a descriptor was available
953 _dbus_transport_get_socket_fd (DBusTransport *transport,
958 if (transport->vtable->get_socket_fd == NULL)
961 if (transport->disconnected)
964 _dbus_transport_ref (transport);
966 retval = (* transport->vtable->get_socket_fd) (transport,
969 _dbus_transport_unref (transport);
975 * Performs a single poll()/select() on the transport's file
976 * descriptors and then reads/writes data as appropriate,
977 * queueing incoming messages and sending outgoing messages.
978 * This is the backend for _dbus_connection_do_iteration().
979 * See _dbus_connection_do_iteration() for full details.
981 * @param transport the transport.
982 * @param flags indicates whether to read or write, and whether to block.
983 * @param timeout_milliseconds if blocking, timeout or -1 for no timeout.
986 _dbus_transport_do_iteration (DBusTransport *transport,
988 int timeout_milliseconds)
990 _dbus_assert (transport->vtable->do_iteration != NULL);
992 _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
993 flags, timeout_milliseconds, !transport->disconnected);
995 if ((flags & (DBUS_ITERATION_DO_WRITING |
996 DBUS_ITERATION_DO_READING)) == 0)
997 return; /* Nothing to do */
999 if (transport->disconnected)
1002 _dbus_transport_ref (transport);
1003 (* transport->vtable->do_iteration) (transport, flags,
1004 timeout_milliseconds);
1005 _dbus_transport_unref (transport);
1007 _dbus_verbose ("end\n");
1011 recover_unused_bytes (DBusTransport *transport)
1013 if (_dbus_auth_needs_decoding (transport->auth))
1015 DBusString plaintext;
1016 const DBusString *encoded;
1020 if (!_dbus_string_init (&plaintext))
1023 _dbus_auth_get_unused_bytes (transport->auth,
1026 if (!_dbus_auth_decode_data (transport->auth,
1027 encoded, &plaintext))
1029 _dbus_string_free (&plaintext);
1033 _dbus_message_loader_get_buffer (transport->loader,
1036 orig_len = _dbus_string_get_length (buffer);
1038 if (!_dbus_string_move (&plaintext, 0, buffer,
1041 _dbus_string_free (&plaintext);
1045 _dbus_verbose (" %d unused bytes sent to message loader\n",
1046 _dbus_string_get_length (buffer) -
1049 _dbus_message_loader_return_buffer (transport->loader,
1051 _dbus_string_get_length (buffer) -
1054 _dbus_auth_delete_unused_bytes (transport->auth);
1056 _dbus_string_free (&plaintext);
1060 const DBusString *bytes;
1063 dbus_bool_t succeeded;
1065 _dbus_message_loader_get_buffer (transport->loader,
1068 orig_len = _dbus_string_get_length (buffer);
1070 _dbus_auth_get_unused_bytes (transport->auth,
1074 if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
1077 _dbus_verbose (" %d unused bytes sent to message loader\n",
1078 _dbus_string_get_length (buffer) -
1081 _dbus_message_loader_return_buffer (transport->loader,
1083 _dbus_string_get_length (buffer) -
1087 _dbus_auth_delete_unused_bytes (transport->auth);
1095 _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
1100 * Reports our current dispatch status (whether there's buffered
1101 * data to be queued as messages, or not, or we need memory).
1103 * @param transport the transport
1104 * @returns current status
1107 _dbus_transport_get_dispatch_status (DBusTransport *transport)
1109 if (_dbus_counter_get_size_value (transport->live_messages) >= transport->max_live_messages_size ||
1110 _dbus_counter_get_unix_fd_value (transport->live_messages) >= transport->max_live_messages_unix_fds)
1111 return DBUS_DISPATCH_COMPLETE; /* complete for now */
1113 if (!_dbus_transport_try_to_authenticate (transport))
1115 if (_dbus_auth_do_work (transport->auth) ==
1116 DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
1117 return DBUS_DISPATCH_NEED_MEMORY;
1118 else if (!_dbus_transport_try_to_authenticate (transport))
1119 return DBUS_DISPATCH_COMPLETE;
1122 if (!transport->unused_bytes_recovered &&
1123 !recover_unused_bytes (transport))
1124 return DBUS_DISPATCH_NEED_MEMORY;
1126 transport->unused_bytes_recovered = TRUE;
1128 if (!_dbus_message_loader_queue_messages (transport->loader))
1129 return DBUS_DISPATCH_NEED_MEMORY;
1131 if (_dbus_message_loader_peek_message (transport->loader) != NULL)
1132 return DBUS_DISPATCH_DATA_REMAINS;
1134 return DBUS_DISPATCH_COMPLETE;
1138 * Processes data we've read while handling a watch, potentially
1139 * converting some of it to messages and queueing those messages on
1142 * @param transport the transport
1143 * @returns #TRUE if we had enough memory to queue all messages
1146 _dbus_transport_queue_messages (DBusTransport *transport)
1148 DBusDispatchStatus status;
1151 _dbus_verbose ("_dbus_transport_queue_messages()\n");
1154 /* Queue any messages */
1155 while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
1157 DBusMessage *message;
1160 link = _dbus_message_loader_pop_message_link (transport->loader);
1161 _dbus_assert (link != NULL);
1163 message = link->data;
1165 _dbus_verbose ("queueing received message %p\n", message);
1167 if (!_dbus_message_add_counter (message, transport->live_messages))
1169 _dbus_message_loader_putback_message_link (transport->loader,
1171 status = DBUS_DISPATCH_NEED_MEMORY;
1176 /* We didn't call the notify function when we added the counter, so
1177 * catch up now. Since we have the connection's lock, it's desirable
1178 * that we bypass the notify function and call this virtual method
1180 if (transport->vtable->live_messages_changed)
1181 (* transport->vtable->live_messages_changed) (transport);
1183 /* pass ownership of link and message ref to connection */
1184 _dbus_connection_queue_received_message_link (transport->connection,
1189 if (_dbus_message_loader_get_is_corrupted (transport->loader))
1191 _dbus_verbose ("Corrupted message stream, disconnecting\n");
1192 _dbus_transport_disconnect (transport);
1195 return status != DBUS_DISPATCH_NEED_MEMORY;
1199 * See dbus_connection_set_max_message_size().
1201 * @param transport the transport
1202 * @param size the max size of a single message
1205 _dbus_transport_set_max_message_size (DBusTransport *transport,
1208 _dbus_message_loader_set_max_message_size (transport->loader, size);
1212 * See dbus_connection_set_max_message_unix_fds().
1214 * @param transport the transport
1215 * @param n the max number of unix fds of a single message
1218 _dbus_transport_set_max_message_unix_fds (DBusTransport *transport,
1221 _dbus_message_loader_set_max_message_unix_fds (transport->loader, n);
1225 * See dbus_connection_get_max_message_size().
1227 * @param transport the transport
1228 * @returns max message size
1231 _dbus_transport_get_max_message_size (DBusTransport *transport)
1233 return _dbus_message_loader_get_max_message_size (transport->loader);
1237 * See dbus_connection_get_max_message_unix_fds().
1239 * @param transport the transport
1240 * @returns max message unix fds
1243 _dbus_transport_get_max_message_unix_fds (DBusTransport *transport)
1245 return _dbus_message_loader_get_max_message_unix_fds (transport->loader);
1249 * See dbus_connection_set_max_received_size().
1251 * @param transport the transport
1252 * @param size the max size of all incoming messages
1255 _dbus_transport_set_max_received_size (DBusTransport *transport,
1258 transport->max_live_messages_size = size;
1259 _dbus_counter_set_notify (transport->live_messages,
1260 transport->max_live_messages_size,
1261 transport->max_live_messages_unix_fds,
1262 live_messages_notify,
1267 * See dbus_connection_set_max_received_unix_fds().
1269 * @param transport the transport
1270 * @param n the max unix fds of all incoming messages
1273 _dbus_transport_set_max_received_unix_fds (DBusTransport *transport,
1276 transport->max_live_messages_unix_fds = n;
1277 _dbus_counter_set_notify (transport->live_messages,
1278 transport->max_live_messages_size,
1279 transport->max_live_messages_unix_fds,
1280 live_messages_notify,
1285 * See dbus_connection_get_max_received_size().
1287 * @param transport the transport
1288 * @returns max bytes for all live messages
1291 _dbus_transport_get_max_received_size (DBusTransport *transport)
1293 return transport->max_live_messages_size;
1297 * See dbus_connection_set_max_received_unix_fds().
1299 * @param transport the transport
1300 * @returns max unix fds for all live messages
1303 _dbus_transport_get_max_received_unix_fds (DBusTransport *transport)
1305 return transport->max_live_messages_unix_fds;
1309 * See dbus_connection_get_unix_user().
1311 * @param transport the transport
1312 * @param uid return location for the user ID
1313 * @returns #TRUE if uid is filled in with a valid user ID
1316 _dbus_transport_get_unix_user (DBusTransport *transport,
1319 DBusCredentials *auth_identity;
1321 *uid = _DBUS_INT32_MAX; /* better than some root or system user in
1322 * case of bugs in the caller. Caller should
1323 * never use this value on purpose, however.
1326 if (!transport->authenticated)
1329 auth_identity = _dbus_auth_get_identity (transport->auth);
1331 if (_dbus_credentials_include (auth_identity,
1332 DBUS_CREDENTIAL_UNIX_USER_ID))
1334 *uid = _dbus_credentials_get_unix_uid (auth_identity);
1342 * See dbus_connection_get_unix_process_id().
1344 * @param transport the transport
1345 * @param pid return location for the process ID
1346 * @returns #TRUE if uid is filled in with a valid process ID
1349 _dbus_transport_get_unix_process_id (DBusTransport *transport,
1352 DBusCredentials *auth_identity;
1354 *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose,
1355 * but we set it to a safe number, INT_MAX,
1356 * just to root out possible bugs in bad callers.
1359 if (!transport->authenticated)
1362 auth_identity = _dbus_auth_get_identity (transport->auth);
1364 if (_dbus_credentials_include (auth_identity,
1365 DBUS_CREDENTIAL_UNIX_PROCESS_ID))
1367 *pid = _dbus_credentials_get_pid (auth_identity);
1375 * See dbus_connection_get_adt_audit_session_data().
1377 * @param transport the transport
1378 * @param data return location for the ADT audit data
1379 * @param data_size return length of audit data
1380 * @returns #TRUE if audit data is filled in with a valid ucred
1383 _dbus_transport_get_adt_audit_session_data (DBusTransport *transport,
1387 DBusCredentials *auth_identity;
1392 if (!transport->authenticated)
1395 auth_identity = _dbus_auth_get_identity (transport->auth);
1397 if (_dbus_credentials_include (auth_identity,
1398 DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID))
1400 *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity);
1401 *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity);
1409 * See dbus_connection_set_unix_user_function().
1411 * @param transport the transport
1412 * @param function the predicate
1413 * @param data data to pass to the predicate
1414 * @param free_data_function function to free the data
1415 * @param old_data the old user data to be freed
1416 * @param old_free_data_function old free data function to free it with
1419 _dbus_transport_set_unix_user_function (DBusTransport *transport,
1420 DBusAllowUnixUserFunction function,
1422 DBusFreeFunction free_data_function,
1424 DBusFreeFunction *old_free_data_function)
1426 *old_data = transport->unix_user_data;
1427 *old_free_data_function = transport->free_unix_user_data;
1429 transport->unix_user_function = function;
1430 transport->unix_user_data = data;
1431 transport->free_unix_user_data = free_data_function;
1435 * See dbus_connection_get_windows_user().
1437 * @param transport the transport
1438 * @param windows_sid_p return location for the user ID
1439 * @returns #TRUE if user is available; the returned value may still be #NULL if no memory to copy it
1442 _dbus_transport_get_windows_user (DBusTransport *transport,
1443 char **windows_sid_p)
1445 DBusCredentials *auth_identity;
1447 *windows_sid_p = NULL;
1449 if (!transport->authenticated)
1452 auth_identity = _dbus_auth_get_identity (transport->auth);
1454 if (_dbus_credentials_include (auth_identity,
1455 DBUS_CREDENTIAL_WINDOWS_SID))
1457 /* If no memory, we are supposed to return TRUE and set NULL */
1458 *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
1467 * See dbus_connection_set_windows_user_function().
1469 * @param transport the transport
1470 * @param function the predicate
1471 * @param data data to pass to the predicate
1472 * @param free_data_function function to free the data
1473 * @param old_data the old user data to be freed
1474 * @param old_free_data_function old free data function to free it with
1478 _dbus_transport_set_windows_user_function (DBusTransport *transport,
1479 DBusAllowWindowsUserFunction function,
1481 DBusFreeFunction free_data_function,
1483 DBusFreeFunction *old_free_data_function)
1485 *old_data = transport->windows_user_data;
1486 *old_free_data_function = transport->free_windows_user_data;
1488 transport->windows_user_function = function;
1489 transport->windows_user_data = data;
1490 transport->free_windows_user_data = free_data_function;
1494 * Sets the SASL authentication mechanisms supported by this transport.
1496 * @param transport the transport
1497 * @param mechanisms the #NULL-terminated array of mechanisms
1499 * @returns #FALSE if no memory
1502 _dbus_transport_set_auth_mechanisms (DBusTransport *transport,
1503 const char **mechanisms)
1505 return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
1509 * See dbus_connection_set_allow_anonymous()
1511 * @param transport the transport
1512 * @param value #TRUE to allow anonymous connection
1515 _dbus_transport_set_allow_anonymous (DBusTransport *transport,
1518 transport->allow_anonymous = value != FALSE;
1521 #ifdef DBUS_ENABLE_STATS
1523 _dbus_transport_get_stats (DBusTransport *transport,
1524 dbus_uint32_t *queue_bytes,
1525 dbus_uint32_t *queue_fds,
1526 dbus_uint32_t *peak_queue_bytes,
1527 dbus_uint32_t *peak_queue_fds)
1529 if (queue_bytes != NULL)
1530 *queue_bytes = _dbus_counter_get_size_value (transport->live_messages);
1532 if (queue_fds != NULL)
1533 *queue_fds = _dbus_counter_get_unix_fd_value (transport->live_messages);
1535 if (peak_queue_bytes != NULL)
1536 *peak_queue_bytes = _dbus_counter_get_peak_size_value (transport->live_messages);
1538 if (peak_queue_fds != NULL)
1539 *peak_queue_fds = _dbus_counter_get_peak_unix_fd_value (transport->live_messages);
1541 #endif /* DBUS_ENABLE_STATS */