Merge branch 'dbus-1.10'
[platform/upstream/dbus.git] / dbus / dbus-transport.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-transport.c DBusTransport object (internal to D-Bus implementation)
3  *
4  * Copyright (C) 2002, 2003  Red Hat Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  * 
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.
12  *
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.
17  * 
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #include <config.h>
25 #include "dbus-transport-protected.h"
26 #include "dbus-transport-unix.h"
27 #include "dbus-transport-socket.h"
28 #include "dbus-connection-internal.h"
29 #include "dbus-watch.h"
30 #include "dbus-auth.h"
31 #include "dbus-address.h"
32 #include "dbus-credentials.h"
33 #include "dbus-mainloop.h"
34 #include "dbus-message.h"
35 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
36 #include "dbus-server-debug-pipe.h"
37 #endif
38
39 /**
40  * @defgroup DBusTransport DBusTransport object
41  * @ingroup  DBusInternals
42  * @brief "Backend" for a DBusConnection.
43  *
44  * Types and functions related to DBusTransport.  A transport is an
45  * abstraction that can send and receive data via various kinds of
46  * network connections or other IPC mechanisms.
47  * 
48  * @{
49  */
50
51 /**
52  * @typedef DBusTransport
53  *
54  * Opaque object representing a way message stream.
55  * DBusTransport abstracts various kinds of actual
56  * transport mechanism, such as different network protocols,
57  * or encryption schemes.
58  */
59
60 static void
61 live_messages_notify (DBusCounter *counter,
62                            void        *user_data)
63 {
64   DBusTransport *transport = user_data;
65
66   _dbus_connection_lock (transport->connection);
67   _dbus_transport_ref (transport);
68
69 #if 0
70   _dbus_verbose ("Size counter value is now %d\n",
71                  (int) _dbus_counter_get_size_value (counter));
72   _dbus_verbose ("Unix FD counter value is now %d\n",
73                  (int) _dbus_counter_get_unix_fd_value (counter));
74 #endif
75
76   /* disable or re-enable the read watch for the transport if
77    * required.
78    */
79   if (transport->vtable->live_messages_changed)
80     {
81       (* transport->vtable->live_messages_changed) (transport);
82     }
83
84   _dbus_transport_unref (transport);
85   _dbus_connection_unlock (transport->connection);
86 }
87
88 /**
89  * Initializes the base class members of DBusTransport.  Chained up to
90  * by subclasses in their constructor.  The server GUID is the
91  * globally unique ID for the server creating this connection
92  * and will be #NULL for the client side of a connection. The GUID
93  * is in hex format.
94  *
95  * @param transport the transport being created.
96  * @param vtable the subclass vtable.
97  * @param server_guid non-#NULL if this transport is on the server side of a connection
98  * @param address the address of the transport
99  * @returns #TRUE on success.
100  */
101 dbus_bool_t
102 _dbus_transport_init_base (DBusTransport             *transport,
103                            const DBusTransportVTable *vtable,
104                            const DBusString          *server_guid,
105                            const DBusString          *address)
106 {
107   DBusMessageLoader *loader;
108   DBusAuth *auth;
109   DBusCounter *counter;
110   char *address_copy;
111   DBusCredentials *creds;
112   
113   loader = _dbus_message_loader_new ();
114   if (loader == NULL)
115     return FALSE;
116   
117   if (server_guid)
118     auth = _dbus_auth_server_new (server_guid);
119   else
120     auth = _dbus_auth_client_new ();
121   if (auth == NULL)
122     {
123       _dbus_message_loader_unref (loader);
124       return FALSE;
125     }
126
127   counter = _dbus_counter_new ();
128   if (counter == NULL)
129     {
130       _dbus_auth_unref (auth);
131       _dbus_message_loader_unref (loader);
132       return FALSE;
133     }  
134
135   creds = _dbus_credentials_new ();
136   if (creds == NULL)
137     {
138       _dbus_counter_unref (counter);
139       _dbus_auth_unref (auth);
140       _dbus_message_loader_unref (loader);
141       return FALSE;
142     }
143   
144   if (server_guid)
145     {
146       _dbus_assert (address == NULL);
147       address_copy = NULL;
148     }
149   else
150     {
151       _dbus_assert (address != NULL);
152
153       if (!_dbus_string_copy_data (address, &address_copy))
154         {
155           _dbus_credentials_unref (creds);
156           _dbus_counter_unref (counter);
157           _dbus_auth_unref (auth);
158           _dbus_message_loader_unref (loader);
159           return FALSE;
160         }
161     }
162   
163   transport->refcount = 1;
164   transport->vtable = vtable;
165   transport->loader = loader;
166   transport->auth = auth;
167   transport->live_messages = counter;
168   transport->authenticated = FALSE;
169   transport->disconnected = FALSE;
170   transport->is_server = (server_guid != NULL);
171   transport->send_credentials_pending = !transport->is_server;
172   transport->receive_credentials_pending = transport->is_server;
173   transport->address = address_copy;
174   
175   transport->unix_user_function = NULL;
176   transport->unix_user_data = NULL;
177   transport->free_unix_user_data = NULL;
178
179   transport->windows_user_function = NULL;
180   transport->windows_user_data = NULL;
181   transport->free_windows_user_data = NULL;
182   
183   transport->expected_guid = NULL;
184   
185   /* Try to default to something that won't totally hose the system,
186    * but doesn't impose too much of a limitation.
187    */
188   transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
189
190   /* On Linux RLIMIT_NOFILE defaults to 1024, so allowing 4096 fds live
191      should be more than enough */
192   transport->max_live_messages_unix_fds = 4096;
193
194   /* credentials read from socket if any */
195   transport->credentials = creds;
196
197   _dbus_counter_set_notify (transport->live_messages,
198                             transport->max_live_messages_size,
199                             transport->max_live_messages_unix_fds,
200                             live_messages_notify,
201                             transport);
202
203   if (transport->address)
204     _dbus_verbose ("Initialized transport on address %s\n", transport->address);
205
206   return TRUE;
207 }
208
209 /**
210  * Finalizes base class members of DBusTransport.
211  * Chained up to from subclass finalizers.
212  *
213  * @param transport the transport.
214  */
215 void
216 _dbus_transport_finalize_base (DBusTransport *transport)
217 {
218   if (!transport->disconnected)
219     _dbus_transport_disconnect (transport);
220
221   if (transport->free_unix_user_data != NULL)
222     (* transport->free_unix_user_data) (transport->unix_user_data);
223
224   if (transport->free_windows_user_data != NULL)
225     (* transport->free_windows_user_data) (transport->windows_user_data);
226   
227   _dbus_message_loader_unref (transport->loader);
228   _dbus_auth_unref (transport->auth);
229   _dbus_counter_set_notify (transport->live_messages,
230                             0, 0, NULL, NULL);
231   _dbus_counter_unref (transport->live_messages);
232   dbus_free (transport->address);
233   dbus_free (transport->expected_guid);
234   if (transport->credentials)
235     _dbus_credentials_unref (transport->credentials);
236 }
237
238
239 /**
240  * Verifies if a given D-Bus address is a valid address
241  * by attempting to connect to it. If it is, returns the
242  * opened DBusTransport object. If it isn't, returns #NULL
243  * and sets @p error.
244  *
245  * @param address the address to be checked.
246  * @param error address where an error can be returned.
247  * @returns a new transport, or #NULL on failure.
248  */
249 static DBusTransport*
250 check_address (const char *address, DBusError *error)
251 {
252   DBusAddressEntry **entries;
253   DBusTransport *transport = NULL;
254   int len, i;
255
256   _dbus_assert (address != NULL);
257
258   if (!dbus_parse_address (address, &entries, &len, error))
259     return NULL;              /* not a valid address */
260
261   for (i = 0; i < len; i++)
262     {
263       transport = _dbus_transport_open (entries[i], error);
264       if (transport != NULL)
265         break;
266     }
267
268   dbus_address_entries_free (entries);
269   return transport;
270 }
271
272 /**
273  * Creates a new transport for the "autostart" method.
274  * This creates a client-side of a transport.
275  *
276  * @param scope scope of autolaunch (Windows only)
277  * @param error address where an error can be returned.
278  * @returns a new transport, or #NULL on failure.
279  */
280 static DBusTransport*
281 _dbus_transport_new_for_autolaunch (const char *scope, DBusError *error)
282 {
283   DBusString address;
284   DBusTransport *result = NULL;
285
286   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
287
288   if (!_dbus_string_init (&address))
289     {
290       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
291       return NULL;
292     }
293
294   if (!_dbus_get_autolaunch_address (scope, &address, error))
295     {
296       _DBUS_ASSERT_ERROR_IS_SET (error);
297       goto out;
298     }
299
300   result = check_address (_dbus_string_get_const_data (&address), error);
301   if (result == NULL)
302     _DBUS_ASSERT_ERROR_IS_SET (error);
303   else
304     _DBUS_ASSERT_ERROR_IS_CLEAR (error);
305
306  out:
307   _dbus_string_free (&address);
308   return result;
309 }
310
311 static DBusTransportOpenResult
312 _dbus_transport_open_autolaunch (DBusAddressEntry  *entry,
313                                  DBusTransport    **transport_p,
314                                  DBusError         *error)
315 {
316   const char *method;
317   
318   method = dbus_address_entry_get_method (entry);
319   _dbus_assert (method != NULL);
320
321   if (strcmp (method, "autolaunch") == 0)
322     {
323       const char *scope = dbus_address_entry_get_value (entry, "scope");
324
325       *transport_p = _dbus_transport_new_for_autolaunch (scope, error);
326
327       if (*transport_p == NULL)
328         {
329           _DBUS_ASSERT_ERROR_IS_SET (error);
330           return DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT;
331         }
332       else
333         {
334           _DBUS_ASSERT_ERROR_IS_CLEAR (error);
335           return DBUS_TRANSPORT_OPEN_OK;
336         }      
337     }
338   else
339     {
340       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
341       return DBUS_TRANSPORT_OPEN_NOT_HANDLED;
342     }
343 }
344
345 static const struct {
346   DBusTransportOpenResult (* func) (DBusAddressEntry *entry,
347                                     DBusTransport   **transport_p,
348                                     DBusError        *error);
349 } open_funcs[] = {
350   { _dbus_transport_open_socket },
351   { _dbus_transport_open_platform_specific },
352   { _dbus_transport_open_autolaunch }
353 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
354   , { _dbus_transport_open_debug_pipe }
355 #endif
356 };
357
358 /**
359  * Try to open a new transport for the given address entry.  (This
360  * opens a client-side-of-the-connection transport.)
361  * 
362  * @param entry the address entry
363  * @param error location to store reason for failure.
364  * @returns new transport of #NULL on failure.
365  */
366 DBusTransport*
367 _dbus_transport_open (DBusAddressEntry *entry,
368                       DBusError        *error)
369 {
370   DBusTransport *transport;
371   const char *expected_guid_orig;
372   char *expected_guid;
373   int i;
374   DBusError tmp_error = DBUS_ERROR_INIT;
375
376   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
377   
378   transport = NULL;
379   expected_guid_orig = dbus_address_entry_get_value (entry, "guid");
380   expected_guid = _dbus_strdup (expected_guid_orig);
381
382   if (expected_guid_orig != NULL && expected_guid == NULL)
383     {
384       _DBUS_SET_OOM (error);
385       return NULL;
386     }
387
388   for (i = 0; i < (int) _DBUS_N_ELEMENTS (open_funcs); ++i)
389     {
390       DBusTransportOpenResult result;
391
392       _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
393       result = (* open_funcs[i].func) (entry, &transport, &tmp_error);
394
395       switch (result)
396         {
397         case DBUS_TRANSPORT_OPEN_OK:
398           _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
399           goto out;
400           break;
401         case DBUS_TRANSPORT_OPEN_NOT_HANDLED:
402           _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
403           /* keep going through the loop of open funcs */
404           break;
405         case DBUS_TRANSPORT_OPEN_BAD_ADDRESS:
406           _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
407           goto out;
408           break;
409         case DBUS_TRANSPORT_OPEN_DID_NOT_CONNECT:
410           _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
411           goto out;
412           break;
413         }
414     }
415
416  out:
417   
418   if (transport == NULL)
419     {
420       if (!dbus_error_is_set (&tmp_error))
421         _dbus_set_bad_address (&tmp_error,
422                                NULL, NULL,
423                                "Unknown address type (examples of valid types are \"tcp\" and on UNIX \"unix\")");
424       
425       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
426       dbus_move_error(&tmp_error, error);
427       dbus_free (expected_guid);
428     }
429   else
430     {
431       _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
432
433       /* In the case of autostart the initial guid is NULL
434        * and the autostart transport recursively calls
435        * _dbus_open_transport wich returns a transport
436        * with a guid.  That guid is the definitive one.
437        *
438        * FIXME: if more transports are added they may have
439        * an effect on the expected_guid semantics (i.e. 
440        * expected_guid and transport->expected_guid may
441        * both have values).  This is very unlikely though
442        * we should either throw asserts here for those 
443        * corner cases or refactor the code so it is 
444        * clearer on what is expected and what is not
445        */
446       if(expected_guid)
447         transport->expected_guid = expected_guid;
448     }
449
450   return transport;
451 }
452
453 /**
454  * Increments the reference count for the transport.
455  *
456  * @param transport the transport.
457  * @returns the transport.
458  */
459 DBusTransport *
460 _dbus_transport_ref (DBusTransport *transport)
461 {
462   _dbus_assert (transport->refcount > 0);
463   
464   transport->refcount += 1;
465
466   return transport;
467 }
468
469 /**
470  * Decrements the reference count for the transport.
471  * Disconnects and finalizes the transport if
472  * the reference count reaches zero.
473  *
474  * @param transport the transport.
475  */
476 void
477 _dbus_transport_unref (DBusTransport *transport)
478 {
479   _dbus_assert (transport != NULL);
480   _dbus_assert (transport->refcount > 0);
481   
482   transport->refcount -= 1;
483   if (transport->refcount == 0)
484     {
485       _dbus_verbose ("finalizing\n");
486       
487       _dbus_assert (transport->vtable->finalize != NULL);
488       
489       (* transport->vtable->finalize) (transport);
490     }
491 }
492
493 /**
494  * Closes our end of the connection to a remote application. Further
495  * attempts to use this transport will fail. Only the first call to
496  * _dbus_transport_disconnect() will have an effect.
497  *
498  * @param transport the transport.
499  * 
500  */
501 void
502 _dbus_transport_disconnect (DBusTransport *transport)
503 {
504   _dbus_verbose ("start\n");
505   
506   _dbus_assert (transport->vtable->disconnect != NULL);
507   
508   if (transport->disconnected)
509     return;
510
511   (* transport->vtable->disconnect) (transport);
512   
513   transport->disconnected = TRUE;
514
515   _dbus_verbose ("end\n");
516 }
517
518 /**
519  * Returns #TRUE if the transport has not been disconnected.
520  * Disconnection can result from _dbus_transport_disconnect()
521  * or because the server drops its end of the connection.
522  *
523  * @param transport the transport.
524  * @returns whether we're connected
525  */
526 dbus_bool_t
527 _dbus_transport_get_is_connected (DBusTransport *transport)
528 {
529   return !transport->disconnected;
530 }
531
532 static dbus_bool_t
533 auth_via_unix_user_function (DBusTransport *transport)
534 {
535   DBusCredentials *auth_identity;
536   dbus_bool_t allow;
537   DBusConnection *connection;
538   DBusAllowUnixUserFunction unix_user_function;
539   void *unix_user_data;
540   dbus_uid_t uid;
541
542   /* Dropping the lock here probably isn't that safe. */
543   
544   auth_identity = _dbus_auth_get_identity (transport->auth);
545   _dbus_assert (auth_identity != NULL);
546
547   connection = transport->connection;
548   unix_user_function = transport->unix_user_function;
549   unix_user_data = transport->unix_user_data;
550   uid = _dbus_credentials_get_unix_uid (auth_identity);
551               
552   _dbus_verbose ("unlock\n");
553   _dbus_connection_unlock (connection);
554
555   allow = (* unix_user_function) (connection,
556                                   uid,
557                                   unix_user_data);
558               
559   _dbus_verbose ("lock post unix user function\n");
560   _dbus_connection_lock (connection);
561
562   if (allow)
563     {
564       _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid);
565     }
566   else
567     {
568       _dbus_verbose ("Client UID "DBUS_UID_FORMAT
569                      " was rejected, disconnecting\n",
570                      _dbus_credentials_get_unix_uid (auth_identity));
571       _dbus_transport_disconnect (transport);
572     }
573
574   return allow;
575 }
576
577 static dbus_bool_t
578 auth_via_windows_user_function (DBusTransport *transport)
579 {
580   DBusCredentials *auth_identity;  
581   dbus_bool_t allow;
582   DBusConnection *connection;
583   DBusAllowWindowsUserFunction windows_user_function;
584   void *windows_user_data;
585   char *windows_sid;
586
587   /* Dropping the lock here probably isn't that safe. */
588   
589   auth_identity = _dbus_auth_get_identity (transport->auth);
590   _dbus_assert (auth_identity != NULL);
591
592   connection = transport->connection;
593   windows_user_function = transport->windows_user_function;
594   windows_user_data = transport->unix_user_data;
595   windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
596
597   if (windows_sid == NULL)
598     {
599       /* OOM */
600       return FALSE;
601     }
602                 
603   _dbus_verbose ("unlock\n");
604   _dbus_connection_unlock (connection);
605
606   allow = (* windows_user_function) (connection,
607                                      windows_sid,
608                                      windows_user_data);
609               
610   _dbus_verbose ("lock post windows user function\n");
611   _dbus_connection_lock (connection);
612
613   if (allow)
614     {
615       _dbus_verbose ("Client SID '%s' authorized\n", windows_sid);
616     }
617   else
618     {
619       _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n",
620                      _dbus_credentials_get_windows_sid (auth_identity));
621       _dbus_transport_disconnect (transport);
622     }
623
624   return allow;
625 }
626
627 static dbus_bool_t
628 auth_via_default_rules (DBusTransport *transport)
629 {
630   DBusCredentials *auth_identity;
631   DBusCredentials *our_identity;
632   dbus_bool_t allow;
633   
634   auth_identity = _dbus_auth_get_identity (transport->auth);
635   _dbus_assert (auth_identity != NULL);
636
637   /* By default, connection is allowed if the client is 1) root or 2)
638    * has the same UID as us or 3) anonymous is allowed.
639    */
640   
641   our_identity = _dbus_credentials_new_from_current_process ();
642   if (our_identity == NULL)
643     {
644       /* OOM */
645       return FALSE;
646     }
647               
648   if (transport->allow_anonymous ||
649       _dbus_credentials_get_unix_uid (auth_identity) == 0 ||
650       _dbus_credentials_same_user (our_identity,
651                                    auth_identity))
652     {
653       if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
654           _dbus_verbose ("Client authorized as SID '%s'"
655                          "matching our SID '%s'\n",
656                          _dbus_credentials_get_windows_sid(auth_identity),
657                          _dbus_credentials_get_windows_sid(our_identity));
658       else
659           _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
660                          " matching our UID "DBUS_UID_FORMAT"\n",
661                          _dbus_credentials_get_unix_uid(auth_identity),
662                          _dbus_credentials_get_unix_uid(our_identity));
663       /* We have authenticated! */
664       allow = TRUE;
665     }
666   else
667     {
668       if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
669           _dbus_verbose ("Client authorized as SID '%s'"
670                          " but our SID is '%s', disconnecting\n",
671                          (_dbus_credentials_get_windows_sid(auth_identity) ?
672                           _dbus_credentials_get_windows_sid(auth_identity) : "<null>"),
673                          (_dbus_credentials_get_windows_sid(our_identity) ?
674                           _dbus_credentials_get_windows_sid(our_identity) : "<null>"));
675       else
676           _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT
677                          " but our UID is "DBUS_UID_FORMAT", disconnecting\n",
678                          _dbus_credentials_get_unix_uid(auth_identity),
679                          _dbus_credentials_get_unix_uid(our_identity));
680       _dbus_transport_disconnect (transport);
681       allow = FALSE;
682     }  
683
684   _dbus_credentials_unref (our_identity);
685   
686   return allow;
687 }
688
689 /**
690  * Returns #TRUE if we have been authenticated. It will return #TRUE even if
691  * the transport is now disconnected, but was ever authenticated before
692  * disconnecting.
693  *
694  * This replaces the older _dbus_transport_get_is_authenticated() which
695  * had side-effects.
696  *
697  * @param transport the transport
698  * @returns whether we're authenticated
699  */
700 dbus_bool_t
701 _dbus_transport_peek_is_authenticated (DBusTransport *transport)
702 {
703   return transport->authenticated;
704 }
705
706 /**
707  * Returns #TRUE if we have been authenticated. It will return #TRUE even if
708  * the transport is now disconnected, but was ever authenticated before
709  * disconnecting.
710  *
711  * If we have not finished authenticating, but we have enough buffered input
712  * to finish the job, then this function will do so before it returns.
713  *
714  * This used to be called _dbus_transport_get_is_authenticated(), but that
715  * name seems inappropriate for a function with side-effects.
716  *
717  * @todo we drop connection->mutex when calling the unix_user_function,
718  * and windows_user_function, which may not be safe really.
719  *
720  * @param transport the transport
721  * @returns whether we're authenticated
722  */
723 dbus_bool_t
724 _dbus_transport_try_to_authenticate (DBusTransport *transport)
725 {  
726   if (transport->authenticated)
727     return TRUE;
728   else
729     {
730       dbus_bool_t maybe_authenticated;
731       
732       if (transport->disconnected)
733         return FALSE;
734
735       /* paranoia ref since we call user callbacks sometimes */
736       _dbus_connection_ref_unlocked (transport->connection);
737       
738       maybe_authenticated =
739         (!(transport->send_credentials_pending ||
740            transport->receive_credentials_pending));
741
742       if (maybe_authenticated)
743         {
744           switch (_dbus_auth_do_work (transport->auth))
745             {
746             case DBUS_AUTH_STATE_AUTHENTICATED:
747               /* leave as maybe_authenticated */
748               break;
749             default:
750               maybe_authenticated = FALSE;
751             }
752         }
753
754       /* If we're the client, verify the GUID
755        */
756       if (maybe_authenticated && !transport->is_server)
757         {
758           const char *server_guid;
759
760           server_guid = _dbus_auth_get_guid_from_server (transport->auth);
761           _dbus_assert (server_guid != NULL);
762
763           if (transport->expected_guid &&
764               strcmp (transport->expected_guid, server_guid) != 0)
765             {
766               _dbus_verbose ("Client expected GUID '%s' and we got '%s' from the server\n",
767                              transport->expected_guid, server_guid);
768               _dbus_transport_disconnect (transport);
769               _dbus_connection_unref_unlocked (transport->connection);
770               return FALSE;
771             }
772         }
773
774       /* If we're the server, see if we want to allow this identity to proceed.
775        */
776       if (maybe_authenticated && transport->is_server)
777         {
778           dbus_bool_t allow;
779           DBusCredentials *auth_identity;
780           
781           auth_identity = _dbus_auth_get_identity (transport->auth);
782           _dbus_assert (auth_identity != NULL);
783           
784           /* If we have an auth'd user and a user function, delegate
785            * deciding whether auth credentials are good enough to the
786            * app; otherwise, use our default decision process.
787            */
788           if (transport->unix_user_function != NULL &&
789               _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID))
790             {
791               allow = auth_via_unix_user_function (transport);
792             }
793           else if (transport->windows_user_function != NULL &&
794                    _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID))
795             {
796               allow = auth_via_windows_user_function (transport);
797             }      
798           else
799             {
800               allow = auth_via_default_rules (transport);
801             }
802           
803           if (!allow)
804             maybe_authenticated = FALSE;
805         }
806
807       transport->authenticated = maybe_authenticated;
808
809       _dbus_connection_unref_unlocked (transport->connection);
810       return maybe_authenticated;
811     }
812 }
813
814 /**
815  * See dbus_connection_get_is_anonymous().
816  *
817  * @param transport the transport
818  * @returns #TRUE if not authenticated or authenticated as anonymous
819  */
820 dbus_bool_t
821 _dbus_transport_get_is_anonymous (DBusTransport *transport)
822 {
823   DBusCredentials *auth_identity;
824   
825   if (!transport->authenticated)
826     return TRUE;
827   
828   auth_identity = _dbus_auth_get_identity (transport->auth);
829
830   if (_dbus_credentials_are_anonymous (auth_identity))
831     return TRUE;
832   else
833     return FALSE;
834 }
835
836 /**
837  * Returns TRUE if the transport supports sending unix fds.
838  *
839  * @param transport the transport
840  * @returns #TRUE if TRUE it is possible to send unix fds across the transport.
841  */
842 dbus_bool_t
843 _dbus_transport_can_pass_unix_fd(DBusTransport *transport)
844 {
845   return DBUS_TRANSPORT_CAN_SEND_UNIX_FD(transport);
846 }
847
848 /**
849  * Gets the address of a transport. It will be
850  * #NULL for a server-side transport.
851  *
852  * @param transport the transport
853  * @returns transport's address
854  */
855 const char*
856 _dbus_transport_get_address (DBusTransport *transport)
857 {
858   return transport->address;
859 }
860
861 /**
862  * Gets the id of the server we are connected to (see
863  * dbus_server_get_id()). Only works on client side.
864  *
865  * @param transport the transport
866  * @returns transport's server's id or #NULL if we are the server side
867  */
868 const char*
869 _dbus_transport_get_server_id (DBusTransport *transport)
870 {
871   if (transport->is_server)
872     return NULL;
873   else if (transport->authenticated)
874     return _dbus_auth_get_guid_from_server (transport->auth);
875   else
876     return transport->expected_guid;
877 }
878
879 /**
880  * Handles a watch by reading data, writing data, or disconnecting
881  * the transport, as appropriate for the given condition.
882  *
883  * @param transport the transport.
884  * @param watch the watch.
885  * @param condition the current state of the watched file descriptor.
886  * @returns #FALSE if not enough memory to fully handle the watch
887  */
888 dbus_bool_t
889 _dbus_transport_handle_watch (DBusTransport           *transport,
890                               DBusWatch               *watch,
891                               unsigned int             condition)
892 {
893   dbus_bool_t retval;
894   
895   _dbus_assert (transport->vtable->handle_watch != NULL);
896
897   if (transport->disconnected)
898     return TRUE;
899
900   if (dbus_watch_get_socket (watch) < 0)
901     {
902       _dbus_warn_check_failed ("Tried to handle an invalidated watch; this watch should have been removed\n");
903       return TRUE;
904     }
905   
906   _dbus_watch_sanitize_condition (watch, &condition);
907
908   _dbus_transport_ref (transport);
909   _dbus_watch_ref (watch);
910   retval = (* transport->vtable->handle_watch) (transport, watch, condition);
911   _dbus_watch_unref (watch);
912   _dbus_transport_unref (transport);
913
914   return retval;
915 }
916
917 /**
918  * Sets the connection using this transport. Allows the transport
919  * to add watches to the connection, queue incoming messages,
920  * and pull outgoing messages.
921  *
922  * @param transport the transport.
923  * @param connection the connection.
924  * @returns #FALSE if not enough memory
925  */
926 dbus_bool_t
927 _dbus_transport_set_connection (DBusTransport  *transport,
928                                 DBusConnection *connection)
929 {
930   _dbus_assert (transport->vtable->connection_set != NULL);
931   _dbus_assert (transport->connection == NULL);
932   
933   transport->connection = connection;
934
935   _dbus_transport_ref (transport);
936   if (!(* transport->vtable->connection_set) (transport))
937     transport->connection = NULL;
938   _dbus_transport_unref (transport);
939
940   return transport->connection != NULL;
941 }
942
943 /**
944  * Get the socket file descriptor, if any.
945  *
946  * @param transport the transport
947  * @param fd_p pointer to fill in with the descriptor
948  * @returns #TRUE if a descriptor was available
949  */
950 dbus_bool_t
951 _dbus_transport_get_socket_fd (DBusTransport *transport,
952                                DBusSocket    *fd_p)
953 {
954   dbus_bool_t retval;
955   
956   if (transport->vtable->get_socket_fd == NULL)
957     return FALSE;
958
959   if (transport->disconnected)
960     return FALSE;
961
962   _dbus_transport_ref (transport);
963
964   retval = (* transport->vtable->get_socket_fd) (transport,
965                                                  fd_p);
966   
967   _dbus_transport_unref (transport);
968
969   return retval;
970 }
971
972 /**
973  * Performs a single poll()/select() on the transport's file
974  * descriptors and then reads/writes data as appropriate,
975  * queueing incoming messages and sending outgoing messages.
976  * This is the backend for _dbus_connection_do_iteration().
977  * See _dbus_connection_do_iteration() for full details.
978  *
979  * @param transport the transport.
980  * @param flags indicates whether to read or write, and whether to block.
981  * @param timeout_milliseconds if blocking, timeout or -1 for no timeout.
982  */
983 void
984 _dbus_transport_do_iteration (DBusTransport  *transport,
985                               unsigned int    flags,
986                               int             timeout_milliseconds)
987 {
988   _dbus_assert (transport->vtable->do_iteration != NULL);
989
990   _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
991                  flags, timeout_milliseconds, !transport->disconnected);
992   
993   if ((flags & (DBUS_ITERATION_DO_WRITING |
994                 DBUS_ITERATION_DO_READING)) == 0)
995     return; /* Nothing to do */
996
997   if (transport->disconnected)
998     return;
999
1000   _dbus_transport_ref (transport);
1001   (* transport->vtable->do_iteration) (transport, flags,
1002                                        timeout_milliseconds);
1003   _dbus_transport_unref (transport);
1004
1005   _dbus_verbose ("end\n");
1006 }
1007
1008 static dbus_bool_t
1009 recover_unused_bytes (DBusTransport *transport)
1010 {
1011   if (_dbus_auth_needs_decoding (transport->auth))
1012     {
1013       DBusString plaintext;
1014       const DBusString *encoded;
1015       DBusString *buffer;
1016       int orig_len;
1017       
1018       if (!_dbus_string_init (&plaintext))
1019         goto nomem;
1020       
1021       _dbus_auth_get_unused_bytes (transport->auth,
1022                                    &encoded);
1023
1024       if (!_dbus_auth_decode_data (transport->auth,
1025                                    encoded, &plaintext))
1026         {
1027           _dbus_string_free (&plaintext);
1028           goto nomem;
1029         }
1030       
1031       _dbus_message_loader_get_buffer (transport->loader,
1032                                        &buffer);
1033       
1034       orig_len = _dbus_string_get_length (buffer);
1035       
1036       if (!_dbus_string_move (&plaintext, 0, buffer,
1037                               orig_len))
1038         {
1039           _dbus_string_free (&plaintext);
1040           goto nomem;
1041         }
1042       
1043       _dbus_verbose (" %d unused bytes sent to message loader\n", 
1044                      _dbus_string_get_length (buffer) -
1045                      orig_len);
1046       
1047       _dbus_message_loader_return_buffer (transport->loader,
1048                                           buffer);
1049
1050       _dbus_auth_delete_unused_bytes (transport->auth);
1051       
1052       _dbus_string_free (&plaintext);
1053     }
1054   else
1055     {
1056       const DBusString *bytes;
1057       DBusString *buffer;
1058       int orig_len;
1059       dbus_bool_t succeeded;
1060
1061       _dbus_message_loader_get_buffer (transport->loader,
1062                                        &buffer);
1063                 
1064       orig_len = _dbus_string_get_length (buffer);
1065                 
1066       _dbus_auth_get_unused_bytes (transport->auth,
1067                                    &bytes);
1068
1069       succeeded = TRUE;
1070       if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
1071         succeeded = FALSE;
1072       
1073       _dbus_verbose (" %d unused bytes sent to message loader\n", 
1074                      _dbus_string_get_length (buffer) -
1075                      orig_len);
1076       
1077       _dbus_message_loader_return_buffer (transport->loader,
1078                                           buffer);
1079
1080       if (succeeded)
1081         _dbus_auth_delete_unused_bytes (transport->auth);
1082       else
1083         goto nomem;
1084     }
1085
1086   return TRUE;
1087
1088  nomem:
1089   _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
1090   return FALSE;
1091 }
1092
1093 /**
1094  * Reports our current dispatch status (whether there's buffered
1095  * data to be queued as messages, or not, or we need memory).
1096  *
1097  * @param transport the transport
1098  * @returns current status
1099  */
1100 DBusDispatchStatus
1101 _dbus_transport_get_dispatch_status (DBusTransport *transport)
1102 {
1103   if (_dbus_counter_get_size_value (transport->live_messages) >= transport->max_live_messages_size ||
1104       _dbus_counter_get_unix_fd_value (transport->live_messages) >= transport->max_live_messages_unix_fds)
1105     return DBUS_DISPATCH_COMPLETE; /* complete for now */
1106
1107   if (!_dbus_transport_try_to_authenticate (transport))
1108     {
1109       if (_dbus_auth_do_work (transport->auth) ==
1110           DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
1111         return DBUS_DISPATCH_NEED_MEMORY;
1112       else if (!_dbus_transport_try_to_authenticate (transport))
1113         return DBUS_DISPATCH_COMPLETE;
1114     }
1115
1116   if (!transport->unused_bytes_recovered &&
1117       !recover_unused_bytes (transport))
1118     return DBUS_DISPATCH_NEED_MEMORY;
1119
1120   transport->unused_bytes_recovered = TRUE;
1121   
1122   if (!_dbus_message_loader_queue_messages (transport->loader))
1123     return DBUS_DISPATCH_NEED_MEMORY;
1124
1125   if (_dbus_message_loader_peek_message (transport->loader) != NULL)
1126     return DBUS_DISPATCH_DATA_REMAINS;
1127   else
1128     return DBUS_DISPATCH_COMPLETE;
1129 }
1130
1131 /**
1132  * Processes data we've read while handling a watch, potentially
1133  * converting some of it to messages and queueing those messages on
1134  * the connection.
1135  *
1136  * @param transport the transport
1137  * @returns #TRUE if we had enough memory to queue all messages
1138  */
1139 dbus_bool_t
1140 _dbus_transport_queue_messages (DBusTransport *transport)
1141 {
1142   DBusDispatchStatus status;
1143
1144 #if 0
1145   _dbus_verbose ("_dbus_transport_queue_messages()\n");
1146 #endif
1147   
1148   /* Queue any messages */
1149   while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
1150     {
1151       DBusMessage *message;
1152       DBusList *link;
1153
1154       link = _dbus_message_loader_pop_message_link (transport->loader);
1155       _dbus_assert (link != NULL);
1156       
1157       message = link->data;
1158       
1159       _dbus_verbose ("queueing received message %p\n", message);
1160
1161       if (!_dbus_message_add_counter (message, transport->live_messages))
1162         {
1163           _dbus_message_loader_putback_message_link (transport->loader,
1164                                                      link);
1165           status = DBUS_DISPATCH_NEED_MEMORY;
1166           break;
1167         }
1168       else
1169         {
1170           /* We didn't call the notify function when we added the counter, so
1171            * catch up now. Since we have the connection's lock, it's desirable
1172            * that we bypass the notify function and call this virtual method
1173            * directly. */
1174           if (transport->vtable->live_messages_changed)
1175             (* transport->vtable->live_messages_changed) (transport);
1176
1177           /* pass ownership of link and message ref to connection */
1178           _dbus_connection_queue_received_message_link (transport->connection,
1179                                                         link);
1180         }
1181     }
1182
1183   if (_dbus_message_loader_get_is_corrupted (transport->loader))
1184     {
1185       _dbus_verbose ("Corrupted message stream, disconnecting\n");
1186       _dbus_transport_disconnect (transport);
1187     }
1188
1189   return status != DBUS_DISPATCH_NEED_MEMORY;
1190 }
1191
1192 /**
1193  * See dbus_connection_set_max_message_size().
1194  *
1195  * @param transport the transport
1196  * @param size the max size of a single message
1197  */
1198 void
1199 _dbus_transport_set_max_message_size (DBusTransport  *transport,
1200                                       long            size)
1201 {
1202   _dbus_message_loader_set_max_message_size (transport->loader, size);
1203 }
1204
1205 /**
1206  * See dbus_connection_set_max_message_unix_fds().
1207  *
1208  * @param transport the transport
1209  * @param n the max number of unix fds of a single message
1210  */
1211 void
1212 _dbus_transport_set_max_message_unix_fds (DBusTransport  *transport,
1213                                           long            n)
1214 {
1215   _dbus_message_loader_set_max_message_unix_fds (transport->loader, n);
1216 }
1217
1218 /**
1219  * See dbus_connection_get_max_message_size().
1220  *
1221  * @param transport the transport
1222  * @returns max message size
1223  */
1224 long
1225 _dbus_transport_get_max_message_size (DBusTransport  *transport)
1226 {
1227   return _dbus_message_loader_get_max_message_size (transport->loader);
1228 }
1229
1230 /**
1231  * See dbus_connection_get_max_message_unix_fds().
1232  *
1233  * @param transport the transport
1234  * @returns max message unix fds
1235  */
1236 long
1237 _dbus_transport_get_max_message_unix_fds (DBusTransport  *transport)
1238 {
1239   return _dbus_message_loader_get_max_message_unix_fds (transport->loader);
1240 }
1241
1242 /**
1243  * See dbus_connection_set_max_received_size().
1244  *
1245  * @param transport the transport
1246  * @param size the max size of all incoming messages
1247  */
1248 void
1249 _dbus_transport_set_max_received_size (DBusTransport  *transport,
1250                                        long            size)
1251 {
1252   transport->max_live_messages_size = size;
1253   _dbus_counter_set_notify (transport->live_messages,
1254                             transport->max_live_messages_size,
1255                             transport->max_live_messages_unix_fds,
1256                             live_messages_notify,
1257                             transport);
1258 }
1259
1260 /**
1261  * See dbus_connection_set_max_received_unix_fds().
1262  *
1263  * @param transport the transport
1264  * @param n the max unix fds of all incoming messages
1265  */
1266 void
1267 _dbus_transport_set_max_received_unix_fds (DBusTransport  *transport,
1268                                            long            n)
1269 {
1270   transport->max_live_messages_unix_fds = n;
1271   _dbus_counter_set_notify (transport->live_messages,
1272                             transport->max_live_messages_size,
1273                             transport->max_live_messages_unix_fds,
1274                             live_messages_notify,
1275                             transport);
1276 }
1277
1278 /**
1279  * See dbus_connection_get_max_received_size().
1280  *
1281  * @param transport the transport
1282  * @returns max bytes for all live messages
1283  */
1284 long
1285 _dbus_transport_get_max_received_size (DBusTransport  *transport)
1286 {
1287   return transport->max_live_messages_size;
1288 }
1289
1290 /**
1291  * See dbus_connection_set_max_received_unix_fds().
1292  *
1293  * @param transport the transport
1294  * @returns max unix fds for all live messages
1295  */
1296 long
1297 _dbus_transport_get_max_received_unix_fds (DBusTransport  *transport)
1298 {
1299   return transport->max_live_messages_unix_fds;
1300 }
1301
1302 /**
1303  * See dbus_connection_get_unix_user().
1304  *
1305  * @param transport the transport
1306  * @param uid return location for the user ID
1307  * @returns #TRUE if uid is filled in with a valid user ID
1308  */
1309 dbus_bool_t
1310 _dbus_transport_get_unix_user (DBusTransport *transport,
1311                                unsigned long *uid)
1312 {
1313   DBusCredentials *auth_identity;
1314
1315   *uid = _DBUS_INT32_MAX; /* better than some root or system user in
1316                            * case of bugs in the caller. Caller should
1317                            * never use this value on purpose, however.
1318                            */
1319   
1320   if (!transport->authenticated)
1321     return FALSE;
1322   
1323   auth_identity = _dbus_auth_get_identity (transport->auth);
1324
1325   if (_dbus_credentials_include (auth_identity,
1326                                  DBUS_CREDENTIAL_UNIX_USER_ID))
1327     {
1328       *uid = _dbus_credentials_get_unix_uid (auth_identity);
1329       return TRUE;
1330     }
1331   else
1332     return FALSE;
1333 }
1334
1335 /**
1336  * See dbus_connection_get_unix_process_id().
1337  *
1338  * @param transport the transport
1339  * @param pid return location for the process ID
1340  * @returns #TRUE if uid is filled in with a valid process ID
1341  */
1342 dbus_bool_t
1343 _dbus_transport_get_unix_process_id (DBusTransport *transport,
1344                                      unsigned long *pid)
1345 {
1346   DBusCredentials *auth_identity;
1347
1348   *pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose,
1349                           * but we set it to a safe number, INT_MAX,
1350                           * just to root out possible bugs in bad callers.
1351                           */
1352   
1353   if (!transport->authenticated)
1354     return FALSE;
1355   
1356   auth_identity = _dbus_auth_get_identity (transport->auth);
1357
1358   if (_dbus_credentials_include (auth_identity,
1359                                  DBUS_CREDENTIAL_UNIX_PROCESS_ID))
1360     {
1361       *pid = _dbus_credentials_get_pid (auth_identity);
1362       return TRUE;
1363     }
1364   else
1365     return FALSE;
1366 }
1367
1368 /**
1369  * See dbus_connection_get_adt_audit_session_data().
1370  *
1371  * @param transport the transport
1372  * @param data return location for the ADT audit data 
1373  * @param data_size return length of audit data
1374  * @returns #TRUE if audit data is filled in with a valid ucred
1375  */
1376 dbus_bool_t
1377 _dbus_transport_get_adt_audit_session_data (DBusTransport      *transport,
1378                                             void              **data,
1379                                             int                *data_size)
1380 {
1381   DBusCredentials *auth_identity;
1382
1383   *data = NULL;
1384   *data_size = 0;
1385   
1386   if (!transport->authenticated)
1387     return FALSE;
1388   
1389   auth_identity = _dbus_auth_get_identity (transport->auth);
1390
1391   if (_dbus_credentials_include (auth_identity,
1392                                  DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID))
1393     {
1394       *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity);
1395       *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity);
1396       return TRUE;
1397     }
1398   else
1399     return FALSE;
1400 }
1401
1402 /**
1403  * See dbus_connection_set_unix_user_function().
1404  *
1405  * @param transport the transport
1406  * @param function the predicate
1407  * @param data data to pass to the predicate
1408  * @param free_data_function function to free the data
1409  * @param old_data the old user data to be freed
1410  * @param old_free_data_function old free data function to free it with
1411  */
1412 void
1413 _dbus_transport_set_unix_user_function (DBusTransport             *transport,
1414                                         DBusAllowUnixUserFunction  function,
1415                                         void                      *data,
1416                                         DBusFreeFunction           free_data_function,
1417                                         void                     **old_data,
1418                                         DBusFreeFunction          *old_free_data_function)
1419 {  
1420   *old_data = transport->unix_user_data;
1421   *old_free_data_function = transport->free_unix_user_data;
1422
1423   transport->unix_user_function = function;
1424   transport->unix_user_data = data;
1425   transport->free_unix_user_data = free_data_function;
1426 }
1427
1428 dbus_bool_t
1429 _dbus_transport_get_linux_security_label (DBusTransport  *transport,
1430                                           char          **label_p)
1431 {
1432   DBusCredentials *auth_identity;
1433
1434   *label_p = NULL;
1435
1436   if (!transport->authenticated)
1437     return FALSE;
1438
1439   auth_identity = _dbus_auth_get_identity (transport->auth);
1440
1441   if (_dbus_credentials_include (auth_identity,
1442                                  DBUS_CREDENTIAL_LINUX_SECURITY_LABEL))
1443     {
1444       /* If no memory, we are supposed to return TRUE and set NULL */
1445       *label_p = _dbus_strdup (_dbus_credentials_get_linux_security_label (auth_identity));
1446
1447       return TRUE;
1448     }
1449   else
1450     {
1451       return FALSE;
1452     }
1453 }
1454
1455 /**
1456  * See dbus_connection_get_windows_user().
1457  *
1458  * @param transport the transport
1459  * @param windows_sid_p return location for the user ID
1460  * @returns #TRUE if user is available; the returned value may still be #NULL if no memory to copy it
1461  */
1462 dbus_bool_t
1463 _dbus_transport_get_windows_user (DBusTransport              *transport,
1464                                   char                      **windows_sid_p)
1465 {
1466   DBusCredentials *auth_identity;
1467
1468   *windows_sid_p = NULL;
1469   
1470   if (!transport->authenticated)
1471     return FALSE;
1472   
1473   auth_identity = _dbus_auth_get_identity (transport->auth);
1474
1475   if (_dbus_credentials_include (auth_identity,
1476                                  DBUS_CREDENTIAL_WINDOWS_SID))
1477     {
1478       /* If no memory, we are supposed to return TRUE and set NULL */
1479       *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
1480
1481       return TRUE;
1482     }
1483   else
1484     return FALSE;
1485 }
1486
1487 /**
1488  * See dbus_connection_set_windows_user_function().
1489  *
1490  * @param transport the transport
1491  * @param function the predicate
1492  * @param data data to pass to the predicate
1493  * @param free_data_function function to free the data
1494  * @param old_data the old user data to be freed
1495  * @param old_free_data_function old free data function to free it with
1496  */
1497
1498 void
1499 _dbus_transport_set_windows_user_function (DBusTransport              *transport,
1500                                            DBusAllowWindowsUserFunction   function,
1501                                            void                       *data,
1502                                            DBusFreeFunction            free_data_function,
1503                                            void                      **old_data,
1504                                            DBusFreeFunction           *old_free_data_function)
1505 {
1506   *old_data = transport->windows_user_data;
1507   *old_free_data_function = transport->free_windows_user_data;
1508
1509   transport->windows_user_function = function;
1510   transport->windows_user_data = data;
1511   transport->free_windows_user_data = free_data_function;
1512 }
1513
1514 /**
1515  * Sets the SASL authentication mechanisms supported by this transport.
1516  *
1517  * @param transport the transport
1518  * @param mechanisms the #NULL-terminated array of mechanisms
1519  *
1520  * @returns #FALSE if no memory
1521  */
1522 dbus_bool_t
1523 _dbus_transport_set_auth_mechanisms (DBusTransport  *transport,
1524                                      const char    **mechanisms)
1525 {
1526   return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
1527 }
1528
1529 /**
1530  * See dbus_connection_set_allow_anonymous()
1531  *
1532  * @param transport the transport
1533  * @param value #TRUE to allow anonymous connection
1534  */
1535 void
1536 _dbus_transport_set_allow_anonymous (DBusTransport              *transport,
1537                                      dbus_bool_t                 value)
1538 {
1539   transport->allow_anonymous = value != FALSE;
1540 }
1541
1542 /**
1543  * Return how many file descriptors are pending in the loader
1544  *
1545  * @param transport the transport
1546  */
1547 int
1548 _dbus_transport_get_pending_fds_count (DBusTransport *transport)
1549 {
1550   return _dbus_message_loader_get_pending_fds_count (transport->loader);
1551 }
1552
1553 /**
1554  * Register a function to be called whenever the number of pending file
1555  * descriptors in the loader change.
1556  *
1557  * @param transport the transport
1558  * @param callback the callback
1559  */
1560 void
1561 _dbus_transport_set_pending_fds_function (DBusTransport *transport,
1562                                            void (* callback) (void *),
1563                                            void *data)
1564 {
1565   _dbus_message_loader_set_pending_fds_function (transport->loader,
1566                                                  callback, data);
1567 }
1568
1569 #ifdef DBUS_ENABLE_STATS
1570 void
1571 _dbus_transport_get_stats (DBusTransport  *transport,
1572                            dbus_uint32_t  *queue_bytes,
1573                            dbus_uint32_t  *queue_fds,
1574                            dbus_uint32_t  *peak_queue_bytes,
1575                            dbus_uint32_t  *peak_queue_fds)
1576 {
1577   if (queue_bytes != NULL)
1578     *queue_bytes = _dbus_counter_get_size_value (transport->live_messages);
1579
1580   if (queue_fds != NULL)
1581     *queue_fds = _dbus_counter_get_unix_fd_value (transport->live_messages);
1582
1583   if (peak_queue_bytes != NULL)
1584     *peak_queue_bytes = _dbus_counter_get_peak_size_value (transport->live_messages);
1585
1586   if (peak_queue_fds != NULL)
1587     *peak_queue_fds = _dbus_counter_get_peak_unix_fd_value (transport->live_messages);
1588 }
1589 #endif /* DBUS_ENABLE_STATS */
1590
1591 /** @} */