2003-03-31 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / dbus / dbus-transport.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
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 1.2
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include "dbus-transport-protected.h"
25 #include "dbus-transport-unix.h"
26 #include "dbus-connection-internal.h"
27 #include "dbus-watch.h"
28 #include "dbus-auth.h"
29 #include "dbus-address.h"
30 #ifdef DBUS_BUILD_TESTS
31 #include "dbus-transport-debug.h"
32 #include "dbus-server-debug-pipe.h"
33 #endif
34
35 /**
36  * @defgroup DBusTransport DBusTransport object
37  * @ingroup  DBusInternals
38  * @brief "Backend" for a DBusConnection.
39  *
40  * Types and functions related to DBusTransport.  A transport is an
41  * abstraction that can send and receive data via various kinds of
42  * network connections or other IPC mechanisms.
43  * 
44  * @{
45  */
46
47 /**
48  * @typedef DBusTransport
49  *
50  * Opaque object representing a way message stream.
51  * DBusTransport abstracts various kinds of actual
52  * transport mechanism, such as different network protocols,
53  * or encryption schemes.
54  */
55
56 static void
57 live_messages_size_notify (DBusCounter *counter,
58                            void        *user_data)
59 {
60   DBusTransport *transport = user_data;
61
62   _dbus_transport_ref (transport);
63
64 #if 0
65   _dbus_verbose ("Counter value is now %d\n",
66                  (int) _dbus_counter_get_value (counter));
67 #endif
68   
69   /* disable or re-enable the read watch for the transport if
70    * required.
71    */
72   if (* transport->vtable->live_messages_changed)
73     (* transport->vtable->live_messages_changed) (transport);
74
75   _dbus_transport_unref (transport);
76 }
77
78 /**
79  * Initializes the base class members of DBusTransport.
80  * Chained up to by subclasses in their constructor.
81  *
82  * @param transport the transport being created.
83  * @param vtable the subclass vtable.
84  * @param server #TRUE if this transport is on the server side of a connection
85  * @param address the address of the transport
86  * @returns #TRUE on success.
87  */
88 dbus_bool_t
89 _dbus_transport_init_base (DBusTransport             *transport,
90                            const DBusTransportVTable *vtable,
91                            dbus_bool_t                server,
92                            const DBusString          *address)
93 {
94   DBusMessageLoader *loader;
95   DBusAuth *auth;
96   DBusCounter *counter;
97   char *address_copy;
98   
99   loader = _dbus_message_loader_new ();
100   if (loader == NULL)
101     return FALSE;
102   
103   if (server)
104     auth = _dbus_auth_server_new ();
105   else
106     auth = _dbus_auth_client_new ();
107   if (auth == NULL)
108     {
109       _dbus_message_loader_unref (loader);
110       return FALSE;
111     }
112
113   counter = _dbus_counter_new ();
114   if (counter == NULL)
115     {
116       _dbus_auth_unref (auth);
117       _dbus_message_loader_unref (loader);
118       return FALSE;
119     }  
120   
121   if (server)
122     {
123       _dbus_assert (address == NULL);
124       address_copy = NULL;
125     }
126   else
127     {
128       _dbus_assert (address != NULL);
129
130       if (!_dbus_string_copy_data (address, &address_copy))
131         {
132           _dbus_counter_unref (counter);
133           _dbus_auth_unref (auth);
134           _dbus_message_loader_unref (loader);
135           return FALSE;
136         }
137     }
138   
139   transport->refcount = 1;
140   transport->vtable = vtable;
141   transport->loader = loader;
142   transport->auth = auth;
143   transport->live_messages_size = counter;
144   transport->authenticated = FALSE;
145   transport->messages_need_sending = FALSE;
146   transport->disconnected = FALSE;
147   transport->send_credentials_pending = !server;
148   transport->receive_credentials_pending = server;
149   transport->is_server = server;
150   transport->address = address_copy;
151   
152   transport->unix_user_function = NULL;
153   transport->unix_user_data = NULL;
154   transport->free_unix_user_data = NULL;
155   
156   /* Try to default to something that won't totally hose the system,
157    * but doesn't impose too much of a limitation.
158    */
159   transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
160   
161   transport->credentials.pid = -1;
162   transport->credentials.uid = -1;
163   transport->credentials.gid = -1;
164
165   _dbus_counter_set_notify (transport->live_messages_size,
166                             transport->max_live_messages_size,
167                             live_messages_size_notify,
168                             transport);
169
170   if (transport->address)
171     _dbus_verbose ("Initialized transport on address %s\n", transport->address);
172   
173   return TRUE;
174 }
175
176 /**
177  * Finalizes base class members of DBusTransport.
178  * Chained up to from subclass finalizers.
179  *
180  * @param transport the transport.
181  */
182 void
183 _dbus_transport_finalize_base (DBusTransport *transport)
184 {
185   if (!transport->disconnected)
186     _dbus_transport_disconnect (transport);
187
188   if (transport->free_unix_user_data != NULL)
189     (* transport->free_unix_user_data) (transport->unix_user_data);
190   
191   _dbus_message_loader_unref (transport->loader);
192   _dbus_auth_unref (transport->auth);
193   _dbus_counter_set_notify (transport->live_messages_size,
194                             0, NULL, NULL);
195   _dbus_counter_unref (transport->live_messages_size);
196   dbus_free (transport->address);
197 }
198
199 /**
200  * Opens a new transport for the given address.  (This opens a
201  * client-side-of-the-connection transport.)
202  *
203  * @todo error messages on bad address could really be better.
204  * DBusResultCode is a bit limiting here.
205  * 
206  * @param address the address.
207  * @param error location to store reason for failure.
208  * @returns new transport of #NULL on failure.
209  */
210 DBusTransport*
211 _dbus_transport_open (const char     *address,
212                       DBusError      *error)
213 {
214   DBusTransport *transport;
215   DBusAddressEntry **entries;
216   int len, i;
217   const char *address_problem_type;
218   const char *address_problem_field;
219   const char *address_problem_other;
220
221   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
222   
223   if (!dbus_parse_address (address, &entries, &len, error))
224     return NULL;
225
226   transport = NULL;
227   address_problem_type = NULL;
228   address_problem_field = NULL;
229   address_problem_other = NULL;
230   
231   for (i = 0; i < len; i++)
232     {
233       const char *method = dbus_address_entry_get_method (entries[i]);
234
235       if (strcmp (method, "unix") == 0)
236         {
237           const char *path = dbus_address_entry_get_value (entries[i], "path");
238
239           if (path == NULL)
240             {
241               address_problem_type = "unix";
242               address_problem_field = "path";              
243               goto bad_address;
244             }
245
246           transport = _dbus_transport_new_for_domain_socket (path, error);
247         }
248       else if (strcmp (method, "tcp") == 0)
249         {
250           const char *host = dbus_address_entry_get_value (entries[i], "host");
251           const char *port = dbus_address_entry_get_value (entries[i], "port");
252           DBusString  str;
253           long lport;
254           dbus_bool_t sresult;
255           
256           if (port == NULL)
257             {
258               address_problem_type = "tcp";
259               address_problem_field = "port";
260               goto bad_address;
261             }
262
263           _dbus_string_init_const (&str, port);
264           sresult = _dbus_string_parse_int (&str, 0, &lport, NULL);
265           _dbus_string_free (&str);
266           
267           if (sresult == FALSE || lport <= 0 || lport > 65535)
268             {
269               address_problem_other = "Port is not an integer between 0 and 65535";
270               goto bad_address;
271             }
272           
273           transport = _dbus_transport_new_for_tcp_socket (host, lport, error);
274         }
275 #ifdef DBUS_BUILD_TESTS
276       else if (strcmp (method, "debug") == 0)
277         {
278           const char *name = dbus_address_entry_get_value (entries[i], "name");
279
280           if (name == NULL)
281             {
282               address_problem_type = "debug";
283               address_problem_field = "name";
284               goto bad_address;
285             }
286
287           transport = _dbus_transport_debug_client_new (name, error);
288         }
289       else if (strcmp (method, "debug-pipe") == 0)
290         {
291           const char *name = dbus_address_entry_get_value (entries[i], "name");
292
293           if (name == NULL)
294             {
295               address_problem_type = "debug-pipe";
296               address_problem_field = "name";
297               goto bad_address;
298             }
299
300           transport = _dbus_transport_debug_pipe_new (name, error);
301         }
302 #endif
303       else
304         {
305           address_problem_other = "Unknown address type (examples of valid types are \"unix\" and \"tcp\")";
306           goto bad_address;
307         }
308
309       if (transport)
310         break;    
311     }
312   
313   dbus_address_entries_free (entries);
314   return transport;
315
316  bad_address:
317   dbus_address_entries_free (entries);
318
319   if (address_problem_type != NULL)
320     dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
321                     "Address of type %s was missing argument %s",
322                     address_problem_type, address_problem_field);
323   else
324     dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
325                     "Could not parse address: %s",
326                     address_problem_other);
327
328   return NULL;
329 }
330
331 /**
332  * Increments the reference count for the transport.
333  *
334  * @param transport the transport.
335  */
336 void
337 _dbus_transport_ref (DBusTransport *transport)
338 {
339   _dbus_assert (transport->refcount > 0);
340   
341   transport->refcount += 1;
342 }
343
344 /**
345  * Decrements the reference count for the transport.
346  * Disconnects and finalizes the transport if
347  * the reference count reaches zero.
348  *
349  * @param transport the transport.
350  */
351 void
352 _dbus_transport_unref (DBusTransport *transport)
353 {
354   _dbus_assert (transport != NULL);
355   _dbus_assert (transport->refcount > 0);
356
357   transport->refcount -= 1;
358   if (transport->refcount == 0)
359     {
360       _dbus_assert (transport->vtable->finalize != NULL);
361       
362       (* transport->vtable->finalize) (transport);
363     }
364 }
365
366 /**
367  * Closes our end of the connection to a remote application. Further
368  * attempts to use this transport will fail. Only the first call to
369  * _dbus_transport_disconnect() will have an effect.
370  *
371  * @param transport the transport.
372  * 
373  */
374 void
375 _dbus_transport_disconnect (DBusTransport *transport)
376 {
377   _dbus_assert (transport->vtable->disconnect != NULL);
378
379   if (transport->disconnected)
380     return;
381
382   (* transport->vtable->disconnect) (transport);
383   
384   transport->disconnected = TRUE;
385
386   if (transport->connection)
387     _dbus_connection_notify_disconnected (transport->connection);
388 }
389
390 /**
391  * Returns #TRUE if the transport has not been disconnected.
392  * Disconnection can result from _dbus_transport_disconnect()
393  * or because the server drops its end of the connection.
394  *
395  * @param transport the transport.
396  * @returns whether we're connected
397  */
398 dbus_bool_t
399 _dbus_transport_get_is_connected (DBusTransport *transport)
400 {
401   return !transport->disconnected;
402 }
403
404 /**
405  * Returns #TRUE if we have been authenticated.  Will return #TRUE
406  * even if the transport is disconnected.
407  *
408  * @todo needs to drop connection->mutex when calling the unix_user_function
409  *
410  * @param transport the transport
411  * @returns whether we're authenticated
412  */
413 dbus_bool_t
414 _dbus_transport_get_is_authenticated (DBusTransport *transport)
415 {  
416   if (transport->authenticated)
417     return TRUE;
418   else
419     {
420       dbus_bool_t maybe_authenticated;
421       
422       if (transport->disconnected)
423         return FALSE;
424       
425       maybe_authenticated =
426         (!(transport->send_credentials_pending ||
427            transport->receive_credentials_pending)) &&
428         _dbus_auth_do_work (transport->auth) == DBUS_AUTH_STATE_AUTHENTICATED;
429
430       /* If we've authenticated as some identity, check that the auth
431        * identity is the same as our own identity.  In the future, we
432        * may have API allowing applications to specify how this is
433        * done, for example they may allow connection as any identity,
434        * but then impose restrictions on certain identities.
435        * Or they may give certain identities extra privileges.
436        */
437       
438       if (maybe_authenticated && transport->is_server)
439         {
440           DBusCredentials auth_identity;
441
442           _dbus_auth_get_identity (transport->auth, &auth_identity);
443
444           if (transport->unix_user_function != NULL)
445             {
446               /* FIXME we hold the connection lock here and should drop it */
447               if (!(* transport->unix_user_function) (transport->connection,
448                                                       auth_identity.uid,
449                                                       transport->unix_user_data))
450                 {
451                   _dbus_verbose ("Client UID %d was rejected, disconnecting\n",
452                                  auth_identity.uid);
453                   _dbus_transport_disconnect (transport);
454                   return FALSE;
455                 }
456               else
457                 {
458                   _dbus_verbose ("Client UID %d authorized\n", auth_identity.uid);
459                 }
460             }
461           else
462             {
463               DBusCredentials our_identity;
464               
465               _dbus_credentials_from_current_process (&our_identity);
466               
467               if (!_dbus_credentials_match (&our_identity,
468                                             &auth_identity))
469                 {
470                   _dbus_verbose ("Client authorized as UID %d but our UID is %d, disconnecting\n",
471                                  auth_identity.uid, our_identity.uid);
472                   _dbus_transport_disconnect (transport);
473                   return FALSE;
474                 }
475               else
476                 {
477                   _dbus_verbose ("Client authorized as UID %d matching our UID %d\n",
478                                  auth_identity.uid, our_identity.uid);
479                 }
480             }
481         }
482
483       transport->authenticated = maybe_authenticated;
484       
485       return transport->authenticated;
486     }
487 }
488
489 /**
490  * Gets the address of a transport. It will be
491  * #NULL for a server-side transport.
492  *
493  * @param transport the transport
494  * @returns transport's address
495  */
496 const char*
497 _dbus_transport_get_address (DBusTransport *transport)
498 {
499   return transport->address;
500 }
501
502 /**
503  * Handles a watch by reading data, writing data, or disconnecting
504  * the transport, as appropriate for the given condition.
505  *
506  * @param transport the transport.
507  * @param watch the watch.
508  * @param condition the current state of the watched file descriptor.
509  * @returns #FALSE if not enough memory to fully handle the watch
510  */
511 dbus_bool_t
512 _dbus_transport_handle_watch (DBusTransport           *transport,
513                               DBusWatch               *watch,
514                               unsigned int             condition)
515 {
516   dbus_bool_t retval;
517   
518   _dbus_assert (transport->vtable->handle_watch != NULL);
519
520   if (transport->disconnected)
521     return TRUE;
522
523   if (dbus_watch_get_fd (watch) < 0)
524     {
525       _dbus_warn ("Tried to handle an invalidated watch; this watch should have been removed\n");
526       return TRUE;
527     }
528   
529   _dbus_watch_sanitize_condition (watch, &condition);
530
531   _dbus_transport_ref (transport);
532   _dbus_watch_ref (watch);
533   retval = (* transport->vtable->handle_watch) (transport, watch, condition);
534   _dbus_watch_unref (watch);
535   _dbus_transport_unref (transport);
536
537   return retval;
538 }
539
540 /**
541  * Sets the connection using this transport. Allows the transport
542  * to add watches to the connection, queue incoming messages,
543  * and pull outgoing messages.
544  *
545  * @param transport the transport.
546  * @param connection the connection.
547  * @returns #FALSE if not enough memory
548  */
549 dbus_bool_t
550 _dbus_transport_set_connection (DBusTransport  *transport,
551                                 DBusConnection *connection)
552 {
553   _dbus_assert (transport->vtable->connection_set != NULL);
554   _dbus_assert (transport->connection == NULL);
555   
556   transport->connection = connection;
557
558   _dbus_transport_ref (transport);
559   if (!(* transport->vtable->connection_set) (transport))
560     transport->connection = NULL;
561   _dbus_transport_unref (transport);
562
563   return transport->connection != NULL;
564 }
565
566 /**
567  * Notifies the transport when the outgoing message queue goes from
568  * empty to non-empty or vice versa. Typically causes the transport to
569  * add or remove its DBUS_WATCH_WRITABLE watch.
570  *
571  * @param transport the transport.
572  * @param queue_length the length of the outgoing message queue.
573  *
574  */
575 void
576 _dbus_transport_messages_pending (DBusTransport  *transport,
577                                   int             queue_length)
578 {
579   _dbus_assert (transport->vtable->messages_pending != NULL);
580
581   if (transport->disconnected)
582     return;
583
584   transport->messages_need_sending = queue_length > 0;
585
586   _dbus_transport_ref (transport);
587   (* transport->vtable->messages_pending) (transport,
588                                            queue_length);
589   _dbus_transport_unref (transport);
590 }
591
592 /**
593  * Performs a single poll()/select() on the transport's file
594  * descriptors and then reads/writes data as appropriate,
595  * queueing incoming messages and sending outgoing messages.
596  * This is the backend for _dbus_connection_do_iteration().
597  * See _dbus_connection_do_iteration() for full details.
598  *
599  * @param transport the transport.
600  * @param flags indicates whether to read or write, and whether to block.
601  * @param timeout_milliseconds if blocking, timeout or -1 for no timeout.
602  */
603 void
604 _dbus_transport_do_iteration (DBusTransport  *transport,
605                               unsigned int    flags,
606                               int             timeout_milliseconds)
607 {
608   _dbus_assert (transport->vtable->do_iteration != NULL);
609
610   _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
611                  flags, timeout_milliseconds, !transport->disconnected);
612   
613   if ((flags & (DBUS_ITERATION_DO_WRITING |
614                 DBUS_ITERATION_DO_READING)) == 0)
615     return; /* Nothing to do */
616
617   if (transport->disconnected)
618     return;
619
620   _dbus_transport_ref (transport);
621   (* transport->vtable->do_iteration) (transport, flags,
622                                        timeout_milliseconds);
623   _dbus_transport_unref (transport);
624 }
625
626 static dbus_bool_t
627 recover_unused_bytes (DBusTransport *transport)
628 {
629   if (_dbus_auth_do_work (transport->auth) != DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES)
630     return TRUE;
631   
632   if (_dbus_auth_needs_decoding (transport->auth))
633     {
634       DBusString plaintext;
635       const DBusString *encoded;
636       DBusString *buffer;
637       int orig_len;
638       
639       if (!_dbus_string_init (&plaintext))
640         goto nomem;
641       
642       _dbus_auth_get_unused_bytes (transport->auth,
643                                    &encoded);
644
645       if (!_dbus_auth_decode_data (transport->auth,
646                                    encoded, &plaintext))
647         {
648           _dbus_string_free (&plaintext);
649           goto nomem;
650         }
651       
652       _dbus_message_loader_get_buffer (transport->loader,
653                                        &buffer);
654       
655       orig_len = _dbus_string_get_length (buffer);
656       
657       if (!_dbus_string_move (&plaintext, 0, buffer,
658                               orig_len))
659         {
660           _dbus_string_free (&plaintext);
661           goto nomem;
662         }
663       
664       _dbus_verbose (" %d unused bytes sent to message loader\n", 
665                      _dbus_string_get_length (buffer) -
666                      orig_len);
667       
668       _dbus_message_loader_return_buffer (transport->loader,
669                                           buffer,
670                                           _dbus_string_get_length (buffer) -
671                                           orig_len);
672
673       _dbus_auth_delete_unused_bytes (transport->auth);
674       
675       _dbus_string_free (&plaintext);
676     }
677   else
678     {
679       const DBusString *bytes;
680       DBusString *buffer;
681       int orig_len;
682       dbus_bool_t succeeded;
683
684       _dbus_message_loader_get_buffer (transport->loader,
685                                        &buffer);
686                 
687       orig_len = _dbus_string_get_length (buffer);
688                 
689       _dbus_auth_get_unused_bytes (transport->auth,
690                                    &bytes);
691
692       succeeded = TRUE;
693       if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
694         succeeded = FALSE;
695       
696       _dbus_verbose (" %d unused bytes sent to message loader\n", 
697                      _dbus_string_get_length (buffer) -
698                      orig_len);
699       
700       _dbus_message_loader_return_buffer (transport->loader,
701                                           buffer,
702                                           _dbus_string_get_length (buffer) -
703                                           orig_len);
704
705       if (succeeded)
706         _dbus_auth_delete_unused_bytes (transport->auth);
707       else
708         goto nomem;
709     }
710
711   return TRUE;
712
713  nomem:
714   _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
715   return FALSE;
716 }
717
718 /**
719  * Reports our current dispatch status (whether there's buffered
720  * data to be queued as messages, or not, or we need memory).
721  *
722  * @param transport the transport
723  * @returns current status
724  */
725 DBusDispatchStatus
726 _dbus_transport_get_dispatch_status (DBusTransport *transport)
727 {
728   if (_dbus_counter_get_value (transport->live_messages_size) >= transport->max_live_messages_size)
729     return DBUS_DISPATCH_COMPLETE; /* complete for now */
730
731   if (!_dbus_transport_get_is_authenticated (transport))
732     {
733       switch (_dbus_auth_do_work (transport->auth))
734         {
735         case DBUS_AUTH_STATE_WAITING_FOR_MEMORY:
736           return DBUS_DISPATCH_NEED_MEMORY;
737         case DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES:
738           if (!recover_unused_bytes (transport))
739             return DBUS_DISPATCH_NEED_MEMORY;
740           break;
741         default:
742           break;
743         }
744     }
745   
746   if (!_dbus_message_loader_queue_messages (transport->loader))
747     return DBUS_DISPATCH_NEED_MEMORY;
748
749   if (_dbus_message_loader_peek_message (transport->loader) != NULL)
750     return DBUS_DISPATCH_DATA_REMAINS;
751   else
752     return DBUS_DISPATCH_COMPLETE;
753 }
754
755 /**
756  * Processes data we've read while handling a watch, potentially
757  * converting some of it to messages and queueing those messages on
758  * the connection.
759  *
760  * @param transport the transport
761  * @returns #TRUE if we had enough memory to queue all messages
762  */
763 dbus_bool_t
764 _dbus_transport_queue_messages (DBusTransport *transport)
765 {
766   DBusDispatchStatus status;
767   
768   /* Queue any messages */
769   while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
770     {
771       DBusMessage *message;
772       DBusList *link;
773
774       link = _dbus_message_loader_pop_message_link (transport->loader);
775       _dbus_assert (link != NULL);
776       
777       message = link->data;
778       
779       _dbus_verbose ("queueing received message %p\n", message);
780
781       _dbus_message_add_size_counter (message, transport->live_messages_size);
782
783       /* pass ownership of link and message ref to connection */
784       _dbus_connection_queue_received_message_link (transport->connection,
785                                                     link);
786     }
787
788   if (_dbus_message_loader_get_is_corrupted (transport->loader))
789     {
790       _dbus_verbose ("Corrupted message stream, disconnecting\n");
791       _dbus_transport_disconnect (transport);
792     }
793
794   return status != DBUS_DISPATCH_NEED_MEMORY;
795 }
796
797 /**
798  * See dbus_connection_set_max_message_size().
799  *
800  * @param transport the transport
801  * @param size the max size of a single message
802  */
803 void
804 _dbus_transport_set_max_message_size (DBusTransport  *transport,
805                                       long            size)
806 {
807   _dbus_message_loader_set_max_message_size (transport->loader, size);
808 }
809
810 /**
811  * See dbus_connection_get_max_message_size().
812  *
813  * @param transport the transport
814  * @returns max message size
815  */
816 long
817 _dbus_transport_get_max_message_size (DBusTransport  *transport)
818 {
819   return _dbus_message_loader_get_max_message_size (transport->loader);
820 }
821
822 /**
823  * See dbus_connection_set_max_live_messages_size().
824  *
825  * @param transport the transport
826  * @param size the max size of all incoming messages
827  */
828 void
829 _dbus_transport_set_max_live_messages_size (DBusTransport  *transport,
830                                             long            size)
831 {
832   transport->max_live_messages_size = size;
833   _dbus_counter_set_notify (transport->live_messages_size,
834                             transport->max_live_messages_size,
835                             live_messages_size_notify,
836                             transport);
837 }
838
839
840 /**
841  * See dbus_connection_get_max_live_messages_size().
842  *
843  * @param transport the transport
844  * @returns max bytes for all live messages
845  */
846 long
847 _dbus_transport_get_max_live_messages_size (DBusTransport  *transport)
848 {
849   return transport->max_live_messages_size;
850 }
851
852 /**
853  * See dbus_connection_get_unix_user().
854  *
855  * @param transport the transport
856  * @param uid return location for the user ID
857  * @returns #TRUE if uid is filled in with a valid user ID
858  */
859 dbus_bool_t
860 _dbus_transport_get_unix_user (DBusTransport *transport,
861                                unsigned long *uid)
862 {
863   DBusCredentials auth_identity;
864
865   *uid = _DBUS_INT_MAX; /* better than some root or system user in
866                          * case of bugs in the caller. Caller should
867                          * never use this value on purpose, however.
868                          */
869   
870   if (!transport->authenticated)
871     return FALSE;
872   
873   _dbus_auth_get_identity (transport->auth, &auth_identity);
874
875   if (auth_identity.uid >= 0)
876     {
877       *uid = auth_identity.uid;
878       return TRUE;
879     }
880   else
881     return FALSE;
882 }
883
884 /**
885  * See dbus_connection_set_unix_user_function().
886  *
887  * @param transport the transport
888  * @param function the predicate
889  * @param data data to pass to the predicate
890  * @param free_data_function function to free the data
891  * @param old_data the old user data to be freed
892  * @param old_free_data_function old free data function to free it with
893  */
894 void
895 _dbus_transport_set_unix_user_function (DBusTransport             *transport,
896                                         DBusAllowUnixUserFunction  function,
897                                         void                      *data,
898                                         DBusFreeFunction           free_data_function,
899                                         void                     **old_data,
900                                         DBusFreeFunction          *old_free_data_function)
901 {  
902   *old_data = transport->unix_user_data;
903   *old_free_data_function = transport->free_unix_user_data;
904
905   transport->unix_user_function = function;
906   transport->unix_user_data = data;
907   transport->free_unix_user_data = free_data_function;
908 }
909
910 /** @} */