00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <config.h>
00025 #include "dbus-shared.h"
00026 #include "dbus-connection.h"
00027 #include "dbus-list.h"
00028 #include "dbus-timeout.h"
00029 #include "dbus-transport.h"
00030 #include "dbus-watch.h"
00031 #include "dbus-connection-internal.h"
00032 #include "dbus-pending-call-internal.h"
00033 #include "dbus-list.h"
00034 #include "dbus-hash.h"
00035 #include "dbus-message-internal.h"
00036 #include "dbus-message-private.h"
00037 #include "dbus-threads.h"
00038 #include "dbus-protocol.h"
00039 #include "dbus-dataslot.h"
00040 #include "dbus-string.h"
00041 #include "dbus-signature.h"
00042 #include "dbus-pending-call.h"
00043 #include "dbus-object-tree.h"
00044 #include "dbus-threads-internal.h"
00045 #include "dbus-bus.h"
00046 #include "dbus-marshal-basic.h"
00047
00048 #ifdef DBUS_DISABLE_CHECKS
00049 #define TOOK_LOCK_CHECK(connection)
00050 #define RELEASING_LOCK_CHECK(connection)
00051 #define HAVE_LOCK_CHECK(connection)
00052 #else
00053 #define TOOK_LOCK_CHECK(connection) do { \
00054 _dbus_assert (!(connection)->have_connection_lock); \
00055 (connection)->have_connection_lock = TRUE; \
00056 } while (0)
00057 #define RELEASING_LOCK_CHECK(connection) do { \
00058 _dbus_assert ((connection)->have_connection_lock); \
00059 (connection)->have_connection_lock = FALSE; \
00060 } while (0)
00061 #define HAVE_LOCK_CHECK(connection) _dbus_assert ((connection)->have_connection_lock)
00062
00063 #endif
00064
00065 #define TRACE_LOCKS 1
00066
00067 #define CONNECTION_LOCK(connection) do { \
00068 if (TRACE_LOCKS) { _dbus_verbose ("LOCK\n"); } \
00069 _dbus_rmutex_lock ((connection)->mutex); \
00070 TOOK_LOCK_CHECK (connection); \
00071 } while (0)
00072
00073 #define CONNECTION_UNLOCK(connection) _dbus_connection_unlock (connection)
00074
00075 #define SLOTS_LOCK(connection) do { \
00076 _dbus_rmutex_lock ((connection)->slot_mutex); \
00077 } while (0)
00078
00079 #define SLOTS_UNLOCK(connection) do { \
00080 _dbus_rmutex_unlock ((connection)->slot_mutex); \
00081 } while (0)
00082
00083 #define DISPATCH_STATUS_NAME(s) \
00084 ((s) == DBUS_DISPATCH_COMPLETE ? "complete" : \
00085 (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
00086 (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" : \
00087 "???")
00088
00206 static void
00207 _dbus_connection_trace_ref (DBusConnection *connection,
00208 int old_refcount,
00209 int new_refcount,
00210 const char *why)
00211 {
00212 #ifdef DBUS_ENABLE_VERBOSE_MODE
00213 static int enabled = -1;
00214
00215 _dbus_trace_ref ("DBusConnection", connection, old_refcount, new_refcount,
00216 why, "DBUS_CONNECTION_TRACE", &enabled);
00217 #endif
00218 }
00219
00223 typedef struct DBusMessageFilter DBusMessageFilter;
00224
00228 struct DBusMessageFilter
00229 {
00230 DBusAtomic refcount;
00231 DBusHandleMessageFunction function;
00232 void *user_data;
00233 DBusFreeFunction free_user_data_function;
00234 };
00235
00236
00240 struct DBusPreallocatedSend
00241 {
00242 DBusConnection *connection;
00243 DBusList *queue_link;
00244 DBusList *counter_link;
00245 };
00246
00247 #if HAVE_DECL_MSG_NOSIGNAL
00248 static dbus_bool_t _dbus_modify_sigpipe = FALSE;
00249 #else
00250 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00251 #endif
00252
00256 struct DBusConnection
00257 {
00258 DBusAtomic refcount;
00260 DBusRMutex *mutex;
00262 DBusCMutex *dispatch_mutex;
00263 DBusCondVar *dispatch_cond;
00264 DBusCMutex *io_path_mutex;
00265 DBusCondVar *io_path_cond;
00267 DBusList *outgoing_messages;
00268 DBusList *incoming_messages;
00269 DBusList *expired_messages;
00271 DBusMessage *message_borrowed;
00275 int n_outgoing;
00276 int n_incoming;
00278 DBusCounter *outgoing_counter;
00280 DBusTransport *transport;
00281 DBusWatchList *watches;
00282 DBusTimeoutList *timeouts;
00284 DBusList *filter_list;
00286 DBusRMutex *slot_mutex;
00287 DBusDataSlotList slot_list;
00289 DBusHashTable *pending_replies;
00291 dbus_uint32_t client_serial;
00292 DBusList *disconnect_message_link;
00294 DBusWakeupMainFunction wakeup_main_function;
00295 void *wakeup_main_data;
00296 DBusFreeFunction free_wakeup_main_data;
00298 DBusDispatchStatusFunction dispatch_status_function;
00299 void *dispatch_status_data;
00300 DBusFreeFunction free_dispatch_status_data;
00302 DBusDispatchStatus last_dispatch_status;
00304 DBusObjectTree *objects;
00306 char *server_guid;
00308
00309
00310
00311
00312 dbus_bool_t dispatch_acquired;
00313 dbus_bool_t io_path_acquired;
00315 unsigned int shareable : 1;
00317 unsigned int exit_on_disconnect : 1;
00319 unsigned int route_peer_messages : 1;
00321 unsigned int disconnected_message_arrived : 1;
00325 unsigned int disconnected_message_processed : 1;
00329 #ifndef DBUS_DISABLE_CHECKS
00330 unsigned int have_connection_lock : 1;
00331 #endif
00332
00333 #if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
00334 int generation;
00335 #endif
00336 };
00337
00338 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection);
00339 static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
00340 DBusDispatchStatus new_status);
00341 static void _dbus_connection_last_unref (DBusConnection *connection);
00342 static void _dbus_connection_acquire_dispatch (DBusConnection *connection);
00343 static void _dbus_connection_release_dispatch (DBusConnection *connection);
00344 static DBusDispatchStatus _dbus_connection_flush_unlocked (DBusConnection *connection);
00345 static void _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection);
00346 static dbus_bool_t _dbus_connection_get_is_connected_unlocked (DBusConnection *connection);
00347 static dbus_bool_t _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
00348 dbus_uint32_t client_serial);
00349
00350 static DBusMessageFilter *
00351 _dbus_message_filter_ref (DBusMessageFilter *filter)
00352 {
00353 #ifdef DBUS_DISABLE_ASSERT
00354 _dbus_atomic_inc (&filter->refcount);
00355 #else
00356 dbus_int32_t old_value;
00357
00358 old_value = _dbus_atomic_inc (&filter->refcount);
00359 _dbus_assert (old_value > 0);
00360 #endif
00361
00362 return filter;
00363 }
00364
00365 static void
00366 _dbus_message_filter_unref (DBusMessageFilter *filter)
00367 {
00368 dbus_int32_t old_value;
00369
00370 old_value = _dbus_atomic_dec (&filter->refcount);
00371 _dbus_assert (old_value > 0);
00372
00373 if (old_value == 1)
00374 {
00375 if (filter->free_user_data_function)
00376 (* filter->free_user_data_function) (filter->user_data);
00377
00378 dbus_free (filter);
00379 }
00380 }
00381
00387 void
00388 _dbus_connection_lock (DBusConnection *connection)
00389 {
00390 CONNECTION_LOCK (connection);
00391 }
00392
00398 void
00399 _dbus_connection_unlock (DBusConnection *connection)
00400 {
00401 DBusList *expired_messages;
00402 DBusList *iter;
00403
00404 if (TRACE_LOCKS)
00405 {
00406 _dbus_verbose ("UNLOCK\n");
00407 }
00408
00409
00410
00411 expired_messages = connection->expired_messages;
00412 connection->expired_messages = NULL;
00413
00414 RELEASING_LOCK_CHECK (connection);
00415 _dbus_rmutex_unlock (connection->mutex);
00416
00417 for (iter = _dbus_list_pop_first_link (&expired_messages);
00418 iter != NULL;
00419 iter = _dbus_list_pop_first_link (&expired_messages))
00420 {
00421 DBusMessage *message = iter->data;
00422
00423 dbus_message_unref (message);
00424 _dbus_list_free_link (iter);
00425 }
00426 }
00427
00435 static void
00436 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00437 {
00438 if (connection->wakeup_main_function)
00439 (*connection->wakeup_main_function) (connection->wakeup_main_data);
00440 }
00441
00442 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
00443
00455 void
00456 _dbus_connection_test_get_locks (DBusConnection *connection,
00457 DBusMutex **mutex_loc,
00458 DBusMutex **dispatch_mutex_loc,
00459 DBusMutex **io_path_mutex_loc,
00460 DBusCondVar **dispatch_cond_loc,
00461 DBusCondVar **io_path_cond_loc)
00462 {
00463 *mutex_loc = (DBusMutex *) connection->mutex;
00464 *dispatch_mutex_loc = (DBusMutex *) connection->dispatch_mutex;
00465 *io_path_mutex_loc = (DBusMutex *) connection->io_path_mutex;
00466 *dispatch_cond_loc = connection->dispatch_cond;
00467 *io_path_cond_loc = connection->io_path_cond;
00468 }
00469 #endif
00470
00479 void
00480 _dbus_connection_queue_received_message_link (DBusConnection *connection,
00481 DBusList *link)
00482 {
00483 DBusPendingCall *pending;
00484 dbus_uint32_t reply_serial;
00485 DBusMessage *message;
00486
00487 _dbus_assert (_dbus_transport_peek_is_authenticated (connection->transport));
00488
00489 _dbus_list_append_link (&connection->incoming_messages,
00490 link);
00491 message = link->data;
00492
00493
00494 reply_serial = dbus_message_get_reply_serial (message);
00495 if (reply_serial != 0)
00496 {
00497 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00498 reply_serial);
00499 if (pending != NULL)
00500 {
00501 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00502 _dbus_connection_remove_timeout_unlocked (connection,
00503 _dbus_pending_call_get_timeout_unlocked (pending));
00504
00505 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00506 }
00507 }
00508
00509
00510
00511 connection->n_incoming += 1;
00512
00513 _dbus_connection_wakeup_mainloop (connection);
00514
00515 _dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00516 message,
00517 dbus_message_type_to_string (dbus_message_get_type (message)),
00518 dbus_message_get_path (message) ?
00519 dbus_message_get_path (message) :
00520 "no path",
00521 dbus_message_get_interface (message) ?
00522 dbus_message_get_interface (message) :
00523 "no interface",
00524 dbus_message_get_member (message) ?
00525 dbus_message_get_member (message) :
00526 "no member",
00527 dbus_message_get_signature (message),
00528 dbus_message_get_reply_serial (message),
00529 connection,
00530 connection->n_incoming);
00531
00532 _dbus_message_trace_ref (message, -1, -1,
00533 "_dbus_conection_queue_received_message_link");
00534 }
00535
00544 void
00545 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00546 DBusList *link)
00547 {
00548 HAVE_LOCK_CHECK (connection);
00549
00550 _dbus_list_append_link (&connection->incoming_messages, link);
00551
00552 connection->n_incoming += 1;
00553
00554 _dbus_connection_wakeup_mainloop (connection);
00555
00556 _dbus_message_trace_ref (link->data, -1, -1,
00557 "_dbus_connection_queue_synthesized_message_link");
00558
00559 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00560 link->data, connection, connection->n_incoming);
00561 }
00562
00563
00571 dbus_bool_t
00572 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00573 {
00574 HAVE_LOCK_CHECK (connection);
00575 return connection->outgoing_messages != NULL;
00576 }
00577
00587 dbus_bool_t
00588 dbus_connection_has_messages_to_send (DBusConnection *connection)
00589 {
00590 dbus_bool_t v;
00591
00592 _dbus_return_val_if_fail (connection != NULL, FALSE);
00593
00594 CONNECTION_LOCK (connection);
00595 v = _dbus_connection_has_messages_to_send_unlocked (connection);
00596 CONNECTION_UNLOCK (connection);
00597
00598 return v;
00599 }
00600
00608 DBusMessage*
00609 _dbus_connection_get_message_to_send (DBusConnection *connection)
00610 {
00611 HAVE_LOCK_CHECK (connection);
00612
00613 return _dbus_list_get_last (&connection->outgoing_messages);
00614 }
00615
00624 void
00625 _dbus_connection_message_sent_unlocked (DBusConnection *connection,
00626 DBusMessage *message)
00627 {
00628 DBusList *link;
00629
00630 HAVE_LOCK_CHECK (connection);
00631
00632
00633
00634
00635
00636
00637 link = _dbus_list_get_last_link (&connection->outgoing_messages);
00638 _dbus_assert (link != NULL);
00639 _dbus_assert (link->data == message);
00640
00641 _dbus_list_unlink (&connection->outgoing_messages,
00642 link);
00643 _dbus_list_prepend_link (&connection->expired_messages, link);
00644
00645 connection->n_outgoing -= 1;
00646
00647 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00648 message,
00649 dbus_message_type_to_string (dbus_message_get_type (message)),
00650 dbus_message_get_path (message) ?
00651 dbus_message_get_path (message) :
00652 "no path",
00653 dbus_message_get_interface (message) ?
00654 dbus_message_get_interface (message) :
00655 "no interface",
00656 dbus_message_get_member (message) ?
00657 dbus_message_get_member (message) :
00658 "no member",
00659 dbus_message_get_signature (message),
00660 connection, connection->n_outgoing);
00661
00662
00663
00664 _dbus_message_remove_counter (message, connection->outgoing_counter);
00665
00666
00667 }
00668
00670 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list,
00671 DBusWatch *watch);
00673 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list,
00674 DBusWatch *watch);
00676 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list,
00677 DBusWatch *watch,
00678 dbus_bool_t enabled);
00679
00680 static dbus_bool_t
00681 protected_change_watch (DBusConnection *connection,
00682 DBusWatch *watch,
00683 DBusWatchAddFunction add_function,
00684 DBusWatchRemoveFunction remove_function,
00685 DBusWatchToggleFunction toggle_function,
00686 dbus_bool_t enabled)
00687 {
00688 dbus_bool_t retval;
00689
00690 HAVE_LOCK_CHECK (connection);
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710 if (connection->watches)
00711 {
00712 if (add_function)
00713 retval = (* add_function) (connection->watches, watch);
00714 else if (remove_function)
00715 {
00716 retval = TRUE;
00717 (* remove_function) (connection->watches, watch);
00718 }
00719 else
00720 {
00721 retval = TRUE;
00722 (* toggle_function) (connection->watches, watch, enabled);
00723 }
00724 return retval;
00725 }
00726 else
00727 return FALSE;
00728 }
00729
00730
00742 dbus_bool_t
00743 _dbus_connection_add_watch_unlocked (DBusConnection *connection,
00744 DBusWatch *watch)
00745 {
00746 return protected_change_watch (connection, watch,
00747 _dbus_watch_list_add_watch,
00748 NULL, NULL, FALSE);
00749 }
00750
00760 void
00761 _dbus_connection_remove_watch_unlocked (DBusConnection *connection,
00762 DBusWatch *watch)
00763 {
00764 protected_change_watch (connection, watch,
00765 NULL,
00766 _dbus_watch_list_remove_watch,
00767 NULL, FALSE);
00768 }
00769
00780 void
00781 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
00782 DBusWatch *watch,
00783 dbus_bool_t enabled)
00784 {
00785 _dbus_assert (watch != NULL);
00786
00787 protected_change_watch (connection, watch,
00788 NULL, NULL,
00789 _dbus_watch_list_toggle_watch,
00790 enabled);
00791 }
00792
00794 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list,
00795 DBusTimeout *timeout);
00797 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00798 DBusTimeout *timeout);
00800 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00801 DBusTimeout *timeout,
00802 dbus_bool_t enabled);
00803
00804 static dbus_bool_t
00805 protected_change_timeout (DBusConnection *connection,
00806 DBusTimeout *timeout,
00807 DBusTimeoutAddFunction add_function,
00808 DBusTimeoutRemoveFunction remove_function,
00809 DBusTimeoutToggleFunction toggle_function,
00810 dbus_bool_t enabled)
00811 {
00812 dbus_bool_t retval;
00813
00814 HAVE_LOCK_CHECK (connection);
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834 if (connection->timeouts)
00835 {
00836 if (add_function)
00837 retval = (* add_function) (connection->timeouts, timeout);
00838 else if (remove_function)
00839 {
00840 retval = TRUE;
00841 (* remove_function) (connection->timeouts, timeout);
00842 }
00843 else
00844 {
00845 retval = TRUE;
00846 (* toggle_function) (connection->timeouts, timeout, enabled);
00847 }
00848 return retval;
00849 }
00850 else
00851 return FALSE;
00852 }
00853
00866 dbus_bool_t
00867 _dbus_connection_add_timeout_unlocked (DBusConnection *connection,
00868 DBusTimeout *timeout)
00869 {
00870 return protected_change_timeout (connection, timeout,
00871 _dbus_timeout_list_add_timeout,
00872 NULL, NULL, FALSE);
00873 }
00874
00884 void
00885 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
00886 DBusTimeout *timeout)
00887 {
00888 protected_change_timeout (connection, timeout,
00889 NULL,
00890 _dbus_timeout_list_remove_timeout,
00891 NULL, FALSE);
00892 }
00893
00904 void
00905 _dbus_connection_toggle_timeout_unlocked (DBusConnection *connection,
00906 DBusTimeout *timeout,
00907 dbus_bool_t enabled)
00908 {
00909 protected_change_timeout (connection, timeout,
00910 NULL, NULL,
00911 _dbus_timeout_list_toggle_timeout,
00912 enabled);
00913 }
00914
00915 static dbus_bool_t
00916 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection,
00917 DBusPendingCall *pending)
00918 {
00919 dbus_uint32_t reply_serial;
00920 DBusTimeout *timeout;
00921
00922 HAVE_LOCK_CHECK (connection);
00923
00924 reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
00925
00926 _dbus_assert (reply_serial != 0);
00927
00928 timeout = _dbus_pending_call_get_timeout_unlocked (pending);
00929
00930 if (timeout)
00931 {
00932 if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
00933 return FALSE;
00934
00935 if (!_dbus_hash_table_insert_int (connection->pending_replies,
00936 reply_serial,
00937 pending))
00938 {
00939 _dbus_connection_remove_timeout_unlocked (connection, timeout);
00940
00941 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00942 HAVE_LOCK_CHECK (connection);
00943 return FALSE;
00944 }
00945
00946 _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE);
00947 }
00948 else
00949 {
00950 if (!_dbus_hash_table_insert_int (connection->pending_replies,
00951 reply_serial,
00952 pending))
00953 {
00954 HAVE_LOCK_CHECK (connection);
00955 return FALSE;
00956 }
00957 }
00958
00959 _dbus_pending_call_ref_unlocked (pending);
00960
00961 HAVE_LOCK_CHECK (connection);
00962
00963 return TRUE;
00964 }
00965
00966 static void
00967 free_pending_call_on_hash_removal (void *data)
00968 {
00969 DBusPendingCall *pending;
00970 DBusConnection *connection;
00971
00972 if (data == NULL)
00973 return;
00974
00975 pending = data;
00976
00977 connection = _dbus_pending_call_get_connection_unlocked (pending);
00978
00979 HAVE_LOCK_CHECK (connection);
00980
00981 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00982 {
00983 _dbus_connection_remove_timeout_unlocked (connection,
00984 _dbus_pending_call_get_timeout_unlocked (pending));
00985
00986 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00987 }
00988
00989
00990
00991
00992
00993
00994 _dbus_connection_ref_unlocked (connection);
00995 _dbus_pending_call_unref_and_unlock (pending);
00996 CONNECTION_LOCK (connection);
00997 _dbus_connection_unref_unlocked (connection);
00998 }
00999
01000 static void
01001 _dbus_connection_detach_pending_call_unlocked (DBusConnection *connection,
01002 DBusPendingCall *pending)
01003 {
01004
01005
01006
01007 _dbus_hash_table_remove_int (connection->pending_replies,
01008 _dbus_pending_call_get_reply_serial_unlocked (pending));
01009 }
01010
01011 static void
01012 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection,
01013 DBusPendingCall *pending)
01014 {
01015
01016
01017
01018
01019
01020
01021
01022 _dbus_pending_call_ref_unlocked (pending);
01023 _dbus_hash_table_remove_int (connection->pending_replies,
01024 _dbus_pending_call_get_reply_serial_unlocked (pending));
01025
01026 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
01027 _dbus_connection_remove_timeout_unlocked (connection,
01028 _dbus_pending_call_get_timeout_unlocked (pending));
01029
01030 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
01031
01032 _dbus_pending_call_unref_and_unlock (pending);
01033 }
01034
01043 void
01044 _dbus_connection_remove_pending_call (DBusConnection *connection,
01045 DBusPendingCall *pending)
01046 {
01047 CONNECTION_LOCK (connection);
01048 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
01049 }
01050
01060 static dbus_bool_t
01061 _dbus_connection_acquire_io_path (DBusConnection *connection,
01062 int timeout_milliseconds)
01063 {
01064 dbus_bool_t we_acquired;
01065
01066 HAVE_LOCK_CHECK (connection);
01067
01068
01069 _dbus_connection_ref_unlocked (connection);
01070
01071
01072 CONNECTION_UNLOCK (connection);
01073
01074 _dbus_verbose ("locking io_path_mutex\n");
01075 _dbus_cmutex_lock (connection->io_path_mutex);
01076
01077 _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n",
01078 connection->io_path_acquired, timeout_milliseconds);
01079
01080 we_acquired = FALSE;
01081
01082 if (connection->io_path_acquired)
01083 {
01084 if (timeout_milliseconds != -1)
01085 {
01086 _dbus_verbose ("waiting %d for IO path to be acquirable\n",
01087 timeout_milliseconds);
01088
01089 if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
01090 connection->io_path_mutex,
01091 timeout_milliseconds))
01092 {
01093
01094
01095
01096
01097
01098
01099
01100
01101 }
01102 }
01103 else
01104 {
01105 while (connection->io_path_acquired)
01106 {
01107 _dbus_verbose ("waiting for IO path to be acquirable\n");
01108 _dbus_condvar_wait (connection->io_path_cond,
01109 connection->io_path_mutex);
01110 }
01111 }
01112 }
01113
01114 if (!connection->io_path_acquired)
01115 {
01116 we_acquired = TRUE;
01117 connection->io_path_acquired = TRUE;
01118 }
01119
01120 _dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n",
01121 connection->io_path_acquired, we_acquired);
01122
01123 _dbus_verbose ("unlocking io_path_mutex\n");
01124 _dbus_cmutex_unlock (connection->io_path_mutex);
01125
01126 CONNECTION_LOCK (connection);
01127
01128 HAVE_LOCK_CHECK (connection);
01129
01130 _dbus_connection_unref_unlocked (connection);
01131
01132 return we_acquired;
01133 }
01134
01142 static void
01143 _dbus_connection_release_io_path (DBusConnection *connection)
01144 {
01145 HAVE_LOCK_CHECK (connection);
01146
01147 _dbus_verbose ("locking io_path_mutex\n");
01148 _dbus_cmutex_lock (connection->io_path_mutex);
01149
01150 _dbus_assert (connection->io_path_acquired);
01151
01152 _dbus_verbose ("start connection->io_path_acquired = %d\n",
01153 connection->io_path_acquired);
01154
01155 connection->io_path_acquired = FALSE;
01156 _dbus_condvar_wake_one (connection->io_path_cond);
01157
01158 _dbus_verbose ("unlocking io_path_mutex\n");
01159 _dbus_cmutex_unlock (connection->io_path_mutex);
01160 }
01161
01197 void
01198 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01199 DBusPendingCall *pending,
01200 unsigned int flags,
01201 int timeout_milliseconds)
01202 {
01203 _dbus_verbose ("start\n");
01204
01205 HAVE_LOCK_CHECK (connection);
01206
01207 if (connection->n_outgoing == 0)
01208 flags &= ~DBUS_ITERATION_DO_WRITING;
01209
01210 if (_dbus_connection_acquire_io_path (connection,
01211 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01212 {
01213 HAVE_LOCK_CHECK (connection);
01214
01215 if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending))
01216 {
01217 _dbus_verbose ("pending call completed while acquiring I/O path");
01218 }
01219 else if ( (pending != NULL) &&
01220 _dbus_connection_peek_for_reply_unlocked (connection,
01221 _dbus_pending_call_get_reply_serial_unlocked (pending)))
01222 {
01223 _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)");
01224 }
01225 else
01226 {
01227 _dbus_transport_do_iteration (connection->transport,
01228 flags, timeout_milliseconds);
01229 }
01230
01231 _dbus_connection_release_io_path (connection);
01232 }
01233
01234 HAVE_LOCK_CHECK (connection);
01235
01236 _dbus_verbose ("end\n");
01237 }
01238
01248 DBusConnection*
01249 _dbus_connection_new_for_transport (DBusTransport *transport)
01250 {
01251 DBusConnection *connection;
01252 DBusWatchList *watch_list;
01253 DBusTimeoutList *timeout_list;
01254 DBusHashTable *pending_replies;
01255 DBusList *disconnect_link;
01256 DBusMessage *disconnect_message;
01257 DBusCounter *outgoing_counter;
01258 DBusObjectTree *objects;
01259
01260 watch_list = NULL;
01261 connection = NULL;
01262 pending_replies = NULL;
01263 timeout_list = NULL;
01264 disconnect_link = NULL;
01265 disconnect_message = NULL;
01266 outgoing_counter = NULL;
01267 objects = NULL;
01268
01269 watch_list = _dbus_watch_list_new ();
01270 if (watch_list == NULL)
01271 goto error;
01272
01273 timeout_list = _dbus_timeout_list_new ();
01274 if (timeout_list == NULL)
01275 goto error;
01276
01277 pending_replies =
01278 _dbus_hash_table_new (DBUS_HASH_INT,
01279 NULL,
01280 (DBusFreeFunction)free_pending_call_on_hash_removal);
01281 if (pending_replies == NULL)
01282 goto error;
01283
01284 connection = dbus_new0 (DBusConnection, 1);
01285 if (connection == NULL)
01286 goto error;
01287
01288 _dbus_rmutex_new_at_location (&connection->mutex);
01289 if (connection->mutex == NULL)
01290 goto error;
01291
01292 _dbus_cmutex_new_at_location (&connection->io_path_mutex);
01293 if (connection->io_path_mutex == NULL)
01294 goto error;
01295
01296 _dbus_cmutex_new_at_location (&connection->dispatch_mutex);
01297 if (connection->dispatch_mutex == NULL)
01298 goto error;
01299
01300 _dbus_condvar_new_at_location (&connection->dispatch_cond);
01301 if (connection->dispatch_cond == NULL)
01302 goto error;
01303
01304 _dbus_condvar_new_at_location (&connection->io_path_cond);
01305 if (connection->io_path_cond == NULL)
01306 goto error;
01307
01308 _dbus_rmutex_new_at_location (&connection->slot_mutex);
01309 if (connection->slot_mutex == NULL)
01310 goto error;
01311
01312 disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01313 DBUS_INTERFACE_LOCAL,
01314 "Disconnected");
01315
01316 if (disconnect_message == NULL)
01317 goto error;
01318
01319 disconnect_link = _dbus_list_alloc_link (disconnect_message);
01320 if (disconnect_link == NULL)
01321 goto error;
01322
01323 outgoing_counter = _dbus_counter_new ();
01324 if (outgoing_counter == NULL)
01325 goto error;
01326
01327 objects = _dbus_object_tree_new (connection);
01328 if (objects == NULL)
01329 goto error;
01330
01331 if (_dbus_modify_sigpipe)
01332 _dbus_disable_sigpipe ();
01333
01334
01335 _dbus_atomic_inc (&connection->refcount);
01336 connection->transport = transport;
01337 connection->watches = watch_list;
01338 connection->timeouts = timeout_list;
01339 connection->pending_replies = pending_replies;
01340 connection->outgoing_counter = outgoing_counter;
01341 connection->filter_list = NULL;
01342 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE;
01343 connection->objects = objects;
01344 connection->exit_on_disconnect = FALSE;
01345 connection->shareable = FALSE;
01346 connection->route_peer_messages = FALSE;
01347 connection->disconnected_message_arrived = FALSE;
01348 connection->disconnected_message_processed = FALSE;
01349
01350 #if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
01351 connection->generation = _dbus_current_generation;
01352 #endif
01353
01354 _dbus_data_slot_list_init (&connection->slot_list);
01355
01356 connection->client_serial = 1;
01357
01358 connection->disconnect_message_link = disconnect_link;
01359
01360 CONNECTION_LOCK (connection);
01361
01362 if (!_dbus_transport_set_connection (transport, connection))
01363 {
01364 CONNECTION_UNLOCK (connection);
01365
01366 goto error;
01367 }
01368
01369 _dbus_transport_ref (transport);
01370
01371 CONNECTION_UNLOCK (connection);
01372
01373 _dbus_connection_trace_ref (connection, 0, 1, "new_for_transport");
01374 return connection;
01375
01376 error:
01377 if (disconnect_message != NULL)
01378 dbus_message_unref (disconnect_message);
01379
01380 if (disconnect_link != NULL)
01381 _dbus_list_free_link (disconnect_link);
01382
01383 if (connection != NULL)
01384 {
01385 _dbus_condvar_free_at_location (&connection->io_path_cond);
01386 _dbus_condvar_free_at_location (&connection->dispatch_cond);
01387 _dbus_rmutex_free_at_location (&connection->mutex);
01388 _dbus_cmutex_free_at_location (&connection->io_path_mutex);
01389 _dbus_cmutex_free_at_location (&connection->dispatch_mutex);
01390 _dbus_rmutex_free_at_location (&connection->slot_mutex);
01391 dbus_free (connection);
01392 }
01393 if (pending_replies)
01394 _dbus_hash_table_unref (pending_replies);
01395
01396 if (watch_list)
01397 _dbus_watch_list_free (watch_list);
01398
01399 if (timeout_list)
01400 _dbus_timeout_list_free (timeout_list);
01401
01402 if (outgoing_counter)
01403 _dbus_counter_unref (outgoing_counter);
01404
01405 if (objects)
01406 _dbus_object_tree_unref (objects);
01407
01408 return NULL;
01409 }
01410
01418 DBusConnection *
01419 _dbus_connection_ref_unlocked (DBusConnection *connection)
01420 {
01421 dbus_int32_t old_refcount;
01422
01423 _dbus_assert (connection != NULL);
01424 _dbus_assert (connection->generation == _dbus_current_generation);
01425
01426 HAVE_LOCK_CHECK (connection);
01427
01428 old_refcount = _dbus_atomic_inc (&connection->refcount);
01429 _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1,
01430 "ref_unlocked");
01431
01432 return connection;
01433 }
01434
01441 void
01442 _dbus_connection_unref_unlocked (DBusConnection *connection)
01443 {
01444 dbus_int32_t old_refcount;
01445
01446 HAVE_LOCK_CHECK (connection);
01447
01448 _dbus_assert (connection != NULL);
01449
01450 old_refcount = _dbus_atomic_dec (&connection->refcount);
01451
01452 _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1,
01453 "unref_unlocked");
01454
01455 if (old_refcount == 1)
01456 _dbus_connection_last_unref (connection);
01457 }
01458
01459 static dbus_uint32_t
01460 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01461 {
01462 dbus_uint32_t serial;
01463
01464 serial = connection->client_serial++;
01465
01466 if (connection->client_serial == 0)
01467 connection->client_serial = 1;
01468
01469 return serial;
01470 }
01471
01485 dbus_bool_t
01486 _dbus_connection_handle_watch (DBusWatch *watch,
01487 unsigned int condition,
01488 void *data)
01489 {
01490 DBusConnection *connection;
01491 dbus_bool_t retval;
01492 DBusDispatchStatus status;
01493
01494 connection = data;
01495
01496 _dbus_verbose ("start\n");
01497
01498 CONNECTION_LOCK (connection);
01499
01500 if (!_dbus_connection_acquire_io_path (connection, 1))
01501 {
01502
01503 CONNECTION_UNLOCK (connection);
01504 return TRUE;
01505 }
01506
01507 HAVE_LOCK_CHECK (connection);
01508 retval = _dbus_transport_handle_watch (connection->transport,
01509 watch, condition);
01510
01511 _dbus_connection_release_io_path (connection);
01512
01513 HAVE_LOCK_CHECK (connection);
01514
01515 _dbus_verbose ("middle\n");
01516
01517 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01518
01519
01520 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01521
01522 _dbus_verbose ("end\n");
01523
01524 return retval;
01525 }
01526
01527
01528 static DBusHashTable *shared_connections = NULL;
01529 static DBusList *shared_connections_no_guid = NULL;
01530
01531 static void
01532 close_connection_on_shutdown (DBusConnection *connection)
01533 {
01534 DBusMessage *message;
01535
01536 dbus_connection_ref (connection);
01537 _dbus_connection_close_possibly_shared (connection);
01538
01539
01540 while ((message = dbus_connection_pop_message (connection)))
01541 {
01542 dbus_message_unref (message);
01543 }
01544 dbus_connection_unref (connection);
01545 }
01546
01547 static void
01548 shared_connections_shutdown (void *data)
01549 {
01550 int n_entries;
01551
01552 if (!_DBUS_LOCK (shared_connections))
01553 {
01554
01555
01556 return;
01557 }
01558
01559
01560 while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
01561 {
01562 DBusConnection *connection;
01563 DBusHashIter iter;
01564
01565 _dbus_hash_iter_init (shared_connections, &iter);
01566 _dbus_hash_iter_next (&iter);
01567
01568 connection = _dbus_hash_iter_get_value (&iter);
01569
01570 _DBUS_UNLOCK (shared_connections);
01571 close_connection_on_shutdown (connection);
01572 if (!_DBUS_LOCK (shared_connections))
01573 _dbus_assert_not_reached ("global locks were already initialized");
01574
01575
01576 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
01577 }
01578
01579 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01580
01581 _dbus_hash_table_unref (shared_connections);
01582 shared_connections = NULL;
01583
01584 if (shared_connections_no_guid != NULL)
01585 {
01586 DBusConnection *connection;
01587 connection = _dbus_list_pop_first (&shared_connections_no_guid);
01588 while (connection != NULL)
01589 {
01590 _DBUS_UNLOCK (shared_connections);
01591 close_connection_on_shutdown (connection);
01592 if (!_DBUS_LOCK (shared_connections))
01593 _dbus_assert_not_reached ("global locks were already initialized");
01594 connection = _dbus_list_pop_first (&shared_connections_no_guid);
01595 }
01596 }
01597
01598 shared_connections_no_guid = NULL;
01599
01600 _DBUS_UNLOCK (shared_connections);
01601 }
01602
01603 static dbus_bool_t
01604 connection_lookup_shared (DBusAddressEntry *entry,
01605 DBusConnection **result)
01606 {
01607 _dbus_verbose ("checking for existing connection\n");
01608
01609 *result = NULL;
01610
01611 if (!_DBUS_LOCK (shared_connections))
01612 {
01613
01614
01615 return FALSE;
01616 }
01617
01618 if (shared_connections == NULL)
01619 {
01620 _dbus_verbose ("creating shared_connections hash table\n");
01621
01622 shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01623 dbus_free,
01624 NULL);
01625 if (shared_connections == NULL)
01626 {
01627 _DBUS_UNLOCK (shared_connections);
01628 return FALSE;
01629 }
01630
01631 if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01632 {
01633 _dbus_hash_table_unref (shared_connections);
01634 shared_connections = NULL;
01635 _DBUS_UNLOCK (shared_connections);
01636 return FALSE;
01637 }
01638
01639 _dbus_verbose (" successfully created shared_connections\n");
01640
01641 _DBUS_UNLOCK (shared_connections);
01642 return TRUE;
01643 }
01644 else
01645 {
01646 const char *guid;
01647
01648 guid = dbus_address_entry_get_value (entry, "guid");
01649
01650 if (guid != NULL)
01651 {
01652 DBusConnection *connection;
01653
01654 connection = _dbus_hash_table_lookup_string (shared_connections,
01655 guid);
01656
01657 if (connection)
01658 {
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673 CONNECTION_LOCK (connection);
01674 if (_dbus_connection_get_is_connected_unlocked (connection))
01675 {
01676 _dbus_connection_ref_unlocked (connection);
01677 *result = connection;
01678 _dbus_verbose ("looked up existing connection to server guid %s\n",
01679 guid);
01680 }
01681 else
01682 {
01683 _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
01684 guid);
01685 }
01686 CONNECTION_UNLOCK (connection);
01687 }
01688 }
01689
01690 _DBUS_UNLOCK (shared_connections);
01691 return TRUE;
01692 }
01693 }
01694
01695 static dbus_bool_t
01696 connection_record_shared_unlocked (DBusConnection *connection,
01697 const char *guid)
01698 {
01699 char *guid_key;
01700 char *guid_in_connection;
01701
01702 HAVE_LOCK_CHECK (connection);
01703 _dbus_assert (connection->server_guid == NULL);
01704 _dbus_assert (connection->shareable);
01705
01706
01707
01708
01709
01710 _dbus_connection_ref_unlocked (connection);
01711
01712 if (guid == NULL)
01713 {
01714 if (!_DBUS_LOCK (shared_connections))
01715 return FALSE;
01716
01717 if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
01718 {
01719 _DBUS_UNLOCK (shared_connections);
01720 return FALSE;
01721 }
01722
01723 _DBUS_UNLOCK (shared_connections);
01724 return TRUE;
01725 }
01726
01727
01728
01729
01730
01731
01732 guid_key = _dbus_strdup (guid);
01733 if (guid_key == NULL)
01734 return FALSE;
01735
01736 guid_in_connection = _dbus_strdup (guid);
01737 if (guid_in_connection == NULL)
01738 {
01739 dbus_free (guid_key);
01740 return FALSE;
01741 }
01742
01743 if (!_DBUS_LOCK (shared_connections))
01744 {
01745 dbus_free (guid_in_connection);
01746 dbus_free (guid_key);
01747 return FALSE;
01748 }
01749
01750 _dbus_assert (shared_connections != NULL);
01751
01752 if (!_dbus_hash_table_insert_string (shared_connections,
01753 guid_key, connection))
01754 {
01755 dbus_free (guid_key);
01756 dbus_free (guid_in_connection);
01757 _DBUS_UNLOCK (shared_connections);
01758 return FALSE;
01759 }
01760
01761 connection->server_guid = guid_in_connection;
01762
01763 _dbus_verbose ("stored connection to %s to be shared\n",
01764 connection->server_guid);
01765
01766 _DBUS_UNLOCK (shared_connections);
01767
01768 _dbus_assert (connection->server_guid != NULL);
01769
01770 return TRUE;
01771 }
01772
01773 static void
01774 connection_forget_shared_unlocked (DBusConnection *connection)
01775 {
01776 HAVE_LOCK_CHECK (connection);
01777
01778 if (!connection->shareable)
01779 return;
01780
01781 if (!_DBUS_LOCK (shared_connections))
01782 {
01783
01784
01785 return;
01786 }
01787
01788 if (connection->server_guid != NULL)
01789 {
01790 _dbus_verbose ("dropping connection to %s out of the shared table\n",
01791 connection->server_guid);
01792
01793 if (!_dbus_hash_table_remove_string (shared_connections,
01794 connection->server_guid))
01795 _dbus_assert_not_reached ("connection was not in the shared table");
01796
01797 dbus_free (connection->server_guid);
01798 connection->server_guid = NULL;
01799 }
01800 else
01801 {
01802 _dbus_list_remove (&shared_connections_no_guid, connection);
01803 }
01804
01805 _DBUS_UNLOCK (shared_connections);
01806
01807
01808 _dbus_connection_unref_unlocked (connection);
01809 }
01810
01811 static DBusConnection*
01812 connection_try_from_address_entry (DBusAddressEntry *entry,
01813 DBusError *error)
01814 {
01815 DBusTransport *transport;
01816 DBusConnection *connection;
01817
01818 transport = _dbus_transport_open (entry, error);
01819
01820 if (transport == NULL)
01821 {
01822 _DBUS_ASSERT_ERROR_IS_SET (error);
01823 return NULL;
01824 }
01825
01826 connection = _dbus_connection_new_for_transport (transport);
01827
01828 _dbus_transport_unref (transport);
01829
01830 if (connection == NULL)
01831 {
01832 _DBUS_SET_OOM (error);
01833 return NULL;
01834 }
01835
01836 #ifndef DBUS_DISABLE_CHECKS
01837 _dbus_assert (!connection->have_connection_lock);
01838 #endif
01839 return connection;
01840 }
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854 static DBusConnection*
01855 _dbus_connection_open_internal (const char *address,
01856 dbus_bool_t shared,
01857 DBusError *error)
01858 {
01859 DBusConnection *connection;
01860 DBusAddressEntry **entries;
01861 DBusError tmp_error = DBUS_ERROR_INIT;
01862 DBusError first_error = DBUS_ERROR_INIT;
01863 int len, i;
01864
01865 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01866
01867 _dbus_verbose ("opening %s connection to: %s\n",
01868 shared ? "shared" : "private", address);
01869
01870 if (!dbus_parse_address (address, &entries, &len, error))
01871 return NULL;
01872
01873 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01874
01875 connection = NULL;
01876
01877 for (i = 0; i < len; i++)
01878 {
01879 if (shared)
01880 {
01881 if (!connection_lookup_shared (entries[i], &connection))
01882 _DBUS_SET_OOM (&tmp_error);
01883 }
01884
01885 if (connection == NULL)
01886 {
01887 connection = connection_try_from_address_entry (entries[i],
01888 &tmp_error);
01889
01890 if (connection != NULL && shared)
01891 {
01892 const char *guid;
01893
01894 connection->shareable = TRUE;
01895
01896
01897 guid = dbus_address_entry_get_value (entries[i], "guid");
01898
01899 CONNECTION_LOCK (connection);
01900
01901 if (!connection_record_shared_unlocked (connection, guid))
01902 {
01903 _DBUS_SET_OOM (&tmp_error);
01904 _dbus_connection_close_possibly_shared_and_unlock (connection);
01905 dbus_connection_unref (connection);
01906 connection = NULL;
01907 }
01908 else
01909 CONNECTION_UNLOCK (connection);
01910 }
01911 }
01912
01913 if (connection)
01914 break;
01915
01916 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01917
01918 if (i == 0)
01919 dbus_move_error (&tmp_error, &first_error);
01920 else
01921 dbus_error_free (&tmp_error);
01922 }
01923
01924 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01925 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01926
01927 if (connection == NULL)
01928 {
01929 _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01930 dbus_move_error (&first_error, error);
01931 }
01932 else
01933 dbus_error_free (&first_error);
01934
01935 dbus_address_entries_free (entries);
01936 return connection;
01937 }
01938
01947 void
01948 _dbus_connection_close_possibly_shared (DBusConnection *connection)
01949 {
01950 _dbus_assert (connection != NULL);
01951 _dbus_assert (connection->generation == _dbus_current_generation);
01952
01953 CONNECTION_LOCK (connection);
01954 _dbus_connection_close_possibly_shared_and_unlock (connection);
01955 }
01956
01957 static DBusPreallocatedSend*
01958 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01959 {
01960 DBusPreallocatedSend *preallocated;
01961
01962 HAVE_LOCK_CHECK (connection);
01963
01964 _dbus_assert (connection != NULL);
01965
01966 preallocated = dbus_new (DBusPreallocatedSend, 1);
01967 if (preallocated == NULL)
01968 return NULL;
01969
01970 preallocated->queue_link = _dbus_list_alloc_link (NULL);
01971 if (preallocated->queue_link == NULL)
01972 goto failed_0;
01973
01974 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01975 if (preallocated->counter_link == NULL)
01976 goto failed_1;
01977
01978 _dbus_counter_ref (preallocated->counter_link->data);
01979
01980 preallocated->connection = connection;
01981
01982 return preallocated;
01983
01984 failed_1:
01985 _dbus_list_free_link (preallocated->queue_link);
01986 failed_0:
01987 dbus_free (preallocated);
01988
01989 return NULL;
01990 }
01991
01992
01993 static void
01994 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection,
01995 DBusPreallocatedSend *preallocated,
01996 DBusMessage *message,
01997 dbus_uint32_t *client_serial)
01998 {
01999 dbus_uint32_t serial;
02000
02001 preallocated->queue_link->data = message;
02002 _dbus_list_prepend_link (&connection->outgoing_messages,
02003 preallocated->queue_link);
02004
02005
02006
02007 _dbus_message_add_counter_link (message,
02008 preallocated->counter_link);
02009
02010 dbus_free (preallocated);
02011 preallocated = NULL;
02012
02013 dbus_message_ref (message);
02014
02015 connection->n_outgoing += 1;
02016
02017 _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
02018 message,
02019 dbus_message_type_to_string (dbus_message_get_type (message)),
02020 dbus_message_get_path (message) ?
02021 dbus_message_get_path (message) :
02022 "no path",
02023 dbus_message_get_interface (message) ?
02024 dbus_message_get_interface (message) :
02025 "no interface",
02026 dbus_message_get_member (message) ?
02027 dbus_message_get_member (message) :
02028 "no member",
02029 dbus_message_get_signature (message),
02030 dbus_message_get_destination (message) ?
02031 dbus_message_get_destination (message) :
02032 "null",
02033 connection,
02034 connection->n_outgoing);
02035
02036 if (dbus_message_get_serial (message) == 0)
02037 {
02038 serial = _dbus_connection_get_next_client_serial (connection);
02039 dbus_message_set_serial (message, serial);
02040 if (client_serial)
02041 *client_serial = serial;
02042 }
02043 else
02044 {
02045 if (client_serial)
02046 *client_serial = dbus_message_get_serial (message);
02047 }
02048
02049 _dbus_verbose ("Message %p serial is %u\n",
02050 message, dbus_message_get_serial (message));
02051
02052 dbus_message_lock (message);
02053
02054
02055
02056
02057 _dbus_connection_do_iteration_unlocked (connection,
02058 NULL,
02059 DBUS_ITERATION_DO_WRITING,
02060 -1);
02061
02062
02063 if (connection->n_outgoing > 0)
02064 _dbus_connection_wakeup_mainloop (connection);
02065 }
02066
02067 static void
02068 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection,
02069 DBusPreallocatedSend *preallocated,
02070 DBusMessage *message,
02071 dbus_uint32_t *client_serial)
02072 {
02073 DBusDispatchStatus status;
02074
02075 HAVE_LOCK_CHECK (connection);
02076
02077 _dbus_connection_send_preallocated_unlocked_no_update (connection,
02078 preallocated,
02079 message, client_serial);
02080
02081 _dbus_verbose ("middle\n");
02082 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02083
02084
02085 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02086 }
02087
02097 dbus_bool_t
02098 _dbus_connection_send_and_unlock (DBusConnection *connection,
02099 DBusMessage *message,
02100 dbus_uint32_t *client_serial)
02101 {
02102 DBusPreallocatedSend *preallocated;
02103
02104 _dbus_assert (connection != NULL);
02105 _dbus_assert (message != NULL);
02106
02107 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02108 if (preallocated == NULL)
02109 {
02110 CONNECTION_UNLOCK (connection);
02111 return FALSE;
02112 }
02113
02114 _dbus_connection_send_preallocated_and_unlock (connection,
02115 preallocated,
02116 message,
02117 client_serial);
02118 return TRUE;
02119 }
02120
02145 void
02146 _dbus_connection_close_if_only_one_ref (DBusConnection *connection)
02147 {
02148 dbus_int32_t refcount;
02149
02150 CONNECTION_LOCK (connection);
02151
02152 refcount = _dbus_atomic_get (&connection->refcount);
02153
02154 _dbus_assert (refcount >= 1);
02155
02156 if (refcount == 1)
02157 _dbus_connection_close_possibly_shared_and_unlock (connection);
02158 else
02159 CONNECTION_UNLOCK (connection);
02160 }
02161
02162
02172 static void
02173 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02174 {
02175 if (timeout_milliseconds == -1)
02176 _dbus_sleep_milliseconds (1000);
02177 else if (timeout_milliseconds < 100)
02178 ;
02179 else if (timeout_milliseconds <= 1000)
02180 _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02181 else
02182 _dbus_sleep_milliseconds (1000);
02183 }
02184
02185 static DBusMessage *
02186 generate_local_error_message (dbus_uint32_t serial,
02187 char *error_name,
02188 char *error_msg)
02189 {
02190 DBusMessage *message;
02191 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
02192 if (!message)
02193 goto out;
02194
02195 if (!dbus_message_set_error_name (message, error_name))
02196 {
02197 dbus_message_unref (message);
02198 message = NULL;
02199 goto out;
02200 }
02201
02202 dbus_message_set_no_reply (message, TRUE);
02203
02204 if (!dbus_message_set_reply_serial (message,
02205 serial))
02206 {
02207 dbus_message_unref (message);
02208 message = NULL;
02209 goto out;
02210 }
02211
02212 if (error_msg != NULL)
02213 {
02214 DBusMessageIter iter;
02215
02216 dbus_message_iter_init_append (message, &iter);
02217 if (!dbus_message_iter_append_basic (&iter,
02218 DBUS_TYPE_STRING,
02219 &error_msg))
02220 {
02221 dbus_message_unref (message);
02222 message = NULL;
02223 goto out;
02224 }
02225 }
02226
02227 out:
02228 return message;
02229 }
02230
02231
02232
02233
02234 static dbus_bool_t
02235 _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
02236 dbus_uint32_t client_serial)
02237 {
02238 DBusList *link;
02239 HAVE_LOCK_CHECK (connection);
02240
02241 link = _dbus_list_get_first_link (&connection->incoming_messages);
02242
02243 while (link != NULL)
02244 {
02245 DBusMessage *reply = link->data;
02246
02247 if (dbus_message_get_reply_serial (reply) == client_serial)
02248 {
02249 _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial);
02250 return TRUE;
02251 }
02252 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02253 }
02254
02255 return FALSE;
02256 }
02257
02258
02259
02260
02261 static DBusMessage*
02262 check_for_reply_unlocked (DBusConnection *connection,
02263 dbus_uint32_t client_serial)
02264 {
02265 DBusList *link;
02266
02267 HAVE_LOCK_CHECK (connection);
02268
02269 link = _dbus_list_get_first_link (&connection->incoming_messages);
02270
02271 while (link != NULL)
02272 {
02273 DBusMessage *reply = link->data;
02274
02275 if (dbus_message_get_reply_serial (reply) == client_serial)
02276 {
02277 _dbus_list_remove_link (&connection->incoming_messages, link);
02278 connection->n_incoming -= 1;
02279 return reply;
02280 }
02281 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02282 }
02283
02284 return NULL;
02285 }
02286
02287 static void
02288 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
02289 {
02290
02291
02292
02293
02294
02295 while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
02296 {
02297 DBusPendingCall *pending;
02298 DBusHashIter iter;
02299
02300 _dbus_hash_iter_init (connection->pending_replies, &iter);
02301 _dbus_hash_iter_next (&iter);
02302
02303 pending = _dbus_hash_iter_get_value (&iter);
02304 _dbus_pending_call_ref_unlocked (pending);
02305
02306 _dbus_pending_call_queue_timeout_error_unlocked (pending,
02307 connection);
02308
02309 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
02310 _dbus_connection_remove_timeout_unlocked (connection,
02311 _dbus_pending_call_get_timeout_unlocked (pending));
02312 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
02313 _dbus_hash_iter_remove_entry (&iter);
02314
02315 _dbus_pending_call_unref_and_unlock (pending);
02316 CONNECTION_LOCK (connection);
02317 }
02318 HAVE_LOCK_CHECK (connection);
02319 }
02320
02321 static void
02322 complete_pending_call_and_unlock (DBusConnection *connection,
02323 DBusPendingCall *pending,
02324 DBusMessage *message)
02325 {
02326 _dbus_pending_call_set_reply_unlocked (pending, message);
02327 _dbus_pending_call_ref_unlocked (pending);
02328 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
02329
02330
02331 _dbus_pending_call_complete (pending);
02332 dbus_pending_call_unref (pending);
02333 }
02334
02335 static dbus_bool_t
02336 check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection,
02337 DBusPendingCall *pending)
02338 {
02339 DBusMessage *reply;
02340 DBusDispatchStatus status;
02341
02342 reply = check_for_reply_unlocked (connection,
02343 _dbus_pending_call_get_reply_serial_unlocked (pending));
02344 if (reply != NULL)
02345 {
02346 _dbus_verbose ("checked for reply\n");
02347
02348 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02349
02350 complete_pending_call_and_unlock (connection, pending, reply);
02351 dbus_message_unref (reply);
02352
02353 CONNECTION_LOCK (connection);
02354 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02355 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02356 dbus_pending_call_unref (pending);
02357
02358 return TRUE;
02359 }
02360
02361 return FALSE;
02362 }
02363
02378 void
02379 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02380 {
02381 long start_tv_sec, start_tv_usec;
02382 long tv_sec, tv_usec;
02383 DBusDispatchStatus status;
02384 DBusConnection *connection;
02385 dbus_uint32_t client_serial;
02386 DBusTimeout *timeout;
02387 int timeout_milliseconds, elapsed_milliseconds;
02388
02389 _dbus_assert (pending != NULL);
02390
02391 if (dbus_pending_call_get_completed (pending))
02392 return;
02393
02394 dbus_pending_call_ref (pending);
02395
02396 connection = _dbus_pending_call_get_connection_and_lock (pending);
02397
02398
02399 _dbus_connection_flush_unlocked (connection);
02400
02401 client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
02402
02403
02404
02405
02406
02407 timeout = _dbus_pending_call_get_timeout_unlocked (pending);
02408 _dbus_get_monotonic_time (&start_tv_sec, &start_tv_usec);
02409 if (timeout)
02410 {
02411 timeout_milliseconds = dbus_timeout_get_interval (timeout);
02412
02413 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n",
02414 timeout_milliseconds,
02415 client_serial,
02416 start_tv_sec, start_tv_usec);
02417 }
02418 else
02419 {
02420 timeout_milliseconds = -1;
02421
02422 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial);
02423 }
02424
02425
02426
02427 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02428 return;
02429
02430
02431
02432 _dbus_connection_do_iteration_unlocked (connection,
02433 pending,
02434 DBUS_ITERATION_DO_READING |
02435 DBUS_ITERATION_BLOCK,
02436 timeout_milliseconds);
02437
02438 recheck_status:
02439
02440 _dbus_verbose ("top of recheck\n");
02441
02442 HAVE_LOCK_CHECK (connection);
02443
02444
02445
02446 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02447
02448
02449
02450
02451 if (_dbus_pending_call_get_completed_unlocked (pending))
02452 {
02453 _dbus_verbose ("Pending call completed by dispatch\n");
02454 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02455 dbus_pending_call_unref (pending);
02456 return;
02457 }
02458
02459 if (status == DBUS_DISPATCH_DATA_REMAINS)
02460 {
02461 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02462 return;
02463 }
02464
02465 _dbus_get_monotonic_time (&tv_sec, &tv_usec);
02466 elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
02467 (tv_usec - start_tv_usec) / 1000;
02468
02469 if (!_dbus_connection_get_is_connected_unlocked (connection))
02470 {
02471 DBusMessage *error_msg;
02472
02473 error_msg = generate_local_error_message (client_serial,
02474 DBUS_ERROR_DISCONNECTED,
02475 "Connection was disconnected before a reply was received");
02476
02477
02478 complete_pending_call_and_unlock (connection, pending, error_msg);
02479 dbus_pending_call_unref (pending);
02480 return;
02481 }
02482 else if (connection->disconnect_message_link == NULL)
02483 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02484 else if (timeout == NULL)
02485 {
02486 if (status == DBUS_DISPATCH_NEED_MEMORY)
02487 {
02488
02489
02490
02491
02492 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02493
02494 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02495 }
02496 else
02497 {
02498
02499 _dbus_connection_do_iteration_unlocked (connection,
02500 pending,
02501 DBUS_ITERATION_DO_READING |
02502 DBUS_ITERATION_BLOCK,
02503 timeout_milliseconds - elapsed_milliseconds);
02504 }
02505
02506 goto recheck_status;
02507 }
02508 else if (tv_sec < start_tv_sec)
02509 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02510 else if (elapsed_milliseconds < timeout_milliseconds)
02511 {
02512 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds);
02513
02514 if (status == DBUS_DISPATCH_NEED_MEMORY)
02515 {
02516
02517
02518
02519
02520 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02521
02522 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02523 }
02524 else
02525 {
02526
02527 _dbus_connection_do_iteration_unlocked (connection,
02528 NULL,
02529 DBUS_ITERATION_DO_READING |
02530 DBUS_ITERATION_BLOCK,
02531 timeout_milliseconds - elapsed_milliseconds);
02532 }
02533
02534 goto recheck_status;
02535 }
02536
02537 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n",
02538 elapsed_milliseconds);
02539
02540 _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
02541
02542
02543 complete_pending_call_and_unlock (connection, pending, NULL);
02544
02545
02546 CONNECTION_LOCK (connection);
02547 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02548 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02549 dbus_pending_call_unref (pending);
02550 }
02551
02557 int
02558 _dbus_connection_get_pending_fds_count (DBusConnection *connection)
02559 {
02560 return _dbus_transport_get_pending_fds_count (connection->transport);
02561 }
02562
02570 void
02571 _dbus_connection_set_pending_fds_function (DBusConnection *connection,
02572 DBusPendingFdsChangeFunction callback,
02573 void *data)
02574 {
02575 _dbus_transport_set_pending_fds_function (connection->transport,
02576 callback, data);
02577 }
02578
02615 DBusConnection*
02616 dbus_connection_open (const char *address,
02617 DBusError *error)
02618 {
02619 DBusConnection *connection;
02620
02621 _dbus_return_val_if_fail (address != NULL, NULL);
02622 _dbus_return_val_if_error_is_set (error, NULL);
02623
02624 connection = _dbus_connection_open_internal (address,
02625 TRUE,
02626 error);
02627
02628 return connection;
02629 }
02630
02658 DBusConnection*
02659 dbus_connection_open_private (const char *address,
02660 DBusError *error)
02661 {
02662 DBusConnection *connection;
02663
02664 _dbus_return_val_if_fail (address != NULL, NULL);
02665 _dbus_return_val_if_error_is_set (error, NULL);
02666
02667 connection = _dbus_connection_open_internal (address,
02668 FALSE,
02669 error);
02670
02671 return connection;
02672 }
02673
02680 DBusConnection *
02681 dbus_connection_ref (DBusConnection *connection)
02682 {
02683 dbus_int32_t old_refcount;
02684
02685 _dbus_return_val_if_fail (connection != NULL, NULL);
02686 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
02687 old_refcount = _dbus_atomic_inc (&connection->refcount);
02688 _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1,
02689 "ref");
02690
02691 return connection;
02692 }
02693
02694 static void
02695 free_outgoing_message (void *element,
02696 void *data)
02697 {
02698 DBusMessage *message = element;
02699 DBusConnection *connection = data;
02700
02701 _dbus_message_remove_counter (message, connection->outgoing_counter);
02702 dbus_message_unref (message);
02703 }
02704
02705
02706
02707
02708
02709 static void
02710 _dbus_connection_last_unref (DBusConnection *connection)
02711 {
02712 DBusList *link;
02713
02714 _dbus_verbose ("Finalizing connection %p\n", connection);
02715
02716 _dbus_assert (_dbus_atomic_get (&connection->refcount) == 0);
02717
02718
02719
02720
02721 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
02722 _dbus_assert (connection->server_guid == NULL);
02723
02724
02725 _dbus_object_tree_free_all_unlocked (connection->objects);
02726
02727 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
02728 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
02729 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
02730 dbus_connection_set_windows_user_function (connection, NULL, NULL, NULL);
02731
02732 _dbus_watch_list_free (connection->watches);
02733 connection->watches = NULL;
02734
02735 _dbus_timeout_list_free (connection->timeouts);
02736 connection->timeouts = NULL;
02737
02738 _dbus_data_slot_list_free (&connection->slot_list);
02739
02740 link = _dbus_list_get_first_link (&connection->filter_list);
02741 while (link != NULL)
02742 {
02743 DBusMessageFilter *filter = link->data;
02744 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
02745
02746 filter->function = NULL;
02747 _dbus_message_filter_unref (filter);
02748 link->data = NULL;
02749
02750 link = next;
02751 }
02752 _dbus_list_clear (&connection->filter_list);
02753
02754
02755
02756 _dbus_object_tree_unref (connection->objects);
02757
02758 _dbus_hash_table_unref (connection->pending_replies);
02759 connection->pending_replies = NULL;
02760
02761 _dbus_list_clear (&connection->filter_list);
02762
02763 _dbus_list_foreach (&connection->outgoing_messages,
02764 free_outgoing_message,
02765 connection);
02766 _dbus_list_clear (&connection->outgoing_messages);
02767
02768 _dbus_list_foreach (&connection->incoming_messages,
02769 (DBusForeachFunction) dbus_message_unref,
02770 NULL);
02771 _dbus_list_clear (&connection->incoming_messages);
02772
02773 _dbus_counter_unref (connection->outgoing_counter);
02774
02775 _dbus_transport_unref (connection->transport);
02776
02777 if (connection->disconnect_message_link)
02778 {
02779 DBusMessage *message = connection->disconnect_message_link->data;
02780 dbus_message_unref (message);
02781 _dbus_list_free_link (connection->disconnect_message_link);
02782 }
02783
02784 _dbus_condvar_free_at_location (&connection->dispatch_cond);
02785 _dbus_condvar_free_at_location (&connection->io_path_cond);
02786
02787 _dbus_cmutex_free_at_location (&connection->io_path_mutex);
02788 _dbus_cmutex_free_at_location (&connection->dispatch_mutex);
02789
02790 _dbus_rmutex_free_at_location (&connection->slot_mutex);
02791
02792 _dbus_rmutex_free_at_location (&connection->mutex);
02793
02794 dbus_free (connection);
02795 }
02796
02816 void
02817 dbus_connection_unref (DBusConnection *connection)
02818 {
02819 dbus_int32_t old_refcount;
02820
02821 _dbus_return_if_fail (connection != NULL);
02822 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02823
02824 old_refcount = _dbus_atomic_dec (&connection->refcount);
02825
02826 _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1,
02827 "unref");
02828
02829 if (old_refcount == 1)
02830 {
02831 #ifndef DBUS_DISABLE_CHECKS
02832 if (_dbus_transport_get_is_connected (connection->transport))
02833 {
02834 _dbus_warn_check_failed ("The last reference on a connection was dropped without closing the connection. This is a bug in an application. See dbus_connection_unref() documentation for details.\n%s",
02835 connection->shareable ?
02836 "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" :
02837 "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
02838 return;
02839 }
02840 #endif
02841 _dbus_connection_last_unref (connection);
02842 }
02843 }
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854 static void
02855 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
02856 {
02857 DBusDispatchStatus status;
02858
02859 HAVE_LOCK_CHECK (connection);
02860
02861 _dbus_verbose ("Disconnecting %p\n", connection);
02862
02863
02864
02865
02866
02867 _dbus_connection_ref_unlocked (connection);
02868
02869 _dbus_transport_disconnect (connection->transport);
02870
02871
02872
02873
02874
02875
02876
02877
02878
02879
02880 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02881
02882
02883 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02884
02885
02886 dbus_connection_unref (connection);
02887 }
02888
02931 void
02932 dbus_connection_close (DBusConnection *connection)
02933 {
02934 _dbus_return_if_fail (connection != NULL);
02935 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02936
02937 CONNECTION_LOCK (connection);
02938
02939 #ifndef DBUS_DISABLE_CHECKS
02940 if (connection->shareable)
02941 {
02942 CONNECTION_UNLOCK (connection);
02943
02944 _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
02945 return;
02946 }
02947 #endif
02948
02949 _dbus_connection_close_possibly_shared_and_unlock (connection);
02950 }
02951
02952 static dbus_bool_t
02953 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
02954 {
02955 HAVE_LOCK_CHECK (connection);
02956 return _dbus_transport_get_is_connected (connection->transport);
02957 }
02958
02972 dbus_bool_t
02973 dbus_connection_get_is_connected (DBusConnection *connection)
02974 {
02975 dbus_bool_t res;
02976
02977 _dbus_return_val_if_fail (connection != NULL, FALSE);
02978
02979 CONNECTION_LOCK (connection);
02980 res = _dbus_connection_get_is_connected_unlocked (connection);
02981 CONNECTION_UNLOCK (connection);
02982
02983 return res;
02984 }
02985
02994 dbus_bool_t
02995 dbus_connection_get_is_authenticated (DBusConnection *connection)
02996 {
02997 dbus_bool_t res;
02998
02999 _dbus_return_val_if_fail (connection != NULL, FALSE);
03000
03001 CONNECTION_LOCK (connection);
03002 res = _dbus_transport_try_to_authenticate (connection->transport);
03003 CONNECTION_UNLOCK (connection);
03004
03005 return res;
03006 }
03007
03028 dbus_bool_t
03029 dbus_connection_get_is_anonymous (DBusConnection *connection)
03030 {
03031 dbus_bool_t res;
03032
03033 _dbus_return_val_if_fail (connection != NULL, FALSE);
03034
03035 CONNECTION_LOCK (connection);
03036 res = _dbus_transport_get_is_anonymous (connection->transport);
03037 CONNECTION_UNLOCK (connection);
03038
03039 return res;
03040 }
03041
03073 char*
03074 dbus_connection_get_server_id (DBusConnection *connection)
03075 {
03076 char *id;
03077
03078 _dbus_return_val_if_fail (connection != NULL, NULL);
03079
03080 CONNECTION_LOCK (connection);
03081 id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
03082 CONNECTION_UNLOCK (connection);
03083
03084 return id;
03085 }
03086
03104 dbus_bool_t
03105 dbus_connection_can_send_type(DBusConnection *connection,
03106 int type)
03107 {
03108 _dbus_return_val_if_fail (connection != NULL, FALSE);
03109
03110 if (!dbus_type_is_valid (type))
03111 return FALSE;
03112
03113 if (type != DBUS_TYPE_UNIX_FD)
03114 return TRUE;
03115
03116 #ifdef HAVE_UNIX_FD_PASSING
03117 {
03118 dbus_bool_t b;
03119
03120 CONNECTION_LOCK(connection);
03121 b = _dbus_transport_can_pass_unix_fd(connection->transport);
03122 CONNECTION_UNLOCK(connection);
03123
03124 return b;
03125 }
03126 #endif
03127
03128 return FALSE;
03129 }
03130
03144 void
03145 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
03146 dbus_bool_t exit_on_disconnect)
03147 {
03148 _dbus_return_if_fail (connection != NULL);
03149
03150 CONNECTION_LOCK (connection);
03151 connection->exit_on_disconnect = exit_on_disconnect != FALSE;
03152 CONNECTION_UNLOCK (connection);
03153 }
03154
03164 DBusPreallocatedSend*
03165 dbus_connection_preallocate_send (DBusConnection *connection)
03166 {
03167 DBusPreallocatedSend *preallocated;
03168
03169 _dbus_return_val_if_fail (connection != NULL, NULL);
03170
03171 CONNECTION_LOCK (connection);
03172
03173 preallocated =
03174 _dbus_connection_preallocate_send_unlocked (connection);
03175
03176 CONNECTION_UNLOCK (connection);
03177
03178 return preallocated;
03179 }
03180
03190 void
03191 dbus_connection_free_preallocated_send (DBusConnection *connection,
03192 DBusPreallocatedSend *preallocated)
03193 {
03194 _dbus_return_if_fail (connection != NULL);
03195 _dbus_return_if_fail (preallocated != NULL);
03196 _dbus_return_if_fail (connection == preallocated->connection);
03197
03198 _dbus_list_free_link (preallocated->queue_link);
03199 _dbus_counter_unref (preallocated->counter_link->data);
03200 _dbus_list_free_link (preallocated->counter_link);
03201 dbus_free (preallocated);
03202 }
03203
03216 void
03217 dbus_connection_send_preallocated (DBusConnection *connection,
03218 DBusPreallocatedSend *preallocated,
03219 DBusMessage *message,
03220 dbus_uint32_t *client_serial)
03221 {
03222 _dbus_return_if_fail (connection != NULL);
03223 _dbus_return_if_fail (preallocated != NULL);
03224 _dbus_return_if_fail (message != NULL);
03225 _dbus_return_if_fail (preallocated->connection == connection);
03226 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
03227 dbus_message_get_member (message) != NULL);
03228 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
03229 (dbus_message_get_interface (message) != NULL &&
03230 dbus_message_get_member (message) != NULL));
03231
03232 CONNECTION_LOCK (connection);
03233
03234 #ifdef HAVE_UNIX_FD_PASSING
03235
03236 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03237 message->n_unix_fds > 0)
03238 {
03239
03240
03241
03242 CONNECTION_UNLOCK (connection);
03243 return;
03244 }
03245
03246 #endif
03247
03248 _dbus_connection_send_preallocated_and_unlock (connection,
03249 preallocated,
03250 message, client_serial);
03251 }
03252
03253 static dbus_bool_t
03254 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
03255 DBusMessage *message,
03256 dbus_uint32_t *client_serial)
03257 {
03258 DBusPreallocatedSend *preallocated;
03259
03260 _dbus_assert (connection != NULL);
03261 _dbus_assert (message != NULL);
03262
03263 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03264 if (preallocated == NULL)
03265 return FALSE;
03266
03267 _dbus_connection_send_preallocated_unlocked_no_update (connection,
03268 preallocated,
03269 message,
03270 client_serial);
03271 return TRUE;
03272 }
03273
03301 dbus_bool_t
03302 dbus_connection_send (DBusConnection *connection,
03303 DBusMessage *message,
03304 dbus_uint32_t *serial)
03305 {
03306 _dbus_return_val_if_fail (connection != NULL, FALSE);
03307 _dbus_return_val_if_fail (message != NULL, FALSE);
03308
03309 CONNECTION_LOCK (connection);
03310
03311 #ifdef HAVE_UNIX_FD_PASSING
03312
03313 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03314 message->n_unix_fds > 0)
03315 {
03316
03317
03318
03319 CONNECTION_UNLOCK (connection);
03320 return FALSE;
03321 }
03322
03323 #endif
03324
03325 return _dbus_connection_send_and_unlock (connection,
03326 message,
03327 serial);
03328 }
03329
03330 static dbus_bool_t
03331 reply_handler_timeout (void *data)
03332 {
03333 DBusConnection *connection;
03334 DBusDispatchStatus status;
03335 DBusPendingCall *pending = data;
03336
03337 connection = _dbus_pending_call_get_connection_and_lock (pending);
03338 _dbus_connection_ref_unlocked (connection);
03339
03340 _dbus_pending_call_queue_timeout_error_unlocked (pending,
03341 connection);
03342 _dbus_connection_remove_timeout_unlocked (connection,
03343 _dbus_pending_call_get_timeout_unlocked (pending));
03344 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
03345
03346 _dbus_verbose ("middle\n");
03347 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03348
03349
03350 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03351 dbus_connection_unref (connection);
03352
03353 return TRUE;
03354 }
03355
03398 dbus_bool_t
03399 dbus_connection_send_with_reply (DBusConnection *connection,
03400 DBusMessage *message,
03401 DBusPendingCall **pending_return,
03402 int timeout_milliseconds)
03403 {
03404 DBusPendingCall *pending;
03405 dbus_int32_t serial = -1;
03406 DBusDispatchStatus status;
03407
03408 _dbus_return_val_if_fail (connection != NULL, FALSE);
03409 _dbus_return_val_if_fail (message != NULL, FALSE);
03410 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03411
03412 if (pending_return)
03413 *pending_return = NULL;
03414
03415 CONNECTION_LOCK (connection);
03416
03417 #ifdef HAVE_UNIX_FD_PASSING
03418
03419 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03420 message->n_unix_fds > 0)
03421 {
03422
03423
03424
03425
03426 CONNECTION_UNLOCK (connection);
03427 return TRUE;
03428 }
03429
03430 #endif
03431
03432 if (!_dbus_connection_get_is_connected_unlocked (connection))
03433 {
03434 CONNECTION_UNLOCK (connection);
03435
03436 return TRUE;
03437 }
03438
03439 pending = _dbus_pending_call_new_unlocked (connection,
03440 timeout_milliseconds,
03441 reply_handler_timeout);
03442
03443 if (pending == NULL)
03444 {
03445 CONNECTION_UNLOCK (connection);
03446 return FALSE;
03447 }
03448
03449
03450 serial = dbus_message_get_serial (message);
03451 if (serial == 0)
03452 {
03453 serial = _dbus_connection_get_next_client_serial (connection);
03454 dbus_message_set_serial (message, serial);
03455 }
03456
03457 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03458 goto error;
03459
03460
03461
03462
03463
03464 if (!_dbus_connection_attach_pending_call_unlocked (connection,
03465 pending))
03466 goto error;
03467
03468 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03469 {
03470 _dbus_connection_detach_pending_call_and_unlock (connection,
03471 pending);
03472 goto error_unlocked;
03473 }
03474
03475 if (pending_return)
03476 *pending_return = pending;
03477 else
03478 {
03479 _dbus_connection_detach_pending_call_unlocked (connection, pending);
03480
03481
03482
03483 }
03484
03485 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03486
03487
03488 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03489
03490 if (pending_return == NULL)
03491 dbus_pending_call_unref (pending);
03492
03493 return TRUE;
03494
03495 error:
03496 CONNECTION_UNLOCK (connection);
03497 error_unlocked:
03498 dbus_pending_call_unref (pending);
03499 return FALSE;
03500 }
03501
03534 DBusMessage*
03535 dbus_connection_send_with_reply_and_block (DBusConnection *connection,
03536 DBusMessage *message,
03537 int timeout_milliseconds,
03538 DBusError *error)
03539 {
03540 DBusMessage *reply;
03541 DBusPendingCall *pending;
03542
03543 _dbus_return_val_if_fail (connection != NULL, NULL);
03544 _dbus_return_val_if_fail (message != NULL, NULL);
03545 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03546 _dbus_return_val_if_error_is_set (error, NULL);
03547
03548 #ifdef HAVE_UNIX_FD_PASSING
03549
03550 CONNECTION_LOCK (connection);
03551 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03552 message->n_unix_fds > 0)
03553 {
03554 CONNECTION_UNLOCK (connection);
03555 dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection.");
03556 return NULL;
03557 }
03558 CONNECTION_UNLOCK (connection);
03559
03560 #endif
03561
03562 if (!dbus_connection_send_with_reply (connection, message,
03563 &pending, timeout_milliseconds))
03564 {
03565 _DBUS_SET_OOM (error);
03566 return NULL;
03567 }
03568
03569 if (pending == NULL)
03570 {
03571 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03572 return NULL;
03573 }
03574
03575 dbus_pending_call_block (pending);
03576
03577 reply = dbus_pending_call_steal_reply (pending);
03578 dbus_pending_call_unref (pending);
03579
03580
03581
03582
03583 _dbus_assert (reply != NULL);
03584
03585 if (dbus_set_error_from_message (error, reply))
03586 {
03587 dbus_message_unref (reply);
03588 return NULL;
03589 }
03590 else
03591 return reply;
03592 }
03593
03602 static DBusDispatchStatus
03603 _dbus_connection_flush_unlocked (DBusConnection *connection)
03604 {
03605
03606
03607
03608
03609
03610 DBusDispatchStatus status;
03611
03612 HAVE_LOCK_CHECK (connection);
03613
03614 while (connection->n_outgoing > 0 &&
03615 _dbus_connection_get_is_connected_unlocked (connection))
03616 {
03617 _dbus_verbose ("doing iteration in\n");
03618 HAVE_LOCK_CHECK (connection);
03619 _dbus_connection_do_iteration_unlocked (connection,
03620 NULL,
03621 DBUS_ITERATION_DO_READING |
03622 DBUS_ITERATION_DO_WRITING |
03623 DBUS_ITERATION_BLOCK,
03624 -1);
03625 }
03626
03627 HAVE_LOCK_CHECK (connection);
03628 _dbus_verbose ("middle\n");
03629 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03630
03631 HAVE_LOCK_CHECK (connection);
03632 return status;
03633 }
03634
03640 void
03641 dbus_connection_flush (DBusConnection *connection)
03642 {
03643
03644
03645
03646
03647
03648 DBusDispatchStatus status;
03649
03650 _dbus_return_if_fail (connection != NULL);
03651
03652 CONNECTION_LOCK (connection);
03653
03654 status = _dbus_connection_flush_unlocked (connection);
03655
03656 HAVE_LOCK_CHECK (connection);
03657
03658 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03659
03660 _dbus_verbose ("end\n");
03661 }
03662
03673 static dbus_bool_t
03674 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03675 int timeout_milliseconds,
03676 dbus_bool_t dispatch)
03677 {
03678 DBusDispatchStatus dstatus;
03679 dbus_bool_t progress_possible;
03680
03681
03682
03683
03684
03685 dbus_connection_ref (connection);
03686 dstatus = dbus_connection_get_dispatch_status (connection);
03687
03688 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03689 {
03690 _dbus_verbose ("doing dispatch\n");
03691 dbus_connection_dispatch (connection);
03692 CONNECTION_LOCK (connection);
03693 }
03694 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03695 {
03696 _dbus_verbose ("pausing for memory\n");
03697 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03698 CONNECTION_LOCK (connection);
03699 }
03700 else
03701 {
03702 CONNECTION_LOCK (connection);
03703 if (_dbus_connection_get_is_connected_unlocked (connection))
03704 {
03705 _dbus_verbose ("doing iteration\n");
03706 _dbus_connection_do_iteration_unlocked (connection,
03707 NULL,
03708 DBUS_ITERATION_DO_READING |
03709 DBUS_ITERATION_DO_WRITING |
03710 DBUS_ITERATION_BLOCK,
03711 timeout_milliseconds);
03712 }
03713 }
03714
03715 HAVE_LOCK_CHECK (connection);
03716
03717
03718
03719
03720 if (dispatch)
03721 progress_possible = connection->n_incoming != 0 ||
03722 connection->disconnect_message_link != NULL;
03723 else
03724 progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03725
03726 CONNECTION_UNLOCK (connection);
03727
03728 dbus_connection_unref (connection);
03729
03730 return progress_possible;
03731 }
03732
03733
03768 dbus_bool_t
03769 dbus_connection_read_write_dispatch (DBusConnection *connection,
03770 int timeout_milliseconds)
03771 {
03772 _dbus_return_val_if_fail (connection != NULL, FALSE);
03773 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03774 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03775 }
03776
03800 dbus_bool_t
03801 dbus_connection_read_write (DBusConnection *connection,
03802 int timeout_milliseconds)
03803 {
03804 _dbus_return_val_if_fail (connection != NULL, FALSE);
03805 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03806 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03807 }
03808
03809
03810
03811
03812
03813
03814 static void
03815 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03816 DBusMessage *head_of_queue)
03817 {
03818 HAVE_LOCK_CHECK (connection);
03819
03820
03821 if (connection->disconnect_message_link == NULL &&
03822 dbus_message_is_signal (head_of_queue,
03823 DBUS_INTERFACE_LOCAL,
03824 "Disconnected"))
03825 {
03826 connection->disconnected_message_arrived = TRUE;
03827 }
03828 }
03829
03849 DBusMessage*
03850 dbus_connection_borrow_message (DBusConnection *connection)
03851 {
03852 DBusDispatchStatus status;
03853 DBusMessage *message;
03854
03855 _dbus_return_val_if_fail (connection != NULL, NULL);
03856
03857 _dbus_verbose ("start\n");
03858
03859
03860
03861
03862 status = dbus_connection_get_dispatch_status (connection);
03863 if (status != DBUS_DISPATCH_DATA_REMAINS)
03864 return NULL;
03865
03866 CONNECTION_LOCK (connection);
03867
03868 _dbus_connection_acquire_dispatch (connection);
03869
03870
03871 _dbus_assert (connection->message_borrowed == NULL);
03872
03873 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03874
03875 message = connection->message_borrowed;
03876
03877 check_disconnected_message_arrived_unlocked (connection, message);
03878
03879
03880 if (message == NULL)
03881 _dbus_connection_release_dispatch (connection);
03882
03883 CONNECTION_UNLOCK (connection);
03884
03885 _dbus_message_trace_ref (message, -1, -1, "dbus_connection_borrow_message");
03886
03887
03888
03889 return message;
03890 }
03891
03900 void
03901 dbus_connection_return_message (DBusConnection *connection,
03902 DBusMessage *message)
03903 {
03904 DBusDispatchStatus status;
03905
03906 _dbus_return_if_fail (connection != NULL);
03907 _dbus_return_if_fail (message != NULL);
03908 _dbus_return_if_fail (message == connection->message_borrowed);
03909 _dbus_return_if_fail (connection->dispatch_acquired);
03910
03911 CONNECTION_LOCK (connection);
03912
03913 _dbus_assert (message == connection->message_borrowed);
03914
03915 connection->message_borrowed = NULL;
03916
03917 _dbus_connection_release_dispatch (connection);
03918
03919 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03920 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03921
03922 _dbus_message_trace_ref (message, -1, -1, "dbus_connection_return_message");
03923 }
03924
03934 void
03935 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03936 DBusMessage *message)
03937 {
03938 DBusMessage *pop_message;
03939 DBusDispatchStatus status;
03940
03941 _dbus_return_if_fail (connection != NULL);
03942 _dbus_return_if_fail (message != NULL);
03943 _dbus_return_if_fail (message == connection->message_borrowed);
03944 _dbus_return_if_fail (connection->dispatch_acquired);
03945
03946 CONNECTION_LOCK (connection);
03947
03948 _dbus_assert (message == connection->message_borrowed);
03949
03950 pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03951 _dbus_assert (message == pop_message);
03952 (void) pop_message;
03953
03954 connection->n_incoming -= 1;
03955
03956 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03957 message, connection->n_incoming);
03958
03959 connection->message_borrowed = NULL;
03960
03961 _dbus_connection_release_dispatch (connection);
03962
03963 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03964 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03965 _dbus_message_trace_ref (message, -1, -1,
03966 "dbus_connection_steal_borrowed_message");
03967 }
03968
03969
03970
03971
03972 static DBusList*
03973 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03974 {
03975 HAVE_LOCK_CHECK (connection);
03976
03977 _dbus_assert (connection->message_borrowed == NULL);
03978
03979 if (connection->n_incoming > 0)
03980 {
03981 DBusList *link;
03982
03983 link = _dbus_list_pop_first_link (&connection->incoming_messages);
03984 connection->n_incoming -= 1;
03985
03986 _dbus_verbose ("Message %p (%s %s %s %s sig:'%s' serial:%u) removed from incoming queue %p, %d incoming\n",
03987 link->data,
03988 dbus_message_type_to_string (dbus_message_get_type (link->data)),
03989 dbus_message_get_path (link->data) ?
03990 dbus_message_get_path (link->data) :
03991 "no path",
03992 dbus_message_get_interface (link->data) ?
03993 dbus_message_get_interface (link->data) :
03994 "no interface",
03995 dbus_message_get_member (link->data) ?
03996 dbus_message_get_member (link->data) :
03997 "no member",
03998 dbus_message_get_signature (link->data),
03999 dbus_message_get_serial (link->data),
04000 connection, connection->n_incoming);
04001
04002 _dbus_message_trace_ref (link->data, -1, -1,
04003 "_dbus_connection_pop_message_link_unlocked");
04004
04005 check_disconnected_message_arrived_unlocked (connection, link->data);
04006
04007 return link;
04008 }
04009 else
04010 return NULL;
04011 }
04012
04013
04014
04015
04016 static DBusMessage*
04017 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
04018 {
04019 DBusList *link;
04020
04021 HAVE_LOCK_CHECK (connection);
04022
04023 link = _dbus_connection_pop_message_link_unlocked (connection);
04024
04025 if (link != NULL)
04026 {
04027 DBusMessage *message;
04028
04029 message = link->data;
04030
04031 _dbus_list_free_link (link);
04032
04033 return message;
04034 }
04035 else
04036 return NULL;
04037 }
04038
04039 static void
04040 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
04041 DBusList *message_link)
04042 {
04043 HAVE_LOCK_CHECK (connection);
04044
04045 _dbus_assert (message_link != NULL);
04046
04047 _dbus_assert (connection->message_borrowed == NULL);
04048
04049 _dbus_assert (connection->dispatch_acquired);
04050
04051 _dbus_list_prepend_link (&connection->incoming_messages,
04052 message_link);
04053 connection->n_incoming += 1;
04054
04055 _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n",
04056 message_link->data,
04057 dbus_message_type_to_string (dbus_message_get_type (message_link->data)),
04058 dbus_message_get_interface (message_link->data) ?
04059 dbus_message_get_interface (message_link->data) :
04060 "no interface",
04061 dbus_message_get_member (message_link->data) ?
04062 dbus_message_get_member (message_link->data) :
04063 "no member",
04064 dbus_message_get_signature (message_link->data),
04065 connection, connection->n_incoming);
04066
04067 _dbus_message_trace_ref (message_link->data, -1, -1,
04068 "_dbus_connection_putback_message_link_unlocked");
04069 }
04070
04090 DBusMessage*
04091 dbus_connection_pop_message (DBusConnection *connection)
04092 {
04093 DBusMessage *message;
04094 DBusDispatchStatus status;
04095
04096 _dbus_verbose ("start\n");
04097
04098
04099
04100
04101 status = dbus_connection_get_dispatch_status (connection);
04102 if (status != DBUS_DISPATCH_DATA_REMAINS)
04103 return NULL;
04104
04105 CONNECTION_LOCK (connection);
04106 _dbus_connection_acquire_dispatch (connection);
04107 HAVE_LOCK_CHECK (connection);
04108
04109 message = _dbus_connection_pop_message_unlocked (connection);
04110
04111 _dbus_verbose ("Returning popped message %p\n", message);
04112
04113 _dbus_connection_release_dispatch (connection);
04114
04115 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04116 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04117
04118 return message;
04119 }
04120
04128 static void
04129 _dbus_connection_acquire_dispatch (DBusConnection *connection)
04130 {
04131 HAVE_LOCK_CHECK (connection);
04132
04133 _dbus_connection_ref_unlocked (connection);
04134 CONNECTION_UNLOCK (connection);
04135
04136 _dbus_verbose ("locking dispatch_mutex\n");
04137 _dbus_cmutex_lock (connection->dispatch_mutex);
04138
04139 while (connection->dispatch_acquired)
04140 {
04141 _dbus_verbose ("waiting for dispatch to be acquirable\n");
04142 _dbus_condvar_wait (connection->dispatch_cond,
04143 connection->dispatch_mutex);
04144 }
04145
04146 _dbus_assert (!connection->dispatch_acquired);
04147
04148 connection->dispatch_acquired = TRUE;
04149
04150 _dbus_verbose ("unlocking dispatch_mutex\n");
04151 _dbus_cmutex_unlock (connection->dispatch_mutex);
04152
04153 CONNECTION_LOCK (connection);
04154 _dbus_connection_unref_unlocked (connection);
04155 }
04156
04164 static void
04165 _dbus_connection_release_dispatch (DBusConnection *connection)
04166 {
04167 HAVE_LOCK_CHECK (connection);
04168
04169 _dbus_verbose ("locking dispatch_mutex\n");
04170 _dbus_cmutex_lock (connection->dispatch_mutex);
04171
04172 _dbus_assert (connection->dispatch_acquired);
04173
04174 connection->dispatch_acquired = FALSE;
04175 _dbus_condvar_wake_one (connection->dispatch_cond);
04176
04177 _dbus_verbose ("unlocking dispatch_mutex\n");
04178 _dbus_cmutex_unlock (connection->dispatch_mutex);
04179 }
04180
04181 static void
04182 _dbus_connection_failed_pop (DBusConnection *connection,
04183 DBusList *message_link)
04184 {
04185 _dbus_list_prepend_link (&connection->incoming_messages,
04186 message_link);
04187 connection->n_incoming += 1;
04188 }
04189
04190
04191 static void
04192 notify_disconnected_unlocked (DBusConnection *connection)
04193 {
04194 HAVE_LOCK_CHECK (connection);
04195
04196
04197
04198
04199
04200
04201
04202 _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
04203
04204
04205
04206
04207
04208 if (connection->n_outgoing > 0)
04209 {
04210 DBusList *link;
04211
04212 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
04213 connection->n_outgoing);
04214
04215 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
04216 {
04217 _dbus_connection_message_sent_unlocked (connection, link->data);
04218 }
04219 }
04220 }
04221
04222
04223 static DBusDispatchStatus
04224 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
04225 {
04226 HAVE_LOCK_CHECK (connection);
04227
04228 if (connection->disconnect_message_link != NULL)
04229 {
04230 _dbus_verbose ("Sending disconnect message\n");
04231
04232
04233
04234
04235 connection_timeout_and_complete_all_pending_calls_unlocked (connection);
04236
04237
04238
04239
04240 _dbus_connection_queue_synthesized_message_link (connection,
04241 connection->disconnect_message_link);
04242 connection->disconnect_message_link = NULL;
04243
04244 return DBUS_DISPATCH_DATA_REMAINS;
04245 }
04246
04247 return DBUS_DISPATCH_COMPLETE;
04248 }
04249
04250 static DBusDispatchStatus
04251 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
04252 {
04253 HAVE_LOCK_CHECK (connection);
04254
04255 if (connection->n_incoming > 0)
04256 return DBUS_DISPATCH_DATA_REMAINS;
04257 else if (!_dbus_transport_queue_messages (connection->transport))
04258 return DBUS_DISPATCH_NEED_MEMORY;
04259 else
04260 {
04261 DBusDispatchStatus status;
04262 dbus_bool_t is_connected;
04263
04264 status = _dbus_transport_get_dispatch_status (connection->transport);
04265 is_connected = _dbus_transport_get_is_connected (connection->transport);
04266
04267 _dbus_verbose ("dispatch status = %s is_connected = %d\n",
04268 DISPATCH_STATUS_NAME (status), is_connected);
04269
04270 if (!is_connected)
04271 {
04272
04273
04274
04275
04276
04277
04278 notify_disconnected_unlocked (connection);
04279
04280
04281
04282
04283
04284
04285 if (status == DBUS_DISPATCH_COMPLETE)
04286 status = notify_disconnected_and_dispatch_complete_unlocked (connection);
04287 }
04288
04289 if (status != DBUS_DISPATCH_COMPLETE)
04290 return status;
04291 else if (connection->n_incoming > 0)
04292 return DBUS_DISPATCH_DATA_REMAINS;
04293 else
04294 return DBUS_DISPATCH_COMPLETE;
04295 }
04296 }
04297
04298 static void
04299 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
04300 DBusDispatchStatus new_status)
04301 {
04302 dbus_bool_t changed;
04303 DBusDispatchStatusFunction function;
04304 void *data;
04305
04306 HAVE_LOCK_CHECK (connection);
04307
04308 _dbus_connection_ref_unlocked (connection);
04309
04310 changed = new_status != connection->last_dispatch_status;
04311
04312 connection->last_dispatch_status = new_status;
04313
04314 function = connection->dispatch_status_function;
04315 data = connection->dispatch_status_data;
04316
04317 if (connection->disconnected_message_arrived &&
04318 !connection->disconnected_message_processed)
04319 {
04320 connection->disconnected_message_processed = TRUE;
04321
04322
04323
04324
04325
04326 connection_forget_shared_unlocked (connection);
04327
04328 if (connection->exit_on_disconnect)
04329 {
04330 CONNECTION_UNLOCK (connection);
04331
04332 _dbus_verbose ("Exiting on Disconnected signal\n");
04333 _dbus_exit (1);
04334 _dbus_assert_not_reached ("Call to exit() returned");
04335 }
04336 }
04337
04338
04339 CONNECTION_UNLOCK (connection);
04340
04341 if (changed && function)
04342 {
04343 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
04344 connection, new_status,
04345 DISPATCH_STATUS_NAME (new_status));
04346 (* function) (connection, new_status, data);
04347 }
04348
04349 dbus_connection_unref (connection);
04350 }
04351
04377 DBusDispatchStatus
04378 dbus_connection_get_dispatch_status (DBusConnection *connection)
04379 {
04380 DBusDispatchStatus status;
04381
04382 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04383
04384 _dbus_verbose ("start\n");
04385
04386 CONNECTION_LOCK (connection);
04387
04388 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04389
04390 CONNECTION_UNLOCK (connection);
04391
04392 return status;
04393 }
04394
04398 static DBusHandlerResult
04399 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
04400 DBusMessage *message)
04401 {
04402 dbus_bool_t sent = FALSE;
04403 DBusMessage *ret = NULL;
04404 DBusList *expire_link;
04405
04406 if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
04407 {
04408
04409 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04410 }
04411
04412 if (!dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04413 {
04414 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04415 }
04416
04417
04418
04419 expire_link = _dbus_list_alloc_link (NULL);
04420
04421 if (!expire_link)
04422 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04423
04424 if (dbus_message_is_method_call (message,
04425 DBUS_INTERFACE_PEER,
04426 "Ping"))
04427 {
04428 ret = dbus_message_new_method_return (message);
04429 if (ret == NULL)
04430 goto out;
04431
04432 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04433 }
04434 else if (dbus_message_is_method_call (message,
04435 DBUS_INTERFACE_PEER,
04436 "GetMachineId"))
04437 {
04438 DBusString uuid;
04439 DBusError error = DBUS_ERROR_INIT;
04440
04441 if (!_dbus_string_init (&uuid))
04442 goto out;
04443
04444 if (_dbus_get_local_machine_uuid_encoded (&uuid, &error))
04445 {
04446 const char *v_STRING;
04447
04448 ret = dbus_message_new_method_return (message);
04449
04450 if (ret == NULL)
04451 {
04452 _dbus_string_free (&uuid);
04453 goto out;
04454 }
04455
04456 v_STRING = _dbus_string_get_const_data (&uuid);
04457 if (dbus_message_append_args (ret,
04458 DBUS_TYPE_STRING, &v_STRING,
04459 DBUS_TYPE_INVALID))
04460 {
04461 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04462 }
04463 }
04464 else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
04465 {
04466 dbus_error_free (&error);
04467 goto out;
04468 }
04469 else
04470 {
04471 ret = dbus_message_new_error (message, error.name, error.message);
04472 dbus_error_free (&error);
04473
04474 if (ret == NULL)
04475 goto out;
04476
04477 sent = _dbus_connection_send_unlocked_no_update (connection, ret,
04478 NULL);
04479 }
04480
04481 _dbus_string_free (&uuid);
04482 }
04483 else
04484 {
04485
04486
04487
04488
04489 ret = dbus_message_new_error (message,
04490 DBUS_ERROR_UNKNOWN_METHOD,
04491 "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04492 if (ret == NULL)
04493 goto out;
04494
04495 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04496 }
04497
04498 out:
04499 if (ret == NULL)
04500 {
04501 _dbus_list_free_link (expire_link);
04502 }
04503 else
04504 {
04505
04506 expire_link->data = ret;
04507 _dbus_list_prepend_link (&connection->expired_messages, expire_link);
04508 }
04509
04510 if (!sent)
04511 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04512
04513 return DBUS_HANDLER_RESULT_HANDLED;
04514 }
04515
04522 static DBusHandlerResult
04523 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04524 DBusMessage *message)
04525 {
04526
04527
04528
04529 return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04530 }
04531
04574 DBusDispatchStatus
04575 dbus_connection_dispatch (DBusConnection *connection)
04576 {
04577 DBusMessage *message;
04578 DBusList *link, *filter_list_copy, *message_link;
04579 DBusHandlerResult result;
04580 DBusPendingCall *pending;
04581 dbus_int32_t reply_serial;
04582 DBusDispatchStatus status;
04583 dbus_bool_t found_object;
04584
04585 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04586
04587 _dbus_verbose ("\n");
04588
04589 CONNECTION_LOCK (connection);
04590 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04591 if (status != DBUS_DISPATCH_DATA_REMAINS)
04592 {
04593
04594 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04595 return status;
04596 }
04597
04598
04599
04600
04601 _dbus_connection_ref_unlocked (connection);
04602
04603 _dbus_connection_acquire_dispatch (connection);
04604 HAVE_LOCK_CHECK (connection);
04605
04606 message_link = _dbus_connection_pop_message_link_unlocked (connection);
04607 if (message_link == NULL)
04608 {
04609
04610
04611 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04612
04613 _dbus_connection_release_dispatch (connection);
04614
04615 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04616
04617 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04618
04619 dbus_connection_unref (connection);
04620
04621 return status;
04622 }
04623
04624 message = message_link->data;
04625
04626 _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n",
04627 message,
04628 dbus_message_type_to_string (dbus_message_get_type (message)),
04629 dbus_message_get_interface (message) ?
04630 dbus_message_get_interface (message) :
04631 "no interface",
04632 dbus_message_get_member (message) ?
04633 dbus_message_get_member (message) :
04634 "no member",
04635 dbus_message_get_signature (message));
04636
04637 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04638
04639
04640
04641
04642
04643
04644
04645
04646 reply_serial = dbus_message_get_reply_serial (message);
04647 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04648 reply_serial);
04649 if (pending)
04650 {
04651 _dbus_verbose ("Dispatching a pending reply\n");
04652 complete_pending_call_and_unlock (connection, pending, message);
04653 pending = NULL;
04654
04655 CONNECTION_LOCK (connection);
04656 _dbus_verbose ("pending call completed in dispatch\n");
04657 result = DBUS_HANDLER_RESULT_HANDLED;
04658 goto out;
04659 }
04660
04661 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04662 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04663 goto out;
04664
04665 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04666 {
04667 _dbus_connection_release_dispatch (connection);
04668 HAVE_LOCK_CHECK (connection);
04669
04670 _dbus_connection_failed_pop (connection, message_link);
04671
04672
04673 _dbus_connection_update_dispatch_status_and_unlock (connection,
04674 DBUS_DISPATCH_NEED_MEMORY);
04675 dbus_connection_unref (connection);
04676
04677 return DBUS_DISPATCH_NEED_MEMORY;
04678 }
04679
04680 _dbus_list_foreach (&filter_list_copy,
04681 (DBusForeachFunction)_dbus_message_filter_ref,
04682 NULL);
04683
04684
04685
04686
04687 CONNECTION_UNLOCK (connection);
04688
04689 link = _dbus_list_get_first_link (&filter_list_copy);
04690 while (link != NULL)
04691 {
04692 DBusMessageFilter *filter = link->data;
04693 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04694
04695 if (filter->function == NULL)
04696 {
04697 _dbus_verbose (" filter was removed in a callback function\n");
04698 link = next;
04699 continue;
04700 }
04701
04702 _dbus_verbose (" running filter on message %p\n", message);
04703 result = (* filter->function) (connection, message, filter->user_data);
04704
04705 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04706 break;
04707
04708 link = next;
04709 }
04710
04711 _dbus_list_foreach (&filter_list_copy,
04712 (DBusForeachFunction)_dbus_message_filter_unref,
04713 NULL);
04714 _dbus_list_clear (&filter_list_copy);
04715
04716 CONNECTION_LOCK (connection);
04717
04718 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04719 {
04720 _dbus_verbose ("No memory\n");
04721 goto out;
04722 }
04723 else if (result == DBUS_HANDLER_RESULT_HANDLED)
04724 {
04725 _dbus_verbose ("filter handled message in dispatch\n");
04726 goto out;
04727 }
04728
04729
04730
04731
04732 _dbus_verbose (" running object path dispatch on message %p (%s %s %s '%s')\n",
04733 message,
04734 dbus_message_type_to_string (dbus_message_get_type (message)),
04735 dbus_message_get_interface (message) ?
04736 dbus_message_get_interface (message) :
04737 "no interface",
04738 dbus_message_get_member (message) ?
04739 dbus_message_get_member (message) :
04740 "no member",
04741 dbus_message_get_signature (message));
04742
04743 HAVE_LOCK_CHECK (connection);
04744 result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04745 message,
04746 &found_object);
04747
04748 CONNECTION_LOCK (connection);
04749
04750 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04751 {
04752 _dbus_verbose ("object tree handled message in dispatch\n");
04753 goto out;
04754 }
04755
04756 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04757 {
04758 DBusMessage *reply;
04759 DBusString str;
04760 DBusPreallocatedSend *preallocated;
04761 DBusList *expire_link;
04762
04763 _dbus_verbose (" sending error %s\n",
04764 DBUS_ERROR_UNKNOWN_METHOD);
04765
04766 if (!_dbus_string_init (&str))
04767 {
04768 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04769 _dbus_verbose ("no memory for error string in dispatch\n");
04770 goto out;
04771 }
04772
04773 if (!_dbus_string_append_printf (&str,
04774 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04775 dbus_message_get_member (message),
04776 dbus_message_get_signature (message),
04777 dbus_message_get_interface (message)))
04778 {
04779 _dbus_string_free (&str);
04780 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04781 _dbus_verbose ("no memory for error string in dispatch\n");
04782 goto out;
04783 }
04784
04785 reply = dbus_message_new_error (message,
04786 found_object ? DBUS_ERROR_UNKNOWN_METHOD : DBUS_ERROR_UNKNOWN_OBJECT,
04787 _dbus_string_get_const_data (&str));
04788 _dbus_string_free (&str);
04789
04790 if (reply == NULL)
04791 {
04792 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04793 _dbus_verbose ("no memory for error reply in dispatch\n");
04794 goto out;
04795 }
04796
04797 expire_link = _dbus_list_alloc_link (reply);
04798
04799 if (expire_link == NULL)
04800 {
04801 dbus_message_unref (reply);
04802 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04803 _dbus_verbose ("no memory for error send in dispatch\n");
04804 goto out;
04805 }
04806
04807 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04808
04809 if (preallocated == NULL)
04810 {
04811 _dbus_list_free_link (expire_link);
04812
04813
04814 dbus_message_unref (reply);
04815 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04816 _dbus_verbose ("no memory for error send in dispatch\n");
04817 goto out;
04818 }
04819
04820 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04821 reply, NULL);
04822
04823 _dbus_list_prepend_link (&connection->expired_messages, expire_link);
04824
04825 result = DBUS_HANDLER_RESULT_HANDLED;
04826 }
04827
04828 _dbus_verbose (" done dispatching %p (%s %s %s '%s') on connection %p\n", message,
04829 dbus_message_type_to_string (dbus_message_get_type (message)),
04830 dbus_message_get_interface (message) ?
04831 dbus_message_get_interface (message) :
04832 "no interface",
04833 dbus_message_get_member (message) ?
04834 dbus_message_get_member (message) :
04835 "no member",
04836 dbus_message_get_signature (message),
04837 connection);
04838
04839 out:
04840 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04841 {
04842 _dbus_verbose ("out of memory\n");
04843
04844
04845
04846
04847
04848 _dbus_connection_putback_message_link_unlocked (connection,
04849 message_link);
04850
04851 message_link = NULL;
04852 message = NULL;
04853 }
04854 else
04855 {
04856 _dbus_verbose (" ... done dispatching\n");
04857 }
04858
04859 _dbus_connection_release_dispatch (connection);
04860 HAVE_LOCK_CHECK (connection);
04861
04862 if (message != NULL)
04863 {
04864
04865
04866
04867
04868
04869
04870
04871 CONNECTION_UNLOCK (connection);
04872 dbus_message_unref (message);
04873 CONNECTION_LOCK (connection);
04874 }
04875
04876 if (message_link != NULL)
04877 _dbus_list_free_link (message_link);
04878
04879 _dbus_verbose ("before final status update\n");
04880 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04881
04882
04883 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04884
04885 dbus_connection_unref (connection);
04886
04887 return status;
04888 }
04889
04951 dbus_bool_t
04952 dbus_connection_set_watch_functions (DBusConnection *connection,
04953 DBusAddWatchFunction add_function,
04954 DBusRemoveWatchFunction remove_function,
04955 DBusWatchToggledFunction toggled_function,
04956 void *data,
04957 DBusFreeFunction free_data_function)
04958 {
04959 dbus_bool_t retval;
04960
04961 _dbus_return_val_if_fail (connection != NULL, FALSE);
04962
04963 CONNECTION_LOCK (connection);
04964
04965 retval = _dbus_watch_list_set_functions (connection->watches,
04966 add_function, remove_function,
04967 toggled_function,
04968 data, free_data_function);
04969
04970 CONNECTION_UNLOCK (connection);
04971
04972 return retval;
04973 }
04974
05014 dbus_bool_t
05015 dbus_connection_set_timeout_functions (DBusConnection *connection,
05016 DBusAddTimeoutFunction add_function,
05017 DBusRemoveTimeoutFunction remove_function,
05018 DBusTimeoutToggledFunction toggled_function,
05019 void *data,
05020 DBusFreeFunction free_data_function)
05021 {
05022 dbus_bool_t retval;
05023
05024 _dbus_return_val_if_fail (connection != NULL, FALSE);
05025
05026 CONNECTION_LOCK (connection);
05027
05028 retval = _dbus_timeout_list_set_functions (connection->timeouts,
05029 add_function, remove_function,
05030 toggled_function,
05031 data, free_data_function);
05032
05033 CONNECTION_UNLOCK (connection);
05034
05035 return retval;
05036 }
05037
05052 void
05053 dbus_connection_set_wakeup_main_function (DBusConnection *connection,
05054 DBusWakeupMainFunction wakeup_main_function,
05055 void *data,
05056 DBusFreeFunction free_data_function)
05057 {
05058 void *old_data;
05059 DBusFreeFunction old_free_data;
05060
05061 _dbus_return_if_fail (connection != NULL);
05062
05063 CONNECTION_LOCK (connection);
05064 old_data = connection->wakeup_main_data;
05065 old_free_data = connection->free_wakeup_main_data;
05066
05067 connection->wakeup_main_function = wakeup_main_function;
05068 connection->wakeup_main_data = data;
05069 connection->free_wakeup_main_data = free_data_function;
05070
05071 CONNECTION_UNLOCK (connection);
05072
05073
05074 if (old_free_data)
05075 (*old_free_data) (old_data);
05076 }
05077
05098 void
05099 dbus_connection_set_dispatch_status_function (DBusConnection *connection,
05100 DBusDispatchStatusFunction function,
05101 void *data,
05102 DBusFreeFunction free_data_function)
05103 {
05104 void *old_data;
05105 DBusFreeFunction old_free_data;
05106
05107 _dbus_return_if_fail (connection != NULL);
05108
05109 CONNECTION_LOCK (connection);
05110 old_data = connection->dispatch_status_data;
05111 old_free_data = connection->free_dispatch_status_data;
05112
05113 connection->dispatch_status_function = function;
05114 connection->dispatch_status_data = data;
05115 connection->free_dispatch_status_data = free_data_function;
05116
05117 CONNECTION_UNLOCK (connection);
05118
05119
05120 if (old_free_data)
05121 (*old_free_data) (old_data);
05122 }
05123
05143 dbus_bool_t
05144 dbus_connection_get_unix_fd (DBusConnection *connection,
05145 int *fd)
05146 {
05147 _dbus_return_val_if_fail (connection != NULL, FALSE);
05148 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
05149
05150 #ifdef DBUS_WIN
05151
05152 return FALSE;
05153 #endif
05154
05155 return dbus_connection_get_socket(connection, fd);
05156 }
05157
05173 dbus_bool_t
05174 dbus_connection_get_socket(DBusConnection *connection,
05175 int *fd)
05176 {
05177 dbus_bool_t retval;
05178 DBusSocket s = DBUS_SOCKET_INIT;
05179
05180 _dbus_return_val_if_fail (connection != NULL, FALSE);
05181 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
05182
05183 CONNECTION_LOCK (connection);
05184
05185 retval = _dbus_transport_get_socket_fd (connection->transport, &s);
05186
05187 if (retval)
05188 {
05189 *fd = _dbus_socket_get_int (s);
05190 }
05191
05192 CONNECTION_UNLOCK (connection);
05193
05194 return retval;
05195 }
05196
05197
05220 dbus_bool_t
05221 dbus_connection_get_unix_user (DBusConnection *connection,
05222 unsigned long *uid)
05223 {
05224 dbus_bool_t result;
05225
05226 _dbus_return_val_if_fail (connection != NULL, FALSE);
05227 _dbus_return_val_if_fail (uid != NULL, FALSE);
05228
05229 CONNECTION_LOCK (connection);
05230
05231 if (!_dbus_transport_try_to_authenticate (connection->transport))
05232 result = FALSE;
05233 else
05234 result = _dbus_transport_get_unix_user (connection->transport,
05235 uid);
05236
05237 #ifdef DBUS_WIN
05238 _dbus_assert (!result);
05239 #endif
05240
05241 CONNECTION_UNLOCK (connection);
05242
05243 return result;
05244 }
05245
05256 dbus_bool_t
05257 dbus_connection_get_unix_process_id (DBusConnection *connection,
05258 unsigned long *pid)
05259 {
05260 dbus_bool_t result;
05261
05262 _dbus_return_val_if_fail (connection != NULL, FALSE);
05263 _dbus_return_val_if_fail (pid != NULL, FALSE);
05264
05265 CONNECTION_LOCK (connection);
05266
05267 if (!_dbus_transport_try_to_authenticate (connection->transport))
05268 result = FALSE;
05269 else
05270 result = _dbus_transport_get_unix_process_id (connection->transport,
05271 pid);
05272
05273 CONNECTION_UNLOCK (connection);
05274
05275 return result;
05276 }
05277
05289 dbus_bool_t
05290 dbus_connection_get_adt_audit_session_data (DBusConnection *connection,
05291 void **data,
05292 dbus_int32_t *data_size)
05293 {
05294 dbus_bool_t result;
05295
05296 _dbus_return_val_if_fail (connection != NULL, FALSE);
05297 _dbus_return_val_if_fail (data != NULL, FALSE);
05298 _dbus_return_val_if_fail (data_size != NULL, FALSE);
05299
05300 CONNECTION_LOCK (connection);
05301
05302 if (!_dbus_transport_try_to_authenticate (connection->transport))
05303 result = FALSE;
05304 else
05305 result = _dbus_transport_get_adt_audit_session_data (connection->transport,
05306 data,
05307 data_size);
05308 CONNECTION_UNLOCK (connection);
05309
05310 return result;
05311 }
05312
05335 void
05336 dbus_connection_set_unix_user_function (DBusConnection *connection,
05337 DBusAllowUnixUserFunction function,
05338 void *data,
05339 DBusFreeFunction free_data_function)
05340 {
05341 void *old_data = NULL;
05342 DBusFreeFunction old_free_function = NULL;
05343
05344 _dbus_return_if_fail (connection != NULL);
05345
05346 CONNECTION_LOCK (connection);
05347 _dbus_transport_set_unix_user_function (connection->transport,
05348 function, data, free_data_function,
05349 &old_data, &old_free_function);
05350 CONNECTION_UNLOCK (connection);
05351
05352 if (old_free_function != NULL)
05353 (* old_free_function) (old_data);
05354 }
05355
05356
05357 dbus_bool_t
05358 _dbus_connection_get_linux_security_label (DBusConnection *connection,
05359 char **label_p)
05360 {
05361 dbus_bool_t result;
05362
05363 _dbus_assert (connection != NULL);
05364 _dbus_assert (label_p != NULL);
05365
05366 CONNECTION_LOCK (connection);
05367
05368 if (!_dbus_transport_try_to_authenticate (connection->transport))
05369 result = FALSE;
05370 else
05371 result = _dbus_transport_get_linux_security_label (connection->transport,
05372 label_p);
05373 #ifndef __linux__
05374 _dbus_assert (!result);
05375 #endif
05376
05377 CONNECTION_UNLOCK (connection);
05378
05379 return result;
05380 }
05381
05413 dbus_bool_t
05414 dbus_connection_get_windows_user (DBusConnection *connection,
05415 char **windows_sid_p)
05416 {
05417 dbus_bool_t result;
05418
05419 _dbus_return_val_if_fail (connection != NULL, FALSE);
05420 _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
05421
05422 CONNECTION_LOCK (connection);
05423
05424 if (!_dbus_transport_try_to_authenticate (connection->transport))
05425 result = FALSE;
05426 else
05427 result = _dbus_transport_get_windows_user (connection->transport,
05428 windows_sid_p);
05429
05430 #ifdef DBUS_UNIX
05431 _dbus_assert (!result);
05432 #endif
05433
05434 CONNECTION_UNLOCK (connection);
05435
05436 return result;
05437 }
05438
05460 void
05461 dbus_connection_set_windows_user_function (DBusConnection *connection,
05462 DBusAllowWindowsUserFunction function,
05463 void *data,
05464 DBusFreeFunction free_data_function)
05465 {
05466 void *old_data = NULL;
05467 DBusFreeFunction old_free_function = NULL;
05468
05469 _dbus_return_if_fail (connection != NULL);
05470
05471 CONNECTION_LOCK (connection);
05472 _dbus_transport_set_windows_user_function (connection->transport,
05473 function, data, free_data_function,
05474 &old_data, &old_free_function);
05475 CONNECTION_UNLOCK (connection);
05476
05477 if (old_free_function != NULL)
05478 (* old_free_function) (old_data);
05479 }
05480
05507 void
05508 dbus_connection_set_allow_anonymous (DBusConnection *connection,
05509 dbus_bool_t value)
05510 {
05511 _dbus_return_if_fail (connection != NULL);
05512
05513 CONNECTION_LOCK (connection);
05514 _dbus_transport_set_allow_anonymous (connection->transport, value);
05515 CONNECTION_UNLOCK (connection);
05516 }
05517
05535 void
05536 dbus_connection_set_route_peer_messages (DBusConnection *connection,
05537 dbus_bool_t value)
05538 {
05539 _dbus_return_if_fail (connection != NULL);
05540
05541 CONNECTION_LOCK (connection);
05542 connection->route_peer_messages = value;
05543 CONNECTION_UNLOCK (connection);
05544 }
05545
05567 dbus_bool_t
05568 dbus_connection_add_filter (DBusConnection *connection,
05569 DBusHandleMessageFunction function,
05570 void *user_data,
05571 DBusFreeFunction free_data_function)
05572 {
05573 DBusMessageFilter *filter;
05574
05575 _dbus_return_val_if_fail (connection != NULL, FALSE);
05576 _dbus_return_val_if_fail (function != NULL, FALSE);
05577
05578 filter = dbus_new0 (DBusMessageFilter, 1);
05579 if (filter == NULL)
05580 return FALSE;
05581
05582 _dbus_atomic_inc (&filter->refcount);
05583
05584 CONNECTION_LOCK (connection);
05585
05586 if (!_dbus_list_append (&connection->filter_list,
05587 filter))
05588 {
05589 _dbus_message_filter_unref (filter);
05590 CONNECTION_UNLOCK (connection);
05591 return FALSE;
05592 }
05593
05594
05595
05596
05597
05598
05599 filter->function = function;
05600 filter->user_data = user_data;
05601 filter->free_user_data_function = free_data_function;
05602
05603 CONNECTION_UNLOCK (connection);
05604 return TRUE;
05605 }
05606
05619 void
05620 dbus_connection_remove_filter (DBusConnection *connection,
05621 DBusHandleMessageFunction function,
05622 void *user_data)
05623 {
05624 DBusList *link;
05625 DBusMessageFilter *filter;
05626
05627 _dbus_return_if_fail (connection != NULL);
05628 _dbus_return_if_fail (function != NULL);
05629
05630 CONNECTION_LOCK (connection);
05631
05632 filter = NULL;
05633
05634 link = _dbus_list_get_last_link (&connection->filter_list);
05635 while (link != NULL)
05636 {
05637 filter = link->data;
05638
05639 if (filter->function == function &&
05640 filter->user_data == user_data)
05641 {
05642 _dbus_list_remove_link (&connection->filter_list, link);
05643 filter->function = NULL;
05644
05645 break;
05646 }
05647
05648 link = _dbus_list_get_prev_link (&connection->filter_list, link);
05649 filter = NULL;
05650 }
05651
05652 CONNECTION_UNLOCK (connection);
05653
05654 #ifndef DBUS_DISABLE_CHECKS
05655 if (filter == NULL)
05656 {
05657 _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05658 function, user_data);
05659 return;
05660 }
05661 #endif
05662
05663
05664 if (filter->free_user_data_function)
05665 (* filter->free_user_data_function) (filter->user_data);
05666
05667 filter->free_user_data_function = NULL;
05668 filter->user_data = NULL;
05669
05670 _dbus_message_filter_unref (filter);
05671 }
05672
05688 static dbus_bool_t
05689 _dbus_connection_register_object_path (DBusConnection *connection,
05690 dbus_bool_t fallback,
05691 const char *path,
05692 const DBusObjectPathVTable *vtable,
05693 void *user_data,
05694 DBusError *error)
05695 {
05696 char **decomposed_path;
05697 dbus_bool_t retval;
05698
05699 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05700 return FALSE;
05701
05702 CONNECTION_LOCK (connection);
05703
05704 retval = _dbus_object_tree_register (connection->objects,
05705 fallback,
05706 (const char **) decomposed_path, vtable,
05707 user_data, error);
05708
05709 CONNECTION_UNLOCK (connection);
05710
05711 dbus_free_string_array (decomposed_path);
05712
05713 return retval;
05714 }
05715
05728 dbus_bool_t
05729 dbus_connection_try_register_object_path (DBusConnection *connection,
05730 const char *path,
05731 const DBusObjectPathVTable *vtable,
05732 void *user_data,
05733 DBusError *error)
05734 {
05735 _dbus_return_val_if_fail (connection != NULL, FALSE);
05736 _dbus_return_val_if_fail (path != NULL, FALSE);
05737 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05738 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05739
05740 return _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, error);
05741 }
05742
05758 dbus_bool_t
05759 dbus_connection_register_object_path (DBusConnection *connection,
05760 const char *path,
05761 const DBusObjectPathVTable *vtable,
05762 void *user_data)
05763 {
05764 dbus_bool_t retval;
05765 DBusError error = DBUS_ERROR_INIT;
05766
05767 _dbus_return_val_if_fail (connection != NULL, FALSE);
05768 _dbus_return_val_if_fail (path != NULL, FALSE);
05769 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05770 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05771
05772 retval = _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, &error);
05773
05774 if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
05775 {
05776 _dbus_warn ("%s\n", error.message);
05777 dbus_error_free (&error);
05778 return FALSE;
05779 }
05780
05781 return retval;
05782 }
05783
05798 dbus_bool_t
05799 dbus_connection_try_register_fallback (DBusConnection *connection,
05800 const char *path,
05801 const DBusObjectPathVTable *vtable,
05802 void *user_data,
05803 DBusError *error)
05804 {
05805 _dbus_return_val_if_fail (connection != NULL, FALSE);
05806 _dbus_return_val_if_fail (path != NULL, FALSE);
05807 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05808 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05809
05810 return _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, error);
05811 }
05812
05830 dbus_bool_t
05831 dbus_connection_register_fallback (DBusConnection *connection,
05832 const char *path,
05833 const DBusObjectPathVTable *vtable,
05834 void *user_data)
05835 {
05836 dbus_bool_t retval;
05837 DBusError error = DBUS_ERROR_INIT;
05838
05839 _dbus_return_val_if_fail (connection != NULL, FALSE);
05840 _dbus_return_val_if_fail (path != NULL, FALSE);
05841 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05842 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05843
05844 retval = _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, &error);
05845
05846 if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
05847 {
05848 _dbus_warn ("%s\n", error.message);
05849 dbus_error_free (&error);
05850 return FALSE;
05851 }
05852
05853 return retval;
05854 }
05855
05865 dbus_bool_t
05866 dbus_connection_unregister_object_path (DBusConnection *connection,
05867 const char *path)
05868 {
05869 char **decomposed_path;
05870
05871 _dbus_return_val_if_fail (connection != NULL, FALSE);
05872 _dbus_return_val_if_fail (path != NULL, FALSE);
05873 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05874
05875 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05876 return FALSE;
05877
05878 CONNECTION_LOCK (connection);
05879
05880 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05881
05882 dbus_free_string_array (decomposed_path);
05883
05884 return TRUE;
05885 }
05886
05897 dbus_bool_t
05898 dbus_connection_get_object_path_data (DBusConnection *connection,
05899 const char *path,
05900 void **data_p)
05901 {
05902 char **decomposed_path;
05903
05904 _dbus_return_val_if_fail (connection != NULL, FALSE);
05905 _dbus_return_val_if_fail (path != NULL, FALSE);
05906 _dbus_return_val_if_fail (data_p != NULL, FALSE);
05907
05908 *data_p = NULL;
05909
05910 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05911 return FALSE;
05912
05913 CONNECTION_LOCK (connection);
05914
05915 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05916
05917 CONNECTION_UNLOCK (connection);
05918
05919 dbus_free_string_array (decomposed_path);
05920
05921 return TRUE;
05922 }
05923
05934 dbus_bool_t
05935 dbus_connection_list_registered (DBusConnection *connection,
05936 const char *parent_path,
05937 char ***child_entries)
05938 {
05939 char **decomposed_path;
05940 dbus_bool_t retval;
05941 _dbus_return_val_if_fail (connection != NULL, FALSE);
05942 _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05943 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05944 _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05945
05946 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05947 return FALSE;
05948
05949 CONNECTION_LOCK (connection);
05950
05951 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05952 (const char **) decomposed_path,
05953 child_entries);
05954 dbus_free_string_array (decomposed_path);
05955
05956 return retval;
05957 }
05958
05959 static DBusDataSlotAllocator slot_allocator =
05960 _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (connection_slots));
05961
05976 dbus_bool_t
05977 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05978 {
05979 return _dbus_data_slot_allocator_alloc (&slot_allocator,
05980 slot_p);
05981 }
05982
05994 void
05995 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05996 {
05997 _dbus_return_if_fail (*slot_p >= 0);
05998
05999 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
06000 }
06001
06024 dbus_bool_t
06025 dbus_connection_set_data (DBusConnection *connection,
06026 dbus_int32_t slot,
06027 void *data,
06028 DBusFreeFunction free_data_func)
06029 {
06030 DBusFreeFunction old_free_func;
06031 void *old_data;
06032 dbus_bool_t retval;
06033
06034 _dbus_return_val_if_fail (connection != NULL, FALSE);
06035 _dbus_return_val_if_fail (slot >= 0, FALSE);
06036
06037 SLOTS_LOCK (connection);
06038
06039 retval = _dbus_data_slot_list_set (&slot_allocator,
06040 &connection->slot_list,
06041 slot, data, free_data_func,
06042 &old_free_func, &old_data);
06043
06044 SLOTS_UNLOCK (connection);
06045
06046 if (retval)
06047 {
06048
06049 if (old_free_func)
06050 (* old_free_func) (old_data);
06051 }
06052
06053 return retval;
06054 }
06055
06073 void*
06074 dbus_connection_get_data (DBusConnection *connection,
06075 dbus_int32_t slot)
06076 {
06077 void *res;
06078
06079 _dbus_return_val_if_fail (connection != NULL, NULL);
06080 _dbus_return_val_if_fail (slot >= 0, NULL);
06081
06082 SLOTS_LOCK (connection);
06083
06084 res = _dbus_data_slot_list_get (&slot_allocator,
06085 &connection->slot_list,
06086 slot);
06087
06088 SLOTS_UNLOCK (connection);
06089
06090 return res;
06091 }
06092
06099 void
06100 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
06101 {
06102 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
06103 }
06104
06113 void
06114 dbus_connection_set_max_message_size (DBusConnection *connection,
06115 long size)
06116 {
06117 _dbus_return_if_fail (connection != NULL);
06118
06119 CONNECTION_LOCK (connection);
06120 _dbus_transport_set_max_message_size (connection->transport,
06121 size);
06122 CONNECTION_UNLOCK (connection);
06123 }
06124
06131 long
06132 dbus_connection_get_max_message_size (DBusConnection *connection)
06133 {
06134 long res;
06135
06136 _dbus_return_val_if_fail (connection != NULL, 0);
06137
06138 CONNECTION_LOCK (connection);
06139 res = _dbus_transport_get_max_message_size (connection->transport);
06140 CONNECTION_UNLOCK (connection);
06141 return res;
06142 }
06143
06152 void
06153 dbus_connection_set_max_message_unix_fds (DBusConnection *connection,
06154 long n)
06155 {
06156 _dbus_return_if_fail (connection != NULL);
06157
06158 CONNECTION_LOCK (connection);
06159 _dbus_transport_set_max_message_unix_fds (connection->transport,
06160 n);
06161 CONNECTION_UNLOCK (connection);
06162 }
06163
06170 long
06171 dbus_connection_get_max_message_unix_fds (DBusConnection *connection)
06172 {
06173 long res;
06174
06175 _dbus_return_val_if_fail (connection != NULL, 0);
06176
06177 CONNECTION_LOCK (connection);
06178 res = _dbus_transport_get_max_message_unix_fds (connection->transport);
06179 CONNECTION_UNLOCK (connection);
06180 return res;
06181 }
06182
06208 void
06209 dbus_connection_set_max_received_size (DBusConnection *connection,
06210 long size)
06211 {
06212 _dbus_return_if_fail (connection != NULL);
06213
06214 CONNECTION_LOCK (connection);
06215 _dbus_transport_set_max_received_size (connection->transport,
06216 size);
06217 CONNECTION_UNLOCK (connection);
06218 }
06219
06226 long
06227 dbus_connection_get_max_received_size (DBusConnection *connection)
06228 {
06229 long res;
06230
06231 _dbus_return_val_if_fail (connection != NULL, 0);
06232
06233 CONNECTION_LOCK (connection);
06234 res = _dbus_transport_get_max_received_size (connection->transport);
06235 CONNECTION_UNLOCK (connection);
06236 return res;
06237 }
06238
06250 void
06251 dbus_connection_set_max_received_unix_fds (DBusConnection *connection,
06252 long n)
06253 {
06254 _dbus_return_if_fail (connection != NULL);
06255
06256 CONNECTION_LOCK (connection);
06257 _dbus_transport_set_max_received_unix_fds (connection->transport,
06258 n);
06259 CONNECTION_UNLOCK (connection);
06260 }
06261
06268 long
06269 dbus_connection_get_max_received_unix_fds (DBusConnection *connection)
06270 {
06271 long res;
06272
06273 _dbus_return_val_if_fail (connection != NULL, 0);
06274
06275 CONNECTION_LOCK (connection);
06276 res = _dbus_transport_get_max_received_unix_fds (connection->transport);
06277 CONNECTION_UNLOCK (connection);
06278 return res;
06279 }
06280
06291 long
06292 dbus_connection_get_outgoing_size (DBusConnection *connection)
06293 {
06294 long res;
06295
06296 _dbus_return_val_if_fail (connection != NULL, 0);
06297
06298 CONNECTION_LOCK (connection);
06299 res = _dbus_counter_get_size_value (connection->outgoing_counter);
06300 CONNECTION_UNLOCK (connection);
06301 return res;
06302 }
06303
06304 #ifdef DBUS_ENABLE_STATS
06305 void
06306 _dbus_connection_get_stats (DBusConnection *connection,
06307 dbus_uint32_t *in_messages,
06308 dbus_uint32_t *in_bytes,
06309 dbus_uint32_t *in_fds,
06310 dbus_uint32_t *in_peak_bytes,
06311 dbus_uint32_t *in_peak_fds,
06312 dbus_uint32_t *out_messages,
06313 dbus_uint32_t *out_bytes,
06314 dbus_uint32_t *out_fds,
06315 dbus_uint32_t *out_peak_bytes,
06316 dbus_uint32_t *out_peak_fds)
06317 {
06318 CONNECTION_LOCK (connection);
06319
06320 if (in_messages != NULL)
06321 *in_messages = connection->n_incoming;
06322
06323 _dbus_transport_get_stats (connection->transport,
06324 in_bytes, in_fds, in_peak_bytes, in_peak_fds);
06325
06326 if (out_messages != NULL)
06327 *out_messages = connection->n_outgoing;
06328
06329 if (out_bytes != NULL)
06330 *out_bytes = _dbus_counter_get_size_value (connection->outgoing_counter);
06331
06332 if (out_fds != NULL)
06333 *out_fds = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
06334
06335 if (out_peak_bytes != NULL)
06336 *out_peak_bytes = _dbus_counter_get_peak_size_value (connection->outgoing_counter);
06337
06338 if (out_peak_fds != NULL)
06339 *out_peak_fds = _dbus_counter_get_peak_unix_fd_value (connection->outgoing_counter);
06340
06341 CONNECTION_UNLOCK (connection);
06342 }
06343 #endif
06344
06352 long
06353 dbus_connection_get_outgoing_unix_fds (DBusConnection *connection)
06354 {
06355 long res;
06356
06357 _dbus_return_val_if_fail (connection != NULL, 0);
06358
06359 CONNECTION_LOCK (connection);
06360 res = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
06361 CONNECTION_UNLOCK (connection);
06362 return res;
06363 }
06364
06365 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
06366
06372 const char*
06373 _dbus_connection_get_address (DBusConnection *connection)
06374 {
06375 return _dbus_transport_get_address (connection->transport);
06376 }
06377 #endif
06378