dbus-transport.c 24.1 KB
Newer Older
1 2 3
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-transport.c DBusTransport object (internal to D-BUS implementation)
 *
4
 * Copyright (C) 2002, 2003  Red Hat Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 * Licensed under the Academic Free License version 1.2
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include "dbus-transport-protected.h"
#include "dbus-transport-unix.h"
#include "dbus-connection-internal.h"
27
#include "dbus-watch.h"
28
#include "dbus-auth.h"
29
#include "dbus-address.h"
30 31
#ifdef DBUS_BUILD_TESTS
#include "dbus-transport-debug.h"
32
#include "dbus-server-debug-pipe.h"
33
#endif
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

/**
 * @defgroup DBusTransport DBusTransport object
 * @ingroup  DBusInternals
 * @brief "Backend" for a DBusConnection.
 *
 * Types and functions related to DBusTransport.  A transport is an
 * abstraction that can send and receive data via various kinds of
 * network connections or other IPC mechanisms.
 * 
 * @{
 */

/**
 * @typedef DBusTransport
 *
 * Opaque object representing a way message stream.
 * DBusTransport abstracts various kinds of actual
 * transport mechanism, such as different network protocols,
 * or encryption schemes.
 */

56 57 58 59 60 61
static void
live_messages_size_notify (DBusCounter *counter,
                           void        *user_data)
{
  DBusTransport *transport = user_data;

62
  _dbus_transport_ref (transport);
63 64 65 66 67 68 69 70 71 72 73 74

#if 0
  _dbus_verbose ("Counter value is now %d\n",
                 (int) _dbus_counter_get_value (counter));
#endif
  
  /* disable or re-enable the read watch for the transport if
   * required.
   */
  if (* transport->vtable->live_messages_changed)
    (* transport->vtable->live_messages_changed) (transport);

75
  _dbus_transport_unref (transport);
76
}
77

78 79 80 81 82 83
/**
 * Initializes the base class members of DBusTransport.
 * Chained up to by subclasses in their constructor.
 *
 * @param transport the transport being created.
 * @param vtable the subclass vtable.
84
 * @param server #TRUE if this transport is on the server side of a connection
85 86 87 88
 * @returns #TRUE on success.
 */
dbus_bool_t
_dbus_transport_init_base (DBusTransport             *transport,
89 90
                           const DBusTransportVTable *vtable,
                           dbus_bool_t                server)
91 92
{
  DBusMessageLoader *loader;
93
  DBusAuth *auth;
94
  DBusCounter *counter;
95
  
96 97 98
  loader = _dbus_message_loader_new ();
  if (loader == NULL)
    return FALSE;
99
  
100 101 102 103 104 105 106 107 108
  if (server)
    auth = _dbus_auth_server_new ();
  else
    auth = _dbus_auth_client_new ();
  if (auth == NULL)
    {
      _dbus_message_loader_unref (loader);
      return FALSE;
    }
109 110 111 112 113 114 115 116

  counter = _dbus_counter_new ();
  if (counter == NULL)
    {
      _dbus_auth_unref (auth);
      _dbus_message_loader_unref (loader);
      return FALSE;
    }
117 118 119 120
  
  transport->refcount = 1;
  transport->vtable = vtable;
  transport->loader = loader;
121
  transport->auth = auth;
122
  transport->live_messages_size = counter;
123 124 125
  transport->authenticated = FALSE;
  transport->messages_need_sending = FALSE;
  transport->disconnected = FALSE;
126 127 128
  transport->send_credentials_pending = !server;
  transport->receive_credentials_pending = server;
  transport->is_server = server;
129

130 131 132 133
  transport->unix_user_function = NULL;
  transport->unix_user_data = NULL;
  transport->free_unix_user_data = NULL;
  
134 135 136 137
  /* Try to default to something that won't totally hose the system,
   * but doesn't impose too much of a limitation.
   */
  transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
138 139 140 141
  
  transport->credentials.pid = -1;
  transport->credentials.uid = -1;
  transport->credentials.gid = -1;
142 143 144 145 146

  _dbus_counter_set_notify (transport->live_messages_size,
                            transport->max_live_messages_size,
                            live_messages_size_notify,
                            transport);
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
  
  return TRUE;
}

/**
 * Finalizes base class members of DBusTransport.
 * Chained up to from subclass finalizers.
 *
 * @param transport the transport.
 */
void
_dbus_transport_finalize_base (DBusTransport *transport)
{
  if (!transport->disconnected)
    _dbus_transport_disconnect (transport);
162 163 164

  if (transport->free_unix_user_data != NULL)
    (* transport->free_unix_user_data) (transport->unix_user_data);
165
  
166
  _dbus_message_loader_unref (transport->loader);
167
  _dbus_auth_unref (transport->auth);
168 169 170
  _dbus_counter_set_notify (transport->live_messages_size,
                            0, NULL, NULL);
  _dbus_counter_unref (transport->live_messages_size);
171 172 173
}

/**
174 175
 * Opens a new transport for the given address.  (This opens a
 * client-side-of-the-connection transport.)
176
 *
177 178
 * @todo error messages on bad address could really be better.
 * DBusResultCode is a bit limiting here.
179 180 181 182 183 184 185 186 187 188
 * 
 * @param address the address.
 * @param result location to store reason for failure.
 * @returns new transport of #NULL on failure.
 */
DBusTransport*
_dbus_transport_open (const char     *address,
                      DBusResultCode *result)
{
  DBusTransport *transport;
189 190
  DBusAddressEntry **entries;
  int len, i;
191
  
192 193
  if (!dbus_parse_address (address, &entries, &len, result))
    return NULL;
194

195 196 197 198 199 200 201 202 203 204 205 206 207 208
  transport = NULL;
  
  for (i = 0; i < len; i++)
    {
      const char *method = dbus_address_entry_get_method (entries[i]);

      if (strcmp (method, "unix") == 0)
	{
	  const char *path = dbus_address_entry_get_value (entries[i], "path");

	  if (path == NULL)
	    goto bad_address;

	  transport = _dbus_transport_new_for_domain_socket (path, FALSE, result);
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
	}
      else if (strcmp (method, "tcp") == 0)
	{
	  const char *host = dbus_address_entry_get_value (entries[i], "host");
          const char *port = dbus_address_entry_get_value (entries[i], "port");
          DBusString  str;
          long lport;
          dbus_bool_t sresult;
          
	  if (port == NULL)
	    goto bad_address;

          _dbus_string_init_const (&str, port);
          sresult = _dbus_string_parse_int (&str, 0, &lport, NULL);
          _dbus_string_free (&str);
          
          if (sresult == FALSE || lport <= 0 || lport > 65535)
            goto bad_address;
          
	  transport = _dbus_transport_new_for_tcp_socket (host, lport, FALSE, result);
	}
230
#ifdef DBUS_BUILD_TESTS
231 232 233 234 235 236 237 238 239
      else if (strcmp (method, "debug") == 0)
	{
	  const char *name = dbus_address_entry_get_value (entries[i], "name");

	  if (name == NULL)
	    goto bad_address;

	  transport = _dbus_transport_debug_client_new (name, result);
	}
240 241 242 243 244 245 246 247 248 249
      else if (strcmp (method, "debug-pipe") == 0)
	{
	  const char *name = dbus_address_entry_get_value (entries[i], "name");

	  if (name == NULL)
	    goto bad_address;

	  transport = _dbus_transport_debug_pipe_new (name, result);
	}
#endif
250 251 252 253 254 255 256 257
      else
	goto bad_address;

      if (transport)
	break;	  
    }
  
  dbus_address_entries_free (entries);
258
  return transport;
259 260 261 262 263 264

 bad_address:
  dbus_address_entries_free (entries);
  dbus_set_result (result, DBUS_RESULT_BAD_ADDRESS);

  return NULL;
265 266 267 268 269 270 271 272 273 274
}

/**
 * Increments the reference count for the transport.
 *
 * @param transport the transport.
 */
void
_dbus_transport_ref (DBusTransport *transport)
{
275 276
  _dbus_assert (transport->refcount > 0);
  
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
  transport->refcount += 1;
}

/**
 * Decrements the reference count for the transport.
 * Disconnects and finalizes the transport if
 * the reference count reaches zero.
 *
 * @param transport the transport.
 */
void
_dbus_transport_unref (DBusTransport *transport)
{
  _dbus_assert (transport != NULL);
  _dbus_assert (transport->refcount > 0);

  transport->refcount -= 1;
  if (transport->refcount == 0)
    {
      _dbus_assert (transport->vtable->finalize != NULL);
      
      (* transport->vtable->finalize) (transport);
    }
}

/**
 * Closes our end of the connection to a remote application. Further
 * attempts to use this transport will fail. Only the first call to
 * _dbus_transport_disconnect() will have an effect.
 *
 * @param transport the transport.
 * 
 */
void
_dbus_transport_disconnect (DBusTransport *transport)
{
  _dbus_assert (transport->vtable->disconnect != NULL);

  if (transport->disconnected)
    return;
317

318
  (* transport->vtable->disconnect) (transport);
319
  
320
  transport->disconnected = TRUE;
321

322 323
  if (transport->connection)
    _dbus_connection_notify_disconnected (transport->connection);
324 325 326 327 328 329 330 331
}

/**
 * Returns #TRUE if the transport has not been disconnected.
 * Disconnection can result from _dbus_transport_disconnect()
 * or because the server drops its end of the connection.
 *
 * @param transport the transport.
332
 * @returns whether we're connected
333 334 335 336 337 338 339
 */
dbus_bool_t
_dbus_transport_get_is_connected (DBusTransport *transport)
{
  return !transport->disconnected;
}

340 341 342 343
/**
 * Returns #TRUE if we have been authenticated.  Will return #TRUE
 * even if the transport is disconnected.
 *
344 345
 * @todo needs to drop connection->mutex when calling the unix_user_function
 *
346 347 348 349 350 351 352 353 354 355
 * @param transport the transport
 * @returns whether we're authenticated
 */
dbus_bool_t
_dbus_transport_get_is_authenticated (DBusTransport *transport)
{  
  if (transport->authenticated)
    return TRUE;
  else
    {
356 357 358
      if (transport->disconnected)
        return FALSE;
      
359
      transport->authenticated =
360 361
        (!(transport->send_credentials_pending ||
           transport->receive_credentials_pending)) &&
362 363
        _dbus_auth_do_work (transport->auth) == DBUS_AUTH_STATE_AUTHENTICATED;

364 365 366 367 368 369 370 371 372 373 374 375 376
      /* If we've authenticated as some identity, check that the auth
       * identity is the same as our own identity.  In the future, we
       * may have API allowing applications to specify how this is
       * done, for example they may allow connection as any identity,
       * but then impose restrictions on certain identities.
       * Or they may give certain identities extra privileges.
       */
      
      if (transport->authenticated && transport->is_server)
        {
          DBusCredentials auth_identity;

          _dbus_auth_get_identity (transport->auth, &auth_identity);
377 378

          if (transport->unix_user_function != NULL)
379
            {
380 381 382 383 384 385 386 387 388 389 390 391 392 393
              /* FIXME we hold the connection lock here and should drop it */
              if (!(* transport->unix_user_function) (transport->connection,
                                                      auth_identity.uid,
                                                      transport->unix_user_data))
                {
                  _dbus_verbose ("Client UID %d was rejected, disconnecting\n",
                                 auth_identity.uid);
                  _dbus_transport_disconnect (transport);
                  return FALSE;
                }
              else
                {
                  _dbus_verbose ("Client UID %d authorized\n", auth_identity.uid);
                }
394 395 396
            }
          else
            {
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
              DBusCredentials our_identity;
              
              _dbus_credentials_from_current_process (&our_identity);
              
              if (!_dbus_credentials_match (&our_identity,
                                            &auth_identity))
                {
                  _dbus_verbose ("Client authorized as UID %d but our UID is %d, disconnecting\n",
                                 auth_identity.uid, our_identity.uid);
                  _dbus_transport_disconnect (transport);
                  return FALSE;
                }
              else
                {
                  _dbus_verbose ("Client authorized as UID %d matching our UID %d\n",
                                 auth_identity.uid, our_identity.uid);
                }
414 415 416
            }
        }
      
417 418 419 420
      return transport->authenticated;
    }
}

421 422 423 424 425 426 427
/**
 * Handles a watch by reading data, writing data, or disconnecting
 * the transport, as appropriate for the given condition.
 *
 * @param transport the transport.
 * @param watch the watch.
 * @param condition the current state of the watched file descriptor.
428
 * @returns #FALSE if not enough memory to fully handle the watch
429
 */
430
dbus_bool_t
431 432 433 434
_dbus_transport_handle_watch (DBusTransport           *transport,
                              DBusWatch               *watch,
                              unsigned int             condition)
{
435 436
  dbus_bool_t retval;
  
437 438 439
  _dbus_assert (transport->vtable->handle_watch != NULL);

  if (transport->disconnected)
440
    return TRUE;
441

442 443 444
  if (dbus_watch_get_fd (watch) < 0)
    {
      _dbus_warn ("Tried to handle an invalidated watch; this watch should have been removed\n");
445
      return TRUE;
446
    }
447
  
448 449
  _dbus_watch_sanitize_condition (watch, &condition);

450
  _dbus_transport_ref (transport);
451
  _dbus_watch_ref (watch);
452
  retval = (* transport->vtable->handle_watch) (transport, watch, condition);
453
  _dbus_watch_unref (watch);
454
  _dbus_transport_unref (transport);
455 456

  return retval;
457 458 459 460 461 462 463 464 465
}

/**
 * Sets the connection using this transport. Allows the transport
 * to add watches to the connection, queue incoming messages,
 * and pull outgoing messages.
 *
 * @param transport the transport.
 * @param connection the connection.
466
 * @returns #FALSE if not enough memory
467
 */
468
dbus_bool_t
469 470 471 472 473 474 475 476
_dbus_transport_set_connection (DBusTransport  *transport,
                                DBusConnection *connection)
{
  _dbus_assert (transport->vtable->connection_set != NULL);
  _dbus_assert (transport->connection == NULL);
  
  transport->connection = connection;

477
  _dbus_transport_ref (transport);
478 479
  if (!(* transport->vtable->connection_set) (transport))
    transport->connection = NULL;
480
  _dbus_transport_unref (transport);
481 482

  return transport->connection != NULL;
483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
}

/**
 * Notifies the transport when the outgoing message queue goes from
 * empty to non-empty or vice versa. Typically causes the transport to
 * add or remove its DBUS_WATCH_WRITABLE watch.
 *
 * @param transport the transport.
 * @param queue_length the length of the outgoing message queue.
 *
 */
void
_dbus_transport_messages_pending (DBusTransport  *transport,
                                  int             queue_length)
{
  _dbus_assert (transport->vtable->messages_pending != NULL);

  if (transport->disconnected)
501
    return;
502 503 504

  transport->messages_need_sending = queue_length > 0;

505
  _dbus_transport_ref (transport);
506 507
  (* transport->vtable->messages_pending) (transport,
                                           queue_length);
508
  _dbus_transport_unref (transport);
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528
}

/**
 * Performs a single poll()/select() on the transport's file
 * descriptors and then reads/writes data as appropriate,
 * queueing incoming messages and sending outgoing messages.
 * This is the backend for _dbus_connection_do_iteration().
 * See _dbus_connection_do_iteration() for full details.
 *
 * @param transport the transport.
 * @param flags indicates whether to read or write, and whether to block.
 * @param timeout_milliseconds if blocking, timeout or -1 for no timeout.
 */
void
_dbus_transport_do_iteration (DBusTransport  *transport,
                              unsigned int    flags,
                              int             timeout_milliseconds)
{
  _dbus_assert (transport->vtable->do_iteration != NULL);

529 530 531
  _dbus_verbose ("Transport iteration flags 0x%x timeout %d connected = %d\n",
                 flags, timeout_milliseconds, !transport->disconnected);
  
532 533 534 535 536
  if ((flags & (DBUS_ITERATION_DO_WRITING |
                DBUS_ITERATION_DO_READING)) == 0)
    return; /* Nothing to do */

  if (transport->disconnected)
537
    return;
538

539
  _dbus_transport_ref (transport);
540 541
  (* transport->vtable->do_iteration) (transport, flags,
                                       timeout_milliseconds);
542
  _dbus_transport_unref (transport);
543 544
}

545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
static dbus_bool_t
recover_unused_bytes (DBusTransport *transport)
{
  if (_dbus_auth_do_work (transport->auth) != DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES)
    return TRUE;
  
  if (_dbus_auth_needs_decoding (transport->auth))
    {
      DBusString plaintext;
      const DBusString *encoded;
      DBusString *buffer;
      int orig_len;
      
      if (!_dbus_string_init (&plaintext, _DBUS_INT_MAX))
        goto nomem;
      
      _dbus_auth_get_unused_bytes (transport->auth,
                                   &encoded);

      if (!_dbus_auth_decode_data (transport->auth,
                                   encoded, &plaintext))
        {
          _dbus_string_free (&plaintext);
          goto nomem;
        }
      
      _dbus_message_loader_get_buffer (transport->loader,
                                       &buffer);
      
      orig_len = _dbus_string_get_length (buffer);
      
      if (!_dbus_string_move (&plaintext, 0, buffer,
                              orig_len))
        {
          _dbus_string_free (&plaintext);
          goto nomem;
        }
      
      _dbus_verbose (" %d unused bytes sent to message loader\n", 
                     _dbus_string_get_length (buffer) -
                     orig_len);
      
      _dbus_message_loader_return_buffer (transport->loader,
                                          buffer,
                                          _dbus_string_get_length (buffer) -
                                          orig_len);

      _dbus_auth_delete_unused_bytes (transport->auth);
      
      _dbus_string_free (&plaintext);
    }
  else
    {
      const DBusString *bytes;
      DBusString *buffer;
      int orig_len;
      dbus_bool_t succeeded;

      _dbus_message_loader_get_buffer (transport->loader,
                                       &buffer);
                
      orig_len = _dbus_string_get_length (buffer);
                
      _dbus_auth_get_unused_bytes (transport->auth,
                                   &bytes);

      succeeded = TRUE;
      if (!_dbus_string_copy (bytes, 0, buffer, _dbus_string_get_length (buffer)))
        succeeded = FALSE;
      
      _dbus_verbose (" %d unused bytes sent to message loader\n", 
                     _dbus_string_get_length (buffer) -
                     orig_len);
      
      _dbus_message_loader_return_buffer (transport->loader,
                                          buffer,
                                          _dbus_string_get_length (buffer) -
                                          orig_len);

      if (succeeded)
        _dbus_auth_delete_unused_bytes (transport->auth);
      else
        goto nomem;
    }

  return TRUE;

 nomem:
  _dbus_verbose ("Not enough memory to transfer unused bytes from auth conversation\n");
  return FALSE;
}

637 638 639 640 641 642 643 644 645 646 647 648 649
/**
 * Reports our current dispatch status (whether there's buffered
 * data to be queued as messages, or not, or we need memory).
 *
 * @param transport the transport
 * @returns current status
 */
DBusDispatchStatus
_dbus_transport_get_dispatch_status (DBusTransport *transport)
{
  if (_dbus_counter_get_value (transport->live_messages_size) >= transport->max_live_messages_size)
    return DBUS_DISPATCH_COMPLETE; /* complete for now */

650 651 652 653 654 655 656 657 658 659 660 661 662 663 664
  if (!_dbus_transport_get_is_authenticated (transport))
    {
      switch (_dbus_auth_do_work (transport->auth))
        {
        case DBUS_AUTH_STATE_WAITING_FOR_MEMORY:
          return DBUS_DISPATCH_NEED_MEMORY;
        case DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES:
          if (!recover_unused_bytes (transport))
            return DBUS_DISPATCH_NEED_MEMORY;
          break;
        default:
          break;
        }
    }
  
665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715
  if (!_dbus_message_loader_queue_messages (transport->loader))
    return DBUS_DISPATCH_NEED_MEMORY;

  if (_dbus_message_loader_peek_message (transport->loader) != NULL)
    return DBUS_DISPATCH_DATA_REMAINS;
  else
    return DBUS_DISPATCH_COMPLETE;
}

/**
 * Processes data we've read while handling a watch, potentially
 * converting some of it to messages and queueing those messages on
 * the connection.
 *
 * @param transport the transport
 * @returns #TRUE if we had enough memory to queue all messages
 */
dbus_bool_t
_dbus_transport_queue_messages (DBusTransport *transport)
{
  DBusDispatchStatus status;
  
  /* Queue any messages */
  while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
    {
      DBusMessage *message;
      DBusList *link;

      link = _dbus_message_loader_pop_message_link (transport->loader);
      _dbus_assert (link != NULL);
      
      message = link->data;
      
      _dbus_verbose ("queueing received message %p\n", message);

      _dbus_message_add_size_counter (message, transport->live_messages_size);

      /* pass ownership of link and message ref to connection */
      _dbus_connection_queue_received_message_link (transport->connection,
                                                    link);
    }

  if (_dbus_message_loader_get_is_corrupted (transport->loader))
    {
      _dbus_verbose ("Corrupted message stream, disconnecting\n");
      _dbus_transport_disconnect (transport);
    }

  return status != DBUS_DISPATCH_NEED_MEMORY;
}

716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770
/**
 * See dbus_connection_set_max_message_size().
 *
 * @param transport the transport
 * @param size the max size of a single message
 */
void
_dbus_transport_set_max_message_size (DBusTransport  *transport,
                                      long            size)
{
  _dbus_message_loader_set_max_message_size (transport->loader, size);
}

/**
 * See dbus_connection_get_max_message_size().
 *
 * @param transport the transport
 * @returns max message size
 */
long
_dbus_transport_get_max_message_size (DBusTransport  *transport)
{
  return _dbus_message_loader_get_max_message_size (transport->loader);
}

/**
 * See dbus_connection_set_max_live_messages_size().
 *
 * @param transport the transport
 * @param size the max size of all incoming messages
 */
void
_dbus_transport_set_max_live_messages_size (DBusTransport  *transport,
                                            long            size)
{
  transport->max_live_messages_size = size;
  _dbus_counter_set_notify (transport->live_messages_size,
                            transport->max_live_messages_size,
                            live_messages_size_notify,
                            transport);
}


/**
 * See dbus_connection_get_max_live_messages_size().
 *
 * @param transport the transport
 * @returns max bytes for all live messages
 */
long
_dbus_transport_get_max_live_messages_size (DBusTransport  *transport)
{
  return transport->max_live_messages_size;
}

771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828
/**
 * See dbus_connection_get_unix_user().
 *
 * @param transport the transport
 * @param uid return location for the user ID
 * @returns #TRUE if uid is filled in with a valid user ID
 */
dbus_bool_t
_dbus_transport_get_unix_user (DBusTransport *transport,
                               unsigned long *uid)
{
  DBusCredentials auth_identity;

  *uid = _DBUS_INT_MAX; /* better than some root or system user in
                         * case of bugs in the caller. Caller should
                         * never use this value on purpose, however.
                         */
  
  if (!transport->authenticated)
    return FALSE;
  
  _dbus_auth_get_identity (transport->auth, &auth_identity);

  if (auth_identity.uid >= 0)
    {
      *uid = auth_identity.uid;
      return TRUE;
    }
  else
    return FALSE;
}

/**
 * See dbus_connection_set_unix_user_function().
 *
 * @param transport the transport
 * @param function the predicate
 * @param data data to pass to the predicate
 * @param free_data_function function to free the data
 * @param old_data the old user data to be freed
 * @param old_free_data_function old free data function to free it with
 */
void
_dbus_transport_set_unix_user_function (DBusTransport             *transport,
                                        DBusAllowUnixUserFunction  function,
                                        void                      *data,
                                        DBusFreeFunction           free_data_function,
                                        void                     **old_data,
                                        DBusFreeFunction          *old_free_data_function)
{  
  *old_data = transport->unix_user_data;
  *old_free_data_function = transport->free_unix_user_data;

  transport->unix_user_function = function;
  transport->unix_user_data = data;
  transport->free_unix_user_data = free_data_function;
}

829
/** @} */