2003-04-06 Havoc Pennington <hp@pobox.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           const char *tmpdir = dbus_address_entry_get_value (entries[i], "tmpdir");
239
240           if (tmpdir != NULL)
241             {
242               address_problem_other = "cannot use the \"tmpdir\" option for an address to connect to, only in an address to listen on";
243               goto bad_address;
244             }
245           
246           if (path == NULL)
247             {
248               address_problem_type = "unix";
249               address_problem_field = "path";              
250               goto bad_address;
251             }
252
253           transport = _dbus_transport_new_for_domain_socket (path, error);
254         }
255       else if (strcmp (method, "tcp") == 0)
256         {
257           const char *host = dbus_address_entry_get_value (entries[i], "host");
258           const char *port = dbus_address_entry_get_value (entries[i], "port");
259           DBusString  str;
260           long lport;
261           dbus_bool_t sresult;
262           
263           if (port == NULL)
264             {
265               address_problem_type = "tcp";
266               address_problem_field = "port";
267               goto bad_address;
268             }
269
270           _dbus_string_init_const (&str, port);
271           sresult = _dbus_string_parse_int (&str, 0, &lport, NULL);
272           _dbus_string_free (&str);
273           
274           if (sresult == FALSE || lport <= 0 || lport > 65535)
275             {
276               address_problem_other = "Port is not an integer between 0 and 65535";
277               goto bad_address;
278             }
279           
280           transport = _dbus_transport_new_for_tcp_socket (host, lport, error);
281         }
282 #ifdef DBUS_BUILD_TESTS
283       else if (strcmp (method, "debug") == 0)
284         {
285           const char *name = dbus_address_entry_get_value (entries[i], "name");
286
287           if (name == NULL)
288             {
289               address_problem_type = "debug";
290               address_problem_field = "name";
291               goto bad_address;
292             }
293
294           transport = _dbus_transport_debug_client_new (name, error);
295         }
296       else if (strcmp (method, "debug-pipe") == 0)
297         {
298           const char *name = dbus_address_entry_get_value (entries[i], "name");
299
300           if (name == NULL)
301             {
302               address_problem_type = "debug-pipe";
303               address_problem_field = "name";
304               goto bad_address;
305             }
306
307           transport = _dbus_transport_debug_pipe_new (name, error);
308         }
309 #endif
310       else
311         {
312           address_problem_other = "Unknown address type (examples of valid types are \"unix\" and \"tcp\")";
313           goto bad_address;
314         }
315
316       if (transport)
317         break;    
318     }
319
320   dbus_address_entries_free (entries);
321   return transport;
322
323  bad_address:
324   dbus_address_entries_free (entries);
325
326   if (address_problem_type != NULL)
327     dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
328                     "Address of type %s was missing argument %s",
329                     address_problem_type, address_problem_field);
330   else
331     dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
332                     "Could not parse address: %s",
333                     address_problem_other);
334
335   return NULL;
336 }
337
338 /**
339  * Increments the reference count for the transport.
340  *
341  * @param transport the transport.
342  */
343 void
344 _dbus_transport_ref (DBusTransport *transport)
345 {
346   _dbus_assert (transport->refcount > 0);
347   
348   transport->refcount += 1;
349 }
350
351 /**
352  * Decrements the reference count for the transport.
353  * Disconnects and finalizes the transport if
354  * the reference count reaches zero.
355  *
356  * @param transport the transport.
357  */
358 void
359 _dbus_transport_unref (DBusTransport *transport)
360 {
361   _dbus_assert (transport != NULL);
362   _dbus_assert (transport->refcount > 0);
363
364   transport->refcount -= 1;
365   if (transport->refcount == 0)
366     {
367       _dbus_assert (transport->vtable->finalize != NULL);
368       
369       (* transport->vtable->finalize) (transport);
370     }
371 }
372
373 /**
374  * Closes our end of the connection to a remote application. Further
375  * attempts to use this transport will fail. Only the first call to
376  * _dbus_transport_disconnect() will have an effect.
377  *
378  * @param transport the transport.
379  * 
380  */
381 void
382 _dbus_transport_disconnect (DBusTransport *transport)
383 {
384   _dbus_assert (transport->vtable->disconnect != NULL);
385
386   if (transport->disconnected)
387     return;
388
389   (* transport->vtable->disconnect) (transport);
390   
391   transport->disconnected = TRUE;
392
393   if (transport->connection)
394     _dbus_connection_notify_disconnected (transport->connection);
395 }
396
397 /**
398  * Returns #TRUE if the transport has not been disconnected.
399  * Disconnection can result from _dbus_transport_disconnect()
400  * or because the server drops its end of the connection.
401  *
402  * @param transport the transport.
403  * @returns whether we're connected
404  */
405 dbus_bool_t
406 _dbus_transport_get_is_connected (DBusTransport *transport)
407 {
408   return !transport->disconnected;
409 }
410
411 /**
412  * Returns #TRUE if we have been authenticated.  Will return #TRUE
413  * even if the transport is disconnected.
414  *
415  * @todo needs to drop connection->mutex when calling the unix_user_function
416  *
417  * @param transport the transport
418  * @returns whether we're authenticated
419  */
420 dbus_bool_t
421 _dbus_transport_get_is_authenticated (DBusTransport *transport)
422 {  
423   if (transport->authenticated)
424     return TRUE;
425   else
426     {
427       dbus_bool_t maybe_authenticated;
428       
429       if (transport->disconnected)
430         return FALSE;
431       
432       maybe_authenticated =
433         (!(transport->send_credentials_pending ||
434            transport->receive_credentials_pending)) &&
435         _dbus_auth_do_work (transport->auth) == DBUS_AUTH_STATE_AUTHENTICATED;
436
437       /* If we've authenticated as some identity, check that the auth
438        * identity is the same as our own identity.  In the future, we
439        * may have API allowing applications to specify how this is
440        * done, for example they may allow connection as any identity,
441        * but then impose restrictions on certain identities.
442        * Or they may give certain identities extra privileges.
443        */
444       
445       if (maybe_authenticated && transport->is_server)
446         {
447           DBusCredentials auth_identity;
448
449           _dbus_auth_get_identity (transport->auth, &auth_identity);
450
451           if (transport->unix_user_function != NULL)
452             {
453               /* FIXME we hold the connection lock here and should drop it */
454               if (!(* transport->unix_user_function) (transport->connection,
455                                                       auth_identity.uid,
456                                                       transport->unix_user_data))
457                 {
458                   _dbus_verbose ("Client UID %d was rejected, disconnecting\n",
459                                  auth_identity.uid);
460                   _dbus_transport_disconnect (transport);
461                   return FALSE;
462                 }
463               else
464                 {
465                   _dbus_verbose ("Client UID %d authorized\n", auth_identity.uid);
466                 }
467             }
468           else
469             {
470               DBusCredentials our_identity;
471               
472               _dbus_credentials_from_current_process (&our_identity);
473               
474               if (!_dbus_credentials_match (&our_identity,
475                                             &auth_identity))
476                 {
477                   _dbus_verbose ("Client authorized as UID %d but our UID is %d, disconnecting\n",
478                                  auth_identity.uid, our_identity.uid);
479                   _dbus_transport_disconnect (transport);
480                   return FALSE;
481                 }
482               else
483                 {
484                   _dbus_verbose ("Client authorized as UID %d matching our UID %d\n",
485                                  auth_identity.uid, our_identity.uid);
486                 }
487             }
488         }
489
490       transport->authenticated = maybe_authenticated;
491       
492       return transport->authenticated;
493     }
494 }
495
496 /**
497  * Gets the address of a transport. It will be
498  * #NULL for a server-side transport.
499  *
500  * @param transport the transport
501  * @returns transport's address
502  */
503 const char*
504 _dbus_transport_get_address (DBusTransport *transport)
505 {
506   return transport->address;
507 }
508
509 /**
510  * Handles a watch by reading data, writing data, or disconnecting
511  * the transport, as appropriate for the given condition.
512  *
513  * @param transport the transport.
514  * @param watch the watch.
515  * @param condition the current state of the watched file descriptor.
516  * @returns #FALSE if not enough memory to fully handle the watch
517  */
518 dbus_bool_t
519 _dbus_transport_handle_watch (DBusTransport           *transport,
520                               DBusWatch               *watch,
521                               unsigned int             condition)
522 {
523   dbus_bool_t retval;
524   
525   _dbus_assert (transport->vtable->handle_watch != NULL);
526
527   if (transport->disconnected)
528     return TRUE;
529
530   if (dbus_watch_get_fd (watch) < 0)
531     {
532       _dbus_warn ("Tried to handle an invalidated watch; this watch should have been removed\n");
533       return TRUE;
534     }
535   
536   _dbus_watch_sanitize_condition (watch, &condition);
537
538   _dbus_transport_ref (transport);
539   _dbus_watch_ref (watch);
540   retval = (* transport->vtable->handle_watch) (transport, watch, condition);
541   _dbus_watch_unref (watch);
542   _dbus_transport_unref (transport);
543
544   return retval;
545 }
546
547 /**
548  * Sets the connection using this transport. Allows the transport
549  * to add watches to the connection, queue incoming messages,
550  * and pull outgoing messages.
551  *
552  * @param transport the transport.
553  * @param connection the connection.
554  * @returns #FALSE if not enough memory
555  */
556 dbus_bool_t
557 _dbus_transport_set_connection (DBusTransport  *transport,
558                                 DBusConnection *connection)
559 {
560   _dbus_assert (transport->vtable->connection_set != NULL);
561   _dbus_assert (transport->connection == NULL);
562   
563   transport->connection = connection;
564
565   _dbus_transport_ref (transport);
566   if (!(* transport->vtable->connection_set) (transport))
567     transport->connection = NULL;
568   _dbus_transport_unref (transport);
569
570   return transport->connection != NULL;
571 }
572
573 /**
574  * Notifies the transport when the outgoing message queue goes from
575  * empty to non-empty or vice versa. Typically causes the transport to
576  * add or remove its DBUS_WATCH_WRITABLE watch.
577  *
578  * @param transport the transport.
579  * @param queue_length the length of the outgoing message queue.
580  *
581  */
582 void
583 _dbus_transport_messages_pending (DBusTransport  *transport,
584                                   int             queue_length)
585 {
586   _dbus_assert (transport->vtable->messages_pending != NULL);
587
588   if (transport->disconnected)
589     return;
590
591   transport->messages_need_sending = queue_length > 0;
592
593   _dbus_transport_ref (transport);
594   (* transport->vtable->messages_pending) (transport,
595                                            queue_length);
596   _dbus_transport_unref (transport);
597 }
598
599 /**
600  * Performs a single poll()/select() on the transport's file
601  * descriptors and then reads/writes data as appropriate,
602  * queueing incoming messages and sending outgoing messages.
603  * This is the backend for _dbus_connection_do_iteration().
604  * See _dbus_connection_do_iteration() for full details.
605  *
606  * @param transport the transport.
607  * @param flags indicates whether to read or write, and whether to block.
608  * @param timeout_milliseconds if blocking, timeout or -1 for no timeout.
609  */
610 void
611 _dbus_transport_do_iteration (DBusTransport  *transport,
612                               unsigned int    flags,
613                               int             timeout_milliseconds)
614 {
615   _dbus_assert (transport->vtable->do_iteration != NULL);
616
617   _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
618                  flags, timeout_milliseconds, !transport->disconnected);
619   
620   if ((flags & (DBUS_ITERATION_DO_WRITING |
621                 DBUS_ITERATION_DO_READING)) == 0)
622     return; /* Nothing to do */
623
624   if (transport->disconnected)
625     return;
626
627   _dbus_transport_ref (transport);
628   (* transport->vtable->do_iteration) (transport, flags,
629                                        timeout_milliseconds);
630   _dbus_transport_unref (transport);
631 }
632
633 static dbus_bool_t
634 recover_unused_bytes (DBusTransport *transport)
635 {
636   if (_dbus_auth_do_work (transport->auth) != DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES)
637     return TRUE;
638   
639   if (_dbus_auth_needs_decoding (transport->auth))
640     {
641       DBusString plaintext;
642       const DBusString *encoded;
643       DBusString *buffer;
644       int orig_len;
645       
646       if (!_dbus_string_init (&plaintext))
647         goto nomem;
648       
649       _dbus_auth_get_unused_bytes (transport->auth,
650                                    &encoded);
651
652       if (!_dbus_auth_decode_data (transport->auth,
653                                    encoded, &plaintext))
654         {
655           _dbus_string_free (&plaintext);
656           goto nomem;
657         }
658       
659       _dbus_message_loader_get_buffer (transport->loader,
660                                        &buffer);
661       
662       orig_len = _dbus_string_get_length (buffer);
663       
664       if (!_dbus_string_move (&plaintext, 0, buffer,
665                               orig_len))
666         {
667           _dbus_string_free (&plaintext);
668           goto nomem;
669         }
670       
671       _dbus_verbose (" %d unused bytes sent to message loader\n", 
672                      _dbus_string_get_length (buffer) -
673                      orig_len);
674       
675       _dbus_message_loader_return_buffer (transport->loader,
676                                           buffer,
677                                           _dbus_string_get_length (buffer) -
678                                           orig_len);
679
680       _dbus_auth_delete_unused_bytes (transport->auth);
681       
682       _dbus_string_free (&plaintext);
683     }
684   else
685     {
686       const DBusString *bytes;
687       DBusString *buffer;
688       int orig_len;
689       dbus_bool_t succeeded;
690
691       _dbus_message_loader_get_buffer (transport->loader,
692                                        &buffer);
693                 
694       orig_len = _dbus_string_get_length (buffer);
695                 
696       _dbus_auth_get_unused_bytes (transport->auth,
697                                    &bytes);
698
699       succeeded = TRUE;
700       if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
701         succeeded = FALSE;
702       
703       _dbus_verbose (" %d unused bytes sent to message loader\n", 
704                      _dbus_string_get_length (buffer) -
705                      orig_len);
706       
707       _dbus_message_loader_return_buffer (transport->loader,
708                                           buffer,
709                                           _dbus_string_get_length (buffer) -
710                                           orig_len);
711
712       if (succeeded)
713         _dbus_auth_delete_unused_bytes (transport->auth);
714       else
715         goto nomem;
716     }
717
718   return TRUE;
719
720  nomem:
721   _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
722   return FALSE;
723 }
724
725 /**
726  * Reports our current dispatch status (whether there's buffered
727  * data to be queued as messages, or not, or we need memory).
728  *
729  * @param transport the transport
730  * @returns current status
731  */
732 DBusDispatchStatus
733 _dbus_transport_get_dispatch_status (DBusTransport *transport)
734 {
735   if (_dbus_counter_get_value (transport->live_messages_size) >= transport->max_live_messages_size)
736     return DBUS_DISPATCH_COMPLETE; /* complete for now */
737
738   if (!_dbus_transport_get_is_authenticated (transport))
739     {
740       switch (_dbus_auth_do_work (transport->auth))
741         {
742         case DBUS_AUTH_STATE_WAITING_FOR_MEMORY:
743           return DBUS_DISPATCH_NEED_MEMORY;
744         case DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES:
745           if (!recover_unused_bytes (transport))
746             return DBUS_DISPATCH_NEED_MEMORY;
747           break;
748         default:
749           break;
750         }
751     }
752   
753   if (!_dbus_message_loader_queue_messages (transport->loader))
754     return DBUS_DISPATCH_NEED_MEMORY;
755
756   if (_dbus_message_loader_peek_message (transport->loader) != NULL)
757     return DBUS_DISPATCH_DATA_REMAINS;
758   else
759     return DBUS_DISPATCH_COMPLETE;
760 }
761
762 /**
763  * Processes data we've read while handling a watch, potentially
764  * converting some of it to messages and queueing those messages on
765  * the connection.
766  *
767  * @param transport the transport
768  * @returns #TRUE if we had enough memory to queue all messages
769  */
770 dbus_bool_t
771 _dbus_transport_queue_messages (DBusTransport *transport)
772 {
773   DBusDispatchStatus status;
774   
775   /* Queue any messages */
776   while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
777     {
778       DBusMessage *message;
779       DBusList *link;
780
781       link = _dbus_message_loader_pop_message_link (transport->loader);
782       _dbus_assert (link != NULL);
783       
784       message = link->data;
785       
786       _dbus_verbose ("queueing received message %p\n", message);
787
788       _dbus_message_add_size_counter (message, transport->live_messages_size);
789
790       /* pass ownership of link and message ref to connection */
791       _dbus_connection_queue_received_message_link (transport->connection,
792                                                     link);
793     }
794
795   if (_dbus_message_loader_get_is_corrupted (transport->loader))
796     {
797       _dbus_verbose ("Corrupted message stream, disconnecting\n");
798       _dbus_transport_disconnect (transport);
799     }
800
801   return status != DBUS_DISPATCH_NEED_MEMORY;
802 }
803
804 /**
805  * See dbus_connection_set_max_message_size().
806  *
807  * @param transport the transport
808  * @param size the max size of a single message
809  */
810 void
811 _dbus_transport_set_max_message_size (DBusTransport  *transport,
812                                       long            size)
813 {
814   _dbus_message_loader_set_max_message_size (transport->loader, size);
815 }
816
817 /**
818  * See dbus_connection_get_max_message_size().
819  *
820  * @param transport the transport
821  * @returns max message size
822  */
823 long
824 _dbus_transport_get_max_message_size (DBusTransport  *transport)
825 {
826   return _dbus_message_loader_get_max_message_size (transport->loader);
827 }
828
829 /**
830  * See dbus_connection_set_max_live_messages_size().
831  *
832  * @param transport the transport
833  * @param size the max size of all incoming messages
834  */
835 void
836 _dbus_transport_set_max_live_messages_size (DBusTransport  *transport,
837                                             long            size)
838 {
839   transport->max_live_messages_size = size;
840   _dbus_counter_set_notify (transport->live_messages_size,
841                             transport->max_live_messages_size,
842                             live_messages_size_notify,
843                             transport);
844 }
845
846
847 /**
848  * See dbus_connection_get_max_live_messages_size().
849  *
850  * @param transport the transport
851  * @returns max bytes for all live messages
852  */
853 long
854 _dbus_transport_get_max_live_messages_size (DBusTransport  *transport)
855 {
856   return transport->max_live_messages_size;
857 }
858
859 /**
860  * See dbus_connection_get_unix_user().
861  *
862  * @param transport the transport
863  * @param uid return location for the user ID
864  * @returns #TRUE if uid is filled in with a valid user ID
865  */
866 dbus_bool_t
867 _dbus_transport_get_unix_user (DBusTransport *transport,
868                                unsigned long *uid)
869 {
870   DBusCredentials auth_identity;
871
872   *uid = _DBUS_INT_MAX; /* better than some root or system user in
873                          * case of bugs in the caller. Caller should
874                          * never use this value on purpose, however.
875                          */
876   
877   if (!transport->authenticated)
878     return FALSE;
879   
880   _dbus_auth_get_identity (transport->auth, &auth_identity);
881
882   if (auth_identity.uid >= 0)
883     {
884       *uid = auth_identity.uid;
885       return TRUE;
886     }
887   else
888     return FALSE;
889 }
890
891 /**
892  * See dbus_connection_set_unix_user_function().
893  *
894  * @param transport the transport
895  * @param function the predicate
896  * @param data data to pass to the predicate
897  * @param free_data_function function to free the data
898  * @param old_data the old user data to be freed
899  * @param old_free_data_function old free data function to free it with
900  */
901 void
902 _dbus_transport_set_unix_user_function (DBusTransport             *transport,
903                                         DBusAllowUnixUserFunction  function,
904                                         void                      *data,
905                                         DBusFreeFunction           free_data_function,
906                                         void                     **old_data,
907                                         DBusFreeFunction          *old_free_data_function)
908 {  
909   *old_data = transport->unix_user_data;
910   *old_free_data_function = transport->free_unix_user_data;
911
912   transport->unix_user_function = function;
913   transport->unix_user_data = data;
914   transport->free_unix_user_data = free_data_function;
915 }
916
917 /**
918  * Sets the SASL authentication mechanisms supported by this transport.
919  *
920  * @param transport the transport
921  * @param mechanisms the #NULL-terminated array of mechanisms
922  *
923  * @returns #FALSE if no memory
924  */
925 dbus_bool_t
926 _dbus_transport_set_auth_mechanisms (DBusTransport  *transport,
927                                      const char    **mechanisms)
928 {
929   return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
930 }
931
932
933 /** @} */