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-list.h"
00033 #include "dbus-hash.h"
00034 #include "dbus-message-internal.h"
00035 #include "dbus-threads.h"
00036 #include "dbus-protocol.h"
00037 #include "dbus-dataslot.h"
00038 #include "dbus-string.h"
00039 #include "dbus-pending-call.h"
00040 #include "dbus-object-tree.h"
00041 #include "dbus-threads-internal.h"
00042
00043 #ifdef DBUS_DISABLE_CHECKS
00044 #define TOOK_LOCK_CHECK(connection)
00045 #define RELEASING_LOCK_CHECK(connection)
00046 #define HAVE_LOCK_CHECK(connection)
00047 #else
00048 #define TOOK_LOCK_CHECK(connection) do { \
00049 _dbus_assert (!(connection)->have_connection_lock); \
00050 (connection)->have_connection_lock = TRUE; \
00051 } while (0)
00052 #define RELEASING_LOCK_CHECK(connection) do { \
00053 _dbus_assert ((connection)->have_connection_lock); \
00054 (connection)->have_connection_lock = FALSE; \
00055 } while (0)
00056 #define HAVE_LOCK_CHECK(connection) _dbus_assert ((connection)->have_connection_lock)
00057
00058 #endif
00059
00060 #define TRACE_LOCKS 1
00061
00062 #define CONNECTION_LOCK(connection) do { \
00063 if (TRACE_LOCKS) { _dbus_verbose (" LOCK: %s\n", _DBUS_FUNCTION_NAME); } \
00064 _dbus_mutex_lock ((connection)->mutex); \
00065 TOOK_LOCK_CHECK (connection); \
00066 } while (0)
00067
00068 #define CONNECTION_UNLOCK(connection) do { \
00069 if (TRACE_LOCKS) { _dbus_verbose (" UNLOCK: %s\n", _DBUS_FUNCTION_NAME); } \
00070 RELEASING_LOCK_CHECK (connection); \
00071 _dbus_mutex_unlock ((connection)->mutex); \
00072 } while (0)
00073
00074 #define DISPATCH_STATUS_NAME(s) \
00075 ((s) == DBUS_DISPATCH_COMPLETE ? "complete" : \
00076 (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
00077 (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" : \
00078 "???")
00079
00157 typedef struct DBusMessageFilter DBusMessageFilter;
00158
00162 struct DBusMessageFilter
00163 {
00164 DBusAtomic refcount;
00165 DBusHandleMessageFunction function;
00166 void *user_data;
00167 DBusFreeFunction free_user_data_function;
00168 };
00169
00170
00174 struct DBusPreallocatedSend
00175 {
00176 DBusConnection *connection;
00177 DBusList *queue_link;
00178 DBusList *counter_link;
00179 };
00180
00181 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00182
00186 struct DBusConnection
00187 {
00188 DBusAtomic refcount;
00190 DBusMutex *mutex;
00192 DBusMutex *dispatch_mutex;
00193 DBusCondVar *dispatch_cond;
00194 DBusMutex *io_path_mutex;
00195 DBusCondVar *io_path_cond;
00197 DBusList *outgoing_messages;
00198 DBusList *incoming_messages;
00200 DBusMessage *message_borrowed;
00204 int n_outgoing;
00205 int n_incoming;
00207 DBusCounter *outgoing_counter;
00209 DBusTransport *transport;
00210 DBusWatchList *watches;
00211 DBusTimeoutList *timeouts;
00213 DBusList *filter_list;
00215 DBusDataSlotList slot_list;
00217 DBusHashTable *pending_replies;
00219 dbus_uint32_t client_serial;
00220 DBusList *disconnect_message_link;
00222 DBusWakeupMainFunction wakeup_main_function;
00223 void *wakeup_main_data;
00224 DBusFreeFunction free_wakeup_main_data;
00226 DBusDispatchStatusFunction dispatch_status_function;
00227 void *dispatch_status_data;
00228 DBusFreeFunction free_dispatch_status_data;
00230 DBusDispatchStatus last_dispatch_status;
00232 DBusList *link_cache;
00235 DBusObjectTree *objects;
00237 char *server_guid;
00239 unsigned int shareable : 1;
00241 unsigned int dispatch_acquired : 1;
00242 unsigned int io_path_acquired : 1;
00244 unsigned int exit_on_disconnect : 1;
00246 #ifndef DBUS_DISABLE_CHECKS
00247 unsigned int have_connection_lock : 1;
00248 #endif
00249
00250 #ifndef DBUS_DISABLE_CHECKS
00251 int generation;
00252 #endif
00253 };
00254
00255 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection);
00256 static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
00257 DBusDispatchStatus new_status);
00258 static void _dbus_connection_last_unref (DBusConnection *connection);
00259 static void _dbus_connection_acquire_dispatch (DBusConnection *connection);
00260 static void _dbus_connection_release_dispatch (DBusConnection *connection);
00261
00262 static DBusMessageFilter *
00263 _dbus_message_filter_ref (DBusMessageFilter *filter)
00264 {
00265 _dbus_assert (filter->refcount.value > 0);
00266 _dbus_atomic_inc (&filter->refcount);
00267
00268 return filter;
00269 }
00270
00271 static void
00272 _dbus_message_filter_unref (DBusMessageFilter *filter)
00273 {
00274 _dbus_assert (filter->refcount.value > 0);
00275
00276 if (_dbus_atomic_dec (&filter->refcount) == 1)
00277 {
00278 if (filter->free_user_data_function)
00279 (* filter->free_user_data_function) (filter->user_data);
00280
00281 dbus_free (filter);
00282 }
00283 }
00284
00290 void
00291 _dbus_connection_lock (DBusConnection *connection)
00292 {
00293 CONNECTION_LOCK (connection);
00294 }
00295
00301 void
00302 _dbus_connection_unlock (DBusConnection *connection)
00303 {
00304 CONNECTION_UNLOCK (connection);
00305 }
00306
00314 static void
00315 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00316 {
00317 if (connection->wakeup_main_function)
00318 (*connection->wakeup_main_function) (connection->wakeup_main_data);
00319 }
00320
00321 #ifdef DBUS_BUILD_TESTS
00322
00332 dbus_bool_t
00333 _dbus_connection_queue_received_message (DBusConnection *connection,
00334 DBusMessage *message)
00335 {
00336 DBusList *link;
00337
00338 link = _dbus_list_alloc_link (message);
00339 if (link == NULL)
00340 return FALSE;
00341
00342 dbus_message_ref (message);
00343 _dbus_connection_queue_received_message_link (connection, link);
00344
00345 return TRUE;
00346 }
00347 #endif
00348
00357 void
00358 _dbus_connection_queue_received_message_link (DBusConnection *connection,
00359 DBusList *link)
00360 {
00361 DBusPendingCall *pending;
00362 dbus_int32_t reply_serial;
00363 DBusMessage *message;
00364
00365 _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00366
00367 _dbus_list_append_link (&connection->incoming_messages,
00368 link);
00369 message = link->data;
00370
00371
00372 reply_serial = dbus_message_get_reply_serial (message);
00373 if (reply_serial != -1)
00374 {
00375 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00376 reply_serial);
00377 if (pending != NULL)
00378 {
00379 if (pending->timeout_added)
00380 _dbus_connection_remove_timeout (connection,
00381 pending->timeout);
00382
00383 pending->timeout_added = FALSE;
00384 }
00385 }
00386
00387 connection->n_incoming += 1;
00388
00389 _dbus_connection_wakeup_mainloop (connection);
00390
00391 _dbus_verbose ("Message %p (%d %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00392 message,
00393 dbus_message_get_type (message),
00394 dbus_message_get_path (message),
00395 dbus_message_get_interface (message) ?
00396 dbus_message_get_interface (message) :
00397 "no interface",
00398 dbus_message_get_member (message) ?
00399 dbus_message_get_member (message) :
00400 "no member",
00401 dbus_message_get_signature (message),
00402 dbus_message_get_reply_serial (message),
00403 connection,
00404 connection->n_incoming);
00405 }
00406
00417 static void
00418 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00419 DBusList *link)
00420 {
00421 HAVE_LOCK_CHECK (connection);
00422
00423 _dbus_list_append_link (&connection->incoming_messages, link);
00424
00425 connection->n_incoming += 1;
00426
00427 _dbus_connection_wakeup_mainloop (connection);
00428
00429 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00430 link->data, connection, connection->n_incoming);
00431 }
00432
00433
00441 dbus_bool_t
00442 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00443 {
00444 HAVE_LOCK_CHECK (connection);
00445 return connection->outgoing_messages != NULL;
00446 }
00447
00454 dbus_bool_t
00455 dbus_connection_has_messages_to_send (DBusConnection *connection)
00456 {
00457 dbus_bool_t v;
00458
00459 _dbus_return_val_if_fail (connection != NULL, FALSE);
00460
00461 CONNECTION_LOCK (connection);
00462 v = _dbus_connection_has_messages_to_send_unlocked (connection);
00463 CONNECTION_UNLOCK (connection);
00464
00465 return v;
00466 }
00467
00475 DBusMessage*
00476 _dbus_connection_get_message_to_send (DBusConnection *connection)
00477 {
00478 HAVE_LOCK_CHECK (connection);
00479
00480 return _dbus_list_get_last (&connection->outgoing_messages);
00481 }
00482
00491 void
00492 _dbus_connection_message_sent (DBusConnection *connection,
00493 DBusMessage *message)
00494 {
00495 DBusList *link;
00496
00497 HAVE_LOCK_CHECK (connection);
00498
00499
00500
00501
00502
00503
00504 link = _dbus_list_get_last_link (&connection->outgoing_messages);
00505 _dbus_assert (link != NULL);
00506 _dbus_assert (link->data == message);
00507
00508
00509 _dbus_list_unlink (&connection->outgoing_messages,
00510 link);
00511 _dbus_list_prepend_link (&connection->link_cache, link);
00512
00513 connection->n_outgoing -= 1;
00514
00515 _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00516 message,
00517 dbus_message_get_type (message),
00518 dbus_message_get_path (message),
00519 dbus_message_get_interface (message) ?
00520 dbus_message_get_interface (message) :
00521 "no interface",
00522 dbus_message_get_member (message) ?
00523 dbus_message_get_member (message) :
00524 "no member",
00525 dbus_message_get_signature (message),
00526 connection, connection->n_outgoing);
00527
00528
00529 _dbus_message_remove_size_counter (message, connection->outgoing_counter,
00530 &link);
00531 _dbus_list_prepend_link (&connection->link_cache, link);
00532
00533 dbus_message_unref (message);
00534 }
00535
00536 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list,
00537 DBusWatch *watch);
00538 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list,
00539 DBusWatch *watch);
00540 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list,
00541 DBusWatch *watch,
00542 dbus_bool_t enabled);
00543
00544 static dbus_bool_t
00545 protected_change_watch (DBusConnection *connection,
00546 DBusWatch *watch,
00547 DBusWatchAddFunction add_function,
00548 DBusWatchRemoveFunction remove_function,
00549 DBusWatchToggleFunction toggle_function,
00550 dbus_bool_t enabled)
00551 {
00552 DBusWatchList *watches;
00553 dbus_bool_t retval;
00554
00555 HAVE_LOCK_CHECK (connection);
00556
00557
00558
00559
00560
00561 watches = connection->watches;
00562 if (watches)
00563 {
00564 connection->watches = NULL;
00565 _dbus_connection_ref_unlocked (connection);
00566 CONNECTION_UNLOCK (connection);
00567
00568 if (add_function)
00569 retval = (* add_function) (watches, watch);
00570 else if (remove_function)
00571 {
00572 retval = TRUE;
00573 (* remove_function) (watches, watch);
00574 }
00575 else
00576 {
00577 retval = TRUE;
00578 (* toggle_function) (watches, watch, enabled);
00579 }
00580
00581 CONNECTION_LOCK (connection);
00582 connection->watches = watches;
00583 _dbus_connection_unref_unlocked (connection);
00584
00585 return retval;
00586 }
00587 else
00588 return FALSE;
00589 }
00590
00591
00602 dbus_bool_t
00603 _dbus_connection_add_watch (DBusConnection *connection,
00604 DBusWatch *watch)
00605 {
00606 return protected_change_watch (connection, watch,
00607 _dbus_watch_list_add_watch,
00608 NULL, NULL, FALSE);
00609 }
00610
00619 void
00620 _dbus_connection_remove_watch (DBusConnection *connection,
00621 DBusWatch *watch)
00622 {
00623 protected_change_watch (connection, watch,
00624 NULL,
00625 _dbus_watch_list_remove_watch,
00626 NULL, FALSE);
00627 }
00628
00639 void
00640 _dbus_connection_toggle_watch (DBusConnection *connection,
00641 DBusWatch *watch,
00642 dbus_bool_t enabled)
00643 {
00644 _dbus_assert (watch != NULL);
00645
00646 protected_change_watch (connection, watch,
00647 NULL, NULL,
00648 _dbus_watch_list_toggle_watch,
00649 enabled);
00650 }
00651
00652 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list,
00653 DBusTimeout *timeout);
00654 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00655 DBusTimeout *timeout);
00656 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00657 DBusTimeout *timeout,
00658 dbus_bool_t enabled);
00659
00660 static dbus_bool_t
00661 protected_change_timeout (DBusConnection *connection,
00662 DBusTimeout *timeout,
00663 DBusTimeoutAddFunction add_function,
00664 DBusTimeoutRemoveFunction remove_function,
00665 DBusTimeoutToggleFunction toggle_function,
00666 dbus_bool_t enabled)
00667 {
00668 DBusTimeoutList *timeouts;
00669 dbus_bool_t retval;
00670
00671 HAVE_LOCK_CHECK (connection);
00672
00673
00674
00675
00676
00677 timeouts = connection->timeouts;
00678 if (timeouts)
00679 {
00680 connection->timeouts = NULL;
00681 _dbus_connection_ref_unlocked (connection);
00682 CONNECTION_UNLOCK (connection);
00683
00684 if (add_function)
00685 retval = (* add_function) (timeouts, timeout);
00686 else if (remove_function)
00687 {
00688 retval = TRUE;
00689 (* remove_function) (timeouts, timeout);
00690 }
00691 else
00692 {
00693 retval = TRUE;
00694 (* toggle_function) (timeouts, timeout, enabled);
00695 }
00696
00697 CONNECTION_LOCK (connection);
00698 connection->timeouts = timeouts;
00699 _dbus_connection_unref_unlocked (connection);
00700
00701 return retval;
00702 }
00703 else
00704 return FALSE;
00705 }
00706
00718 dbus_bool_t
00719 _dbus_connection_add_timeout (DBusConnection *connection,
00720 DBusTimeout *timeout)
00721 {
00722 return protected_change_timeout (connection, timeout,
00723 _dbus_timeout_list_add_timeout,
00724 NULL, NULL, FALSE);
00725 }
00726
00735 void
00736 _dbus_connection_remove_timeout (DBusConnection *connection,
00737 DBusTimeout *timeout)
00738 {
00739 protected_change_timeout (connection, timeout,
00740 NULL,
00741 _dbus_timeout_list_remove_timeout,
00742 NULL, FALSE);
00743 }
00744
00754 void
00755 _dbus_connection_toggle_timeout (DBusConnection *connection,
00756 DBusTimeout *timeout,
00757 dbus_bool_t enabled)
00758 {
00759 protected_change_timeout (connection, timeout,
00760 NULL, NULL,
00761 _dbus_timeout_list_toggle_timeout,
00762 enabled);
00763 }
00764
00765 static dbus_bool_t
00766 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection,
00767 DBusPendingCall *pending)
00768 {
00769 HAVE_LOCK_CHECK (connection);
00770
00771 _dbus_assert (pending->reply_serial != 0);
00772
00773 if (!_dbus_connection_add_timeout (connection, pending->timeout))
00774 return FALSE;
00775
00776 if (!_dbus_hash_table_insert_int (connection->pending_replies,
00777 pending->reply_serial,
00778 pending))
00779 {
00780 _dbus_connection_remove_timeout (connection, pending->timeout);
00781
00782 HAVE_LOCK_CHECK (connection);
00783 return FALSE;
00784 }
00785
00786 pending->timeout_added = TRUE;
00787 pending->connection = connection;
00788
00789 dbus_pending_call_ref (pending);
00790
00791 HAVE_LOCK_CHECK (connection);
00792
00793 return TRUE;
00794 }
00795
00796 static void
00797 free_pending_call_on_hash_removal (void *data)
00798 {
00799 DBusPendingCall *pending;
00800
00801 if (data == NULL)
00802 return;
00803
00804 pending = data;
00805
00806 if (pending->connection)
00807 {
00808 if (pending->timeout_added)
00809 {
00810 _dbus_connection_remove_timeout (pending->connection,
00811 pending->timeout);
00812 pending->timeout_added = FALSE;
00813 }
00814
00815 pending->connection = NULL;
00816
00817 dbus_pending_call_unref (pending);
00818 }
00819 }
00820
00821 static void
00822 _dbus_connection_detach_pending_call_unlocked (DBusConnection *connection,
00823 DBusPendingCall *pending)
00824 {
00825
00826
00827 dbus_pending_call_ref (pending);
00828 _dbus_hash_table_remove_int (connection->pending_replies,
00829 pending->reply_serial);
00830 _dbus_assert (pending->connection == NULL);
00831 dbus_pending_call_unref (pending);
00832 }
00833
00834 static void
00835 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection,
00836 DBusPendingCall *pending)
00837 {
00838
00839
00840
00841
00842 dbus_pending_call_ref (pending);
00843 _dbus_hash_table_remove_int (connection->pending_replies,
00844 pending->reply_serial);
00845 _dbus_assert (pending->connection == NULL);
00846 CONNECTION_UNLOCK (connection);
00847 dbus_pending_call_unref (pending);
00848 }
00849
00858 void
00859 _dbus_connection_remove_pending_call (DBusConnection *connection,
00860 DBusPendingCall *pending)
00861 {
00862 CONNECTION_LOCK (connection);
00863 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
00864 }
00865
00874 void
00875 _dbus_pending_call_complete_and_unlock (DBusPendingCall *pending,
00876 DBusMessage *message)
00877 {
00878 if (message == NULL)
00879 {
00880 message = pending->timeout_link->data;
00881 _dbus_list_clear (&pending->timeout_link);
00882 }
00883 else
00884 dbus_message_ref (message);
00885
00886 _dbus_verbose (" handing message %p (%s) to pending call serial %u\n",
00887 message,
00888 dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN ?
00889 "method return" :
00890 dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ?
00891 "error" : "other type",
00892 pending->reply_serial);
00893
00894 _dbus_assert (pending->reply == NULL);
00895 _dbus_assert (pending->reply_serial == dbus_message_get_reply_serial (message));
00896 pending->reply = message;
00897
00898 dbus_pending_call_ref (pending);
00899 _dbus_connection_detach_pending_call_and_unlock (pending->connection, pending);
00900
00901
00902 _dbus_pending_call_notify (pending);
00903 dbus_pending_call_unref (pending);
00904 }
00905
00915 static dbus_bool_t
00916 _dbus_connection_acquire_io_path (DBusConnection *connection,
00917 int timeout_milliseconds)
00918 {
00919 dbus_bool_t we_acquired;
00920
00921 HAVE_LOCK_CHECK (connection);
00922
00923
00924 _dbus_connection_ref_unlocked (connection);
00925
00926
00927 CONNECTION_UNLOCK (connection);
00928
00929 _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00930 _dbus_mutex_lock (connection->io_path_mutex);
00931
00932 _dbus_verbose ("%s start connection->io_path_acquired = %d timeout = %d\n",
00933 _DBUS_FUNCTION_NAME, connection->io_path_acquired, timeout_milliseconds);
00934
00935 we_acquired = FALSE;
00936
00937 if (connection->io_path_acquired)
00938 {
00939 if (timeout_milliseconds != -1)
00940 {
00941 _dbus_verbose ("%s waiting %d for IO path to be acquirable\n",
00942 _DBUS_FUNCTION_NAME, timeout_milliseconds);
00943 _dbus_condvar_wait_timeout (connection->io_path_cond,
00944 connection->io_path_mutex,
00945 timeout_milliseconds);
00946 }
00947 else
00948 {
00949 while (connection->io_path_acquired)
00950 {
00951 _dbus_verbose ("%s waiting for IO path to be acquirable\n", _DBUS_FUNCTION_NAME);
00952 _dbus_condvar_wait (connection->io_path_cond, connection->io_path_mutex);
00953 }
00954 }
00955 }
00956
00957 if (!connection->io_path_acquired)
00958 {
00959 we_acquired = TRUE;
00960 connection->io_path_acquired = TRUE;
00961 }
00962
00963 _dbus_verbose ("%s end connection->io_path_acquired = %d we_acquired = %d\n",
00964 _DBUS_FUNCTION_NAME, connection->io_path_acquired, we_acquired);
00965
00966 _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00967 _dbus_mutex_unlock (connection->io_path_mutex);
00968
00969 CONNECTION_LOCK (connection);
00970
00971 HAVE_LOCK_CHECK (connection);
00972
00973 _dbus_connection_unref_unlocked (connection);
00974
00975 return we_acquired;
00976 }
00977
00985 static void
00986 _dbus_connection_release_io_path (DBusConnection *connection)
00987 {
00988 HAVE_LOCK_CHECK (connection);
00989
00990 _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00991 _dbus_mutex_lock (connection->io_path_mutex);
00992
00993 _dbus_assert (connection->io_path_acquired);
00994
00995 _dbus_verbose ("%s start connection->io_path_acquired = %d\n",
00996 _DBUS_FUNCTION_NAME, connection->io_path_acquired);
00997
00998 connection->io_path_acquired = FALSE;
00999 _dbus_condvar_wake_one (connection->io_path_cond);
01000
01001 _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01002 _dbus_mutex_unlock (connection->io_path_mutex);
01003 }
01004
01033 void
01034 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01035 unsigned int flags,
01036 int timeout_milliseconds)
01037 {
01038 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01039
01040 HAVE_LOCK_CHECK (connection);
01041
01042 if (connection->n_outgoing == 0)
01043 flags &= ~DBUS_ITERATION_DO_WRITING;
01044
01045 if (_dbus_connection_acquire_io_path (connection,
01046 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01047 {
01048 HAVE_LOCK_CHECK (connection);
01049
01050 _dbus_transport_do_iteration (connection->transport,
01051 flags, timeout_milliseconds);
01052 _dbus_connection_release_io_path (connection);
01053 }
01054
01055 HAVE_LOCK_CHECK (connection);
01056
01057 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01058 }
01059
01069 DBusConnection*
01070 _dbus_connection_new_for_transport (DBusTransport *transport)
01071 {
01072 DBusConnection *connection;
01073 DBusWatchList *watch_list;
01074 DBusTimeoutList *timeout_list;
01075 DBusHashTable *pending_replies;
01076 DBusMutex *mutex;
01077 DBusMutex *io_path_mutex;
01078 DBusMutex *dispatch_mutex;
01079 DBusCondVar *dispatch_cond;
01080 DBusCondVar *io_path_cond;
01081 DBusList *disconnect_link;
01082 DBusMessage *disconnect_message;
01083 DBusCounter *outgoing_counter;
01084 DBusObjectTree *objects;
01085
01086 watch_list = NULL;
01087 connection = NULL;
01088 pending_replies = NULL;
01089 timeout_list = NULL;
01090 mutex = NULL;
01091 io_path_mutex = NULL;
01092 dispatch_mutex = NULL;
01093 dispatch_cond = NULL;
01094 io_path_cond = NULL;
01095 disconnect_link = NULL;
01096 disconnect_message = NULL;
01097 outgoing_counter = NULL;
01098 objects = NULL;
01099
01100 watch_list = _dbus_watch_list_new ();
01101 if (watch_list == NULL)
01102 goto error;
01103
01104 timeout_list = _dbus_timeout_list_new ();
01105 if (timeout_list == NULL)
01106 goto error;
01107
01108 pending_replies =
01109 _dbus_hash_table_new (DBUS_HASH_INT,
01110 NULL,
01111 (DBusFreeFunction)free_pending_call_on_hash_removal);
01112 if (pending_replies == NULL)
01113 goto error;
01114
01115 connection = dbus_new0 (DBusConnection, 1);
01116 if (connection == NULL)
01117 goto error;
01118
01119 mutex = _dbus_mutex_new ();
01120 if (mutex == NULL)
01121 goto error;
01122
01123 io_path_mutex = _dbus_mutex_new ();
01124 if (io_path_mutex == NULL)
01125 goto error;
01126
01127 dispatch_mutex = _dbus_mutex_new ();
01128 if (dispatch_mutex == NULL)
01129 goto error;
01130
01131 dispatch_cond = _dbus_condvar_new ();
01132 if (dispatch_cond == NULL)
01133 goto error;
01134
01135 io_path_cond = _dbus_condvar_new ();
01136 if (io_path_cond == NULL)
01137 goto error;
01138
01139 disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01140 DBUS_INTERFACE_LOCAL,
01141 "Disconnected");
01142
01143 if (disconnect_message == NULL)
01144 goto error;
01145
01146 disconnect_link = _dbus_list_alloc_link (disconnect_message);
01147 if (disconnect_link == NULL)
01148 goto error;
01149
01150 outgoing_counter = _dbus_counter_new ();
01151 if (outgoing_counter == NULL)
01152 goto error;
01153
01154 objects = _dbus_object_tree_new (connection);
01155 if (objects == NULL)
01156 goto error;
01157
01158 if (_dbus_modify_sigpipe)
01159 _dbus_disable_sigpipe ();
01160
01161 connection->refcount.value = 1;
01162 connection->mutex = mutex;
01163 connection->dispatch_cond = dispatch_cond;
01164 connection->dispatch_mutex = dispatch_mutex;
01165 connection->io_path_cond = io_path_cond;
01166 connection->io_path_mutex = io_path_mutex;
01167 connection->transport = transport;
01168 connection->watches = watch_list;
01169 connection->timeouts = timeout_list;
01170 connection->pending_replies = pending_replies;
01171 connection->outgoing_counter = outgoing_counter;
01172 connection->filter_list = NULL;
01173 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE;
01174 connection->objects = objects;
01175 connection->exit_on_disconnect = FALSE;
01176 connection->shareable = FALSE;
01177 #ifndef DBUS_DISABLE_CHECKS
01178 connection->generation = _dbus_current_generation;
01179 #endif
01180
01181 _dbus_data_slot_list_init (&connection->slot_list);
01182
01183 connection->client_serial = 1;
01184
01185 connection->disconnect_message_link = disconnect_link;
01186
01187 CONNECTION_LOCK (connection);
01188
01189 if (!_dbus_transport_set_connection (transport, connection))
01190 goto error;
01191
01192 _dbus_transport_ref (transport);
01193
01194 CONNECTION_UNLOCK (connection);
01195
01196 return connection;
01197
01198 error:
01199 if (disconnect_message != NULL)
01200 dbus_message_unref (disconnect_message);
01201
01202 if (disconnect_link != NULL)
01203 _dbus_list_free_link (disconnect_link);
01204
01205 if (io_path_cond != NULL)
01206 _dbus_condvar_free (io_path_cond);
01207
01208 if (dispatch_cond != NULL)
01209 _dbus_condvar_free (dispatch_cond);
01210
01211 if (mutex != NULL)
01212 _dbus_mutex_free (mutex);
01213
01214 if (io_path_mutex != NULL)
01215 _dbus_mutex_free (io_path_mutex);
01216
01217 if (dispatch_mutex != NULL)
01218 _dbus_mutex_free (dispatch_mutex);
01219
01220 if (connection != NULL)
01221 dbus_free (connection);
01222
01223 if (pending_replies)
01224 _dbus_hash_table_unref (pending_replies);
01225
01226 if (watch_list)
01227 _dbus_watch_list_free (watch_list);
01228
01229 if (timeout_list)
01230 _dbus_timeout_list_free (timeout_list);
01231
01232 if (outgoing_counter)
01233 _dbus_counter_unref (outgoing_counter);
01234
01235 if (objects)
01236 _dbus_object_tree_unref (objects);
01237
01238 return NULL;
01239 }
01240
01248 DBusConnection *
01249 _dbus_connection_ref_unlocked (DBusConnection *connection)
01250 {
01251 _dbus_assert (connection != NULL);
01252 _dbus_assert (connection->generation == _dbus_current_generation);
01253
01254 HAVE_LOCK_CHECK (connection);
01255
01256 #ifdef DBUS_HAVE_ATOMIC_INT
01257 _dbus_atomic_inc (&connection->refcount);
01258 #else
01259 _dbus_assert (connection->refcount.value > 0);
01260 connection->refcount.value += 1;
01261 #endif
01262
01263 return connection;
01264 }
01265
01272 void
01273 _dbus_connection_unref_unlocked (DBusConnection *connection)
01274 {
01275 dbus_bool_t last_unref;
01276
01277 HAVE_LOCK_CHECK (connection);
01278
01279 _dbus_assert (connection != NULL);
01280
01281
01282
01283
01284
01285 #ifdef DBUS_HAVE_ATOMIC_INT
01286 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01287 #else
01288 _dbus_assert (connection->refcount.value > 0);
01289
01290 connection->refcount.value -= 1;
01291 last_unref = (connection->refcount.value == 0);
01292 #if 0
01293 printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01294 #endif
01295 #endif
01296
01297 if (last_unref)
01298 _dbus_connection_last_unref (connection);
01299 }
01300
01301 static dbus_uint32_t
01302 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01303 {
01304 int serial;
01305
01306 serial = connection->client_serial++;
01307
01308 if (connection->client_serial < 0)
01309 connection->client_serial = 1;
01310
01311 return serial;
01312 }
01313
01327 dbus_bool_t
01328 _dbus_connection_handle_watch (DBusWatch *watch,
01329 unsigned int condition,
01330 void *data)
01331 {
01332 DBusConnection *connection;
01333 dbus_bool_t retval;
01334 DBusDispatchStatus status;
01335
01336 connection = data;
01337
01338 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01339
01340 CONNECTION_LOCK (connection);
01341 _dbus_connection_acquire_io_path (connection, -1);
01342 HAVE_LOCK_CHECK (connection);
01343 retval = _dbus_transport_handle_watch (connection->transport,
01344 watch, condition);
01345
01346 _dbus_connection_release_io_path (connection);
01347
01348 HAVE_LOCK_CHECK (connection);
01349
01350 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01351
01352 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01353
01354
01355 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01356
01357 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01358
01359 return retval;
01360 }
01361
01362 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01363 static DBusHashTable *shared_connections = NULL;
01364
01365 static void
01366 shared_connections_shutdown (void *data)
01367 {
01368 _DBUS_LOCK (shared_connections);
01369
01370 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01371 _dbus_hash_table_unref (shared_connections);
01372 shared_connections = NULL;
01373
01374 _DBUS_UNLOCK (shared_connections);
01375 }
01376
01377 static dbus_bool_t
01378 connection_lookup_shared (DBusAddressEntry *entry,
01379 DBusConnection **result)
01380 {
01381 _dbus_verbose ("checking for existing connection\n");
01382
01383 *result = NULL;
01384
01385 _DBUS_LOCK (shared_connections);
01386
01387 if (shared_connections == NULL)
01388 {
01389 _dbus_verbose ("creating shared_connections hash table\n");
01390
01391 shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01392 dbus_free,
01393 NULL);
01394 if (shared_connections == NULL)
01395 {
01396 _DBUS_UNLOCK (shared_connections);
01397 return FALSE;
01398 }
01399
01400 if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01401 {
01402 _dbus_hash_table_unref (shared_connections);
01403 shared_connections = NULL;
01404 _DBUS_UNLOCK (shared_connections);
01405 return FALSE;
01406 }
01407
01408 _dbus_verbose (" successfully created shared_connections\n");
01409
01410 _DBUS_UNLOCK (shared_connections);
01411 return TRUE;
01412 }
01413 else
01414 {
01415 const char *guid;
01416
01417 guid = dbus_address_entry_get_value (entry, "guid");
01418
01419 if (guid != NULL)
01420 {
01421 *result = _dbus_hash_table_lookup_string (shared_connections,
01422 guid);
01423
01424 if (*result)
01425 {
01426
01427
01428
01429
01430
01431
01432
01433
01434 dbus_connection_ref (*result);
01435
01436 _dbus_verbose ("looked up existing connection to server guid %s\n",
01437 guid);
01438 }
01439 }
01440
01441 _DBUS_UNLOCK (shared_connections);
01442 return TRUE;
01443 }
01444 }
01445
01446 static dbus_bool_t
01447 connection_record_shared_unlocked (DBusConnection *connection,
01448 const char *guid)
01449 {
01450 char *guid_key;
01451 char *guid_in_connection;
01452
01453
01454
01455
01456
01457
01458 _dbus_assert (connection->server_guid == NULL);
01459 _dbus_assert (connection->shareable);
01460
01461 guid_key = _dbus_strdup (guid);
01462 if (guid_key == NULL)
01463 return FALSE;
01464
01465 guid_in_connection = _dbus_strdup (guid);
01466 if (guid_in_connection == NULL)
01467 {
01468 dbus_free (guid_key);
01469 return FALSE;
01470 }
01471
01472 _DBUS_LOCK (shared_connections);
01473 _dbus_assert (shared_connections != NULL);
01474
01475 if (!_dbus_hash_table_insert_string (shared_connections,
01476 guid_key, connection))
01477 {
01478 dbus_free (guid_key);
01479 dbus_free (guid_in_connection);
01480 _DBUS_UNLOCK (shared_connections);
01481 return FALSE;
01482 }
01483
01484 connection->server_guid = guid_in_connection;
01485
01486 _dbus_verbose ("stored connection to %s to be shared\n",
01487 connection->server_guid);
01488
01489 _DBUS_UNLOCK (shared_connections);
01490
01491 _dbus_assert (connection->server_guid != NULL);
01492
01493 return TRUE;
01494 }
01495
01496 static void
01497 connection_forget_shared_unlocked (DBusConnection *connection)
01498 {
01499 HAVE_LOCK_CHECK (connection);
01500
01501 if (connection->server_guid == NULL)
01502 return;
01503
01504 _dbus_verbose ("dropping connection to %s out of the shared table\n",
01505 connection->server_guid);
01506
01507 _DBUS_LOCK (shared_connections);
01508
01509 if (!_dbus_hash_table_remove_string (shared_connections,
01510 connection->server_guid))
01511 _dbus_assert_not_reached ("connection was not in the shared table");
01512
01513 dbus_free (connection->server_guid);
01514 connection->server_guid = NULL;
01515
01516 _DBUS_UNLOCK (shared_connections);
01517 }
01518
01519 static DBusConnection*
01520 connection_try_from_address_entry (DBusAddressEntry *entry,
01521 DBusError *error)
01522 {
01523 DBusTransport *transport;
01524 DBusConnection *connection;
01525
01526 transport = _dbus_transport_open (entry, error);
01527
01528 if (transport == NULL)
01529 {
01530 _DBUS_ASSERT_ERROR_IS_SET (error);
01531 return NULL;
01532 }
01533
01534 connection = _dbus_connection_new_for_transport (transport);
01535
01536 _dbus_transport_unref (transport);
01537
01538 if (connection == NULL)
01539 {
01540 _DBUS_SET_OOM (error);
01541 return NULL;
01542 }
01543
01544 #ifndef DBUS_DISABLE_CHECKS
01545 _dbus_assert (!connection->have_connection_lock);
01546 #endif
01547 return connection;
01548 }
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562 static DBusConnection*
01563 _dbus_connection_open_internal (const char *address,
01564 dbus_bool_t shared,
01565 DBusError *error)
01566 {
01567 DBusConnection *connection;
01568 DBusAddressEntry **entries;
01569 DBusError tmp_error;
01570 DBusError first_error;
01571 int len, i;
01572
01573 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01574
01575 _dbus_verbose ("opening %s connection to: %s\n",
01576 shared ? "shared" : "private", address);
01577
01578 if (!dbus_parse_address (address, &entries, &len, error))
01579 return NULL;
01580
01581 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01582
01583 connection = NULL;
01584
01585 dbus_error_init (&tmp_error);
01586 dbus_error_init (&first_error);
01587 for (i = 0; i < len; i++)
01588 {
01589 if (shared)
01590 {
01591 if (!connection_lookup_shared (entries[i], &connection))
01592 _DBUS_SET_OOM (&tmp_error);
01593 }
01594
01595 if (connection == NULL)
01596 {
01597 connection = connection_try_from_address_entry (entries[i],
01598 &tmp_error);
01599
01600 if (connection != NULL && shared)
01601 {
01602 const char *guid;
01603
01604 connection->shareable = TRUE;
01605
01606 guid = dbus_address_entry_get_value (entries[i], "guid");
01607
01608
01609
01610
01611
01612 if (guid &&
01613 !connection_record_shared_unlocked (connection, guid))
01614 {
01615 _DBUS_SET_OOM (&tmp_error);
01616 dbus_connection_close (connection);
01617 dbus_connection_unref (connection);
01618 connection = NULL;
01619 }
01620
01621
01622
01623
01624 }
01625 }
01626
01627 if (connection)
01628 break;
01629
01630 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01631
01632 if (i == 0)
01633 dbus_move_error (&tmp_error, &first_error);
01634 else
01635 dbus_error_free (&tmp_error);
01636 }
01637
01638
01639
01640 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01641 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01642
01643 if (connection == NULL)
01644 {
01645 _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01646 dbus_move_error (&first_error, error);
01647 }
01648 else
01649 {
01650 dbus_error_free (&first_error);
01651 }
01652
01653 dbus_address_entries_free (entries);
01654 return connection;
01655 }
01656
01684 DBusConnection*
01685 dbus_connection_open (const char *address,
01686 DBusError *error)
01687 {
01688 DBusConnection *connection;
01689
01690 _dbus_return_val_if_fail (address != NULL, NULL);
01691 _dbus_return_val_if_error_is_set (error, NULL);
01692
01693 connection = _dbus_connection_open_internal (address,
01694 TRUE,
01695 error);
01696
01697 return connection;
01698 }
01699
01714 DBusConnection*
01715 dbus_connection_open_private (const char *address,
01716 DBusError *error)
01717 {
01718 DBusConnection *connection;
01719
01720 _dbus_return_val_if_fail (address != NULL, NULL);
01721 _dbus_return_val_if_error_is_set (error, NULL);
01722
01723 connection = _dbus_connection_open_internal (address,
01724 FALSE,
01725 error);
01726
01727 return connection;
01728 }
01729
01736 DBusConnection *
01737 dbus_connection_ref (DBusConnection *connection)
01738 {
01739 _dbus_return_val_if_fail (connection != NULL, NULL);
01740 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
01741
01742
01743
01744
01745
01746 #ifdef DBUS_HAVE_ATOMIC_INT
01747 _dbus_atomic_inc (&connection->refcount);
01748 #else
01749 CONNECTION_LOCK (connection);
01750 _dbus_assert (connection->refcount.value > 0);
01751
01752 connection->refcount.value += 1;
01753 CONNECTION_UNLOCK (connection);
01754 #endif
01755
01756 return connection;
01757 }
01758
01759 static void
01760 free_outgoing_message (void *element,
01761 void *data)
01762 {
01763 DBusMessage *message = element;
01764 DBusConnection *connection = data;
01765
01766 _dbus_message_remove_size_counter (message,
01767 connection->outgoing_counter,
01768 NULL);
01769 dbus_message_unref (message);
01770 }
01771
01772
01773
01774
01775
01776 static void
01777 _dbus_connection_last_unref (DBusConnection *connection)
01778 {
01779 DBusList *link;
01780
01781 _dbus_verbose ("Finalizing connection %p\n", connection);
01782
01783 _dbus_assert (connection->refcount.value == 0);
01784
01785
01786
01787
01788 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
01789 _dbus_assert (connection->server_guid == NULL);
01790
01791
01792 _dbus_object_tree_free_all_unlocked (connection->objects);
01793
01794 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
01795 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
01796 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
01797
01798 _dbus_watch_list_free (connection->watches);
01799 connection->watches = NULL;
01800
01801 _dbus_timeout_list_free (connection->timeouts);
01802 connection->timeouts = NULL;
01803
01804 _dbus_data_slot_list_free (&connection->slot_list);
01805
01806 link = _dbus_list_get_first_link (&connection->filter_list);
01807 while (link != NULL)
01808 {
01809 DBusMessageFilter *filter = link->data;
01810 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
01811
01812 filter->function = NULL;
01813 _dbus_message_filter_unref (filter);
01814 link->data = NULL;
01815
01816 link = next;
01817 }
01818 _dbus_list_clear (&connection->filter_list);
01819
01820
01821
01822 _dbus_object_tree_unref (connection->objects);
01823
01824 _dbus_hash_table_unref (connection->pending_replies);
01825 connection->pending_replies = NULL;
01826
01827 _dbus_list_clear (&connection->filter_list);
01828
01829 _dbus_list_foreach (&connection->outgoing_messages,
01830 free_outgoing_message,
01831 connection);
01832 _dbus_list_clear (&connection->outgoing_messages);
01833
01834 _dbus_list_foreach (&connection->incoming_messages,
01835 (DBusForeachFunction) dbus_message_unref,
01836 NULL);
01837 _dbus_list_clear (&connection->incoming_messages);
01838
01839 _dbus_counter_unref (connection->outgoing_counter);
01840
01841 _dbus_transport_unref (connection->transport);
01842
01843 if (connection->disconnect_message_link)
01844 {
01845 DBusMessage *message = connection->disconnect_message_link->data;
01846 dbus_message_unref (message);
01847 _dbus_list_free_link (connection->disconnect_message_link);
01848 }
01849
01850 _dbus_list_clear (&connection->link_cache);
01851
01852 _dbus_condvar_free (connection->dispatch_cond);
01853 _dbus_condvar_free (connection->io_path_cond);
01854
01855 _dbus_mutex_free (connection->io_path_mutex);
01856 _dbus_mutex_free (connection->dispatch_mutex);
01857
01858 _dbus_mutex_free (connection->mutex);
01859
01860 dbus_free (connection);
01861 }
01862
01874 void
01875 dbus_connection_unref (DBusConnection *connection)
01876 {
01877 dbus_bool_t last_unref;
01878
01879 _dbus_return_if_fail (connection != NULL);
01880 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
01881
01882
01883
01884
01885
01886 #ifdef DBUS_HAVE_ATOMIC_INT
01887 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01888 #else
01889 CONNECTION_LOCK (connection);
01890
01891 _dbus_assert (connection->refcount.value > 0);
01892
01893 connection->refcount.value -= 1;
01894 last_unref = (connection->refcount.value == 0);
01895
01896 #if 0
01897 printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
01898 #endif
01899
01900 CONNECTION_UNLOCK (connection);
01901 #endif
01902
01903 if (last_unref)
01904 _dbus_connection_last_unref (connection);
01905 }
01906
01920 void
01921 dbus_connection_close (DBusConnection *connection)
01922 {
01923 DBusDispatchStatus status;
01924
01925 _dbus_return_if_fail (connection != NULL);
01926 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
01927
01928 _dbus_verbose ("Disconnecting %p\n", connection);
01929
01930 CONNECTION_LOCK (connection);
01931
01932 _dbus_transport_disconnect (connection->transport);
01933
01934 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01935 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01936
01937
01938 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01939 }
01940
01947 void
01948 dbus_connection_disconnect (DBusConnection *connection)
01949 {
01950 dbus_connection_close (connection);
01951 }
01952
01953 static dbus_bool_t
01954 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
01955 {
01956 HAVE_LOCK_CHECK (connection);
01957 return _dbus_transport_get_is_connected (connection->transport);
01958 }
01959
01970 dbus_bool_t
01971 dbus_connection_get_is_connected (DBusConnection *connection)
01972 {
01973 dbus_bool_t res;
01974
01975 _dbus_return_val_if_fail (connection != NULL, FALSE);
01976
01977 CONNECTION_LOCK (connection);
01978 res = _dbus_connection_get_is_connected_unlocked (connection);
01979 CONNECTION_UNLOCK (connection);
01980
01981 return res;
01982 }
01983
01992 dbus_bool_t
01993 dbus_connection_get_is_authenticated (DBusConnection *connection)
01994 {
01995 dbus_bool_t res;
01996
01997 _dbus_return_val_if_fail (connection != NULL, FALSE);
01998
01999 CONNECTION_LOCK (connection);
02000 res = _dbus_transport_get_is_authenticated (connection->transport);
02001 CONNECTION_UNLOCK (connection);
02002
02003 return res;
02004 }
02005
02019 void
02020 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
02021 dbus_bool_t exit_on_disconnect)
02022 {
02023 _dbus_return_if_fail (connection != NULL);
02024
02025 CONNECTION_LOCK (connection);
02026 connection->exit_on_disconnect = exit_on_disconnect != FALSE;
02027 CONNECTION_UNLOCK (connection);
02028 }
02029
02030 static DBusPreallocatedSend*
02031 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
02032 {
02033 DBusPreallocatedSend *preallocated;
02034
02035 HAVE_LOCK_CHECK (connection);
02036
02037 _dbus_assert (connection != NULL);
02038
02039 preallocated = dbus_new (DBusPreallocatedSend, 1);
02040 if (preallocated == NULL)
02041 return NULL;
02042
02043 if (connection->link_cache != NULL)
02044 {
02045 preallocated->queue_link =
02046 _dbus_list_pop_first_link (&connection->link_cache);
02047 preallocated->queue_link->data = NULL;
02048 }
02049 else
02050 {
02051 preallocated->queue_link = _dbus_list_alloc_link (NULL);
02052 if (preallocated->queue_link == NULL)
02053 goto failed_0;
02054 }
02055
02056 if (connection->link_cache != NULL)
02057 {
02058 preallocated->counter_link =
02059 _dbus_list_pop_first_link (&connection->link_cache);
02060 preallocated->counter_link->data = connection->outgoing_counter;
02061 }
02062 else
02063 {
02064 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
02065 if (preallocated->counter_link == NULL)
02066 goto failed_1;
02067 }
02068
02069 _dbus_counter_ref (preallocated->counter_link->data);
02070
02071 preallocated->connection = connection;
02072
02073 return preallocated;
02074
02075 failed_1:
02076 _dbus_list_free_link (preallocated->queue_link);
02077 failed_0:
02078 dbus_free (preallocated);
02079
02080 return NULL;
02081 }
02082
02092 DBusPreallocatedSend*
02093 dbus_connection_preallocate_send (DBusConnection *connection)
02094 {
02095 DBusPreallocatedSend *preallocated;
02096
02097 _dbus_return_val_if_fail (connection != NULL, NULL);
02098
02099 CONNECTION_LOCK (connection);
02100
02101 preallocated =
02102 _dbus_connection_preallocate_send_unlocked (connection);
02103
02104 CONNECTION_UNLOCK (connection);
02105
02106 return preallocated;
02107 }
02108
02118 void
02119 dbus_connection_free_preallocated_send (DBusConnection *connection,
02120 DBusPreallocatedSend *preallocated)
02121 {
02122 _dbus_return_if_fail (connection != NULL);
02123 _dbus_return_if_fail (preallocated != NULL);
02124 _dbus_return_if_fail (connection == preallocated->connection);
02125
02126 _dbus_list_free_link (preallocated->queue_link);
02127 _dbus_counter_unref (preallocated->counter_link->data);
02128 _dbus_list_free_link (preallocated->counter_link);
02129 dbus_free (preallocated);
02130 }
02131
02132
02133 static void
02134 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection,
02135 DBusPreallocatedSend *preallocated,
02136 DBusMessage *message,
02137 dbus_uint32_t *client_serial)
02138 {
02139 dbus_uint32_t serial;
02140 const char *sig;
02141
02142 preallocated->queue_link->data = message;
02143 _dbus_list_prepend_link (&connection->outgoing_messages,
02144 preallocated->queue_link);
02145
02146 _dbus_message_add_size_counter_link (message,
02147 preallocated->counter_link);
02148
02149 dbus_free (preallocated);
02150 preallocated = NULL;
02151
02152 dbus_message_ref (message);
02153
02154 connection->n_outgoing += 1;
02155
02156 sig = dbus_message_get_signature (message);
02157
02158 _dbus_verbose ("Message %p (%d %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
02159 message,
02160 dbus_message_get_type (message),
02161 dbus_message_get_path (message),
02162 dbus_message_get_interface (message) ?
02163 dbus_message_get_interface (message) :
02164 "no interface",
02165 dbus_message_get_member (message) ?
02166 dbus_message_get_member (message) :
02167 "no member",
02168 sig,
02169 dbus_message_get_destination (message) ?
02170 dbus_message_get_destination (message) :
02171 "null",
02172 connection,
02173 connection->n_outgoing);
02174
02175 if (dbus_message_get_serial (message) == 0)
02176 {
02177 serial = _dbus_connection_get_next_client_serial (connection);
02178 _dbus_message_set_serial (message, serial);
02179 if (client_serial)
02180 *client_serial = serial;
02181 }
02182 else
02183 {
02184 if (client_serial)
02185 *client_serial = dbus_message_get_serial (message);
02186 }
02187
02188 _dbus_verbose ("Message %p serial is %u\n",
02189 message, dbus_message_get_serial (message));
02190
02191 _dbus_message_lock (message);
02192
02193
02194
02195
02196 _dbus_connection_do_iteration_unlocked (connection,
02197 DBUS_ITERATION_DO_WRITING,
02198 -1);
02199
02200
02201 if (connection->n_outgoing > 0)
02202 _dbus_connection_wakeup_mainloop (connection);
02203 }
02204
02205 static void
02206 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection,
02207 DBusPreallocatedSend *preallocated,
02208 DBusMessage *message,
02209 dbus_uint32_t *client_serial)
02210 {
02211 DBusDispatchStatus status;
02212
02213 HAVE_LOCK_CHECK (connection);
02214
02215 _dbus_connection_send_preallocated_unlocked_no_update (connection,
02216 preallocated,
02217 message, client_serial);
02218
02219 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02220 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02221
02222
02223 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02224 }
02225
02238 void
02239 dbus_connection_send_preallocated (DBusConnection *connection,
02240 DBusPreallocatedSend *preallocated,
02241 DBusMessage *message,
02242 dbus_uint32_t *client_serial)
02243 {
02244 _dbus_return_if_fail (connection != NULL);
02245 _dbus_return_if_fail (preallocated != NULL);
02246 _dbus_return_if_fail (message != NULL);
02247 _dbus_return_if_fail (preallocated->connection == connection);
02248 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
02249 (dbus_message_get_interface (message) != NULL &&
02250 dbus_message_get_member (message) != NULL));
02251 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
02252 (dbus_message_get_interface (message) != NULL &&
02253 dbus_message_get_member (message) != NULL));
02254
02255 CONNECTION_LOCK (connection);
02256 _dbus_connection_send_preallocated_and_unlock (connection,
02257 preallocated,
02258 message, client_serial);
02259 }
02260
02261 static dbus_bool_t
02262 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
02263 DBusMessage *message,
02264 dbus_uint32_t *client_serial)
02265 {
02266 DBusPreallocatedSend *preallocated;
02267
02268 _dbus_assert (connection != NULL);
02269 _dbus_assert (message != NULL);
02270
02271 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02272 if (preallocated == NULL)
02273 return FALSE;
02274
02275 _dbus_connection_send_preallocated_unlocked_no_update (connection,
02276 preallocated,
02277 message,
02278 client_serial);
02279 return TRUE;
02280 }
02281
02282 dbus_bool_t
02283 _dbus_connection_send_and_unlock (DBusConnection *connection,
02284 DBusMessage *message,
02285 dbus_uint32_t *client_serial)
02286 {
02287 DBusPreallocatedSend *preallocated;
02288
02289 _dbus_assert (connection != NULL);
02290 _dbus_assert (message != NULL);
02291
02292 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02293 if (preallocated == NULL)
02294 {
02295 CONNECTION_UNLOCK (connection);
02296 return FALSE;
02297 }
02298
02299 _dbus_connection_send_preallocated_and_unlock (connection,
02300 preallocated,
02301 message,
02302 client_serial);
02303 return TRUE;
02304 }
02305
02324 dbus_bool_t
02325 dbus_connection_send (DBusConnection *connection,
02326 DBusMessage *message,
02327 dbus_uint32_t *client_serial)
02328 {
02329 _dbus_return_val_if_fail (connection != NULL, FALSE);
02330 _dbus_return_val_if_fail (message != NULL, FALSE);
02331
02332 CONNECTION_LOCK (connection);
02333
02334 return _dbus_connection_send_and_unlock (connection,
02335 message,
02336 client_serial);
02337 }
02338
02339 static dbus_bool_t
02340 reply_handler_timeout (void *data)
02341 {
02342 DBusConnection *connection;
02343 DBusDispatchStatus status;
02344 DBusPendingCall *pending = data;
02345
02346 connection = pending->connection;
02347
02348 CONNECTION_LOCK (connection);
02349 if (pending->timeout_link)
02350 {
02351 _dbus_connection_queue_synthesized_message_link (connection,
02352 pending->timeout_link);
02353 pending->timeout_link = NULL;
02354 }
02355
02356 _dbus_connection_remove_timeout (connection,
02357 pending->timeout);
02358 pending->timeout_added = FALSE;
02359
02360 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02361 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02362
02363
02364 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02365
02366 return TRUE;
02367 }
02368
02406 dbus_bool_t
02407 dbus_connection_send_with_reply (DBusConnection *connection,
02408 DBusMessage *message,
02409 DBusPendingCall **pending_return,
02410 int timeout_milliseconds)
02411 {
02412 DBusPendingCall *pending;
02413 DBusMessage *reply;
02414 DBusList *reply_link;
02415 dbus_int32_t serial = -1;
02416 DBusDispatchStatus status;
02417
02418 _dbus_return_val_if_fail (connection != NULL, FALSE);
02419 _dbus_return_val_if_fail (message != NULL, FALSE);
02420 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02421
02422 if (pending_return)
02423 *pending_return = NULL;
02424
02425 pending = _dbus_pending_call_new (connection,
02426 timeout_milliseconds,
02427 reply_handler_timeout);
02428
02429 if (pending == NULL)
02430 return FALSE;
02431
02432 CONNECTION_LOCK (connection);
02433
02434
02435 if (dbus_message_get_serial (message) == 0)
02436 {
02437 serial = _dbus_connection_get_next_client_serial (connection);
02438 _dbus_message_set_serial (message, serial);
02439 }
02440
02441 pending->reply_serial = serial;
02442
02443 reply = dbus_message_new_error (message, DBUS_ERROR_NO_REPLY,
02444 "No reply within specified time");
02445 if (reply == NULL)
02446 goto error;
02447
02448 reply_link = _dbus_list_alloc_link (reply);
02449 if (reply_link == NULL)
02450 {
02451 CONNECTION_UNLOCK (connection);
02452 dbus_message_unref (reply);
02453 goto error_unlocked;
02454 }
02455
02456 pending->timeout_link = reply_link;
02457
02458
02459
02460
02461
02462 if (!_dbus_connection_attach_pending_call_unlocked (connection,
02463 pending))
02464 goto error;
02465
02466 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
02467 {
02468 _dbus_connection_detach_pending_call_and_unlock (connection,
02469 pending);
02470 goto error_unlocked;
02471 }
02472
02473 if (pending_return)
02474 *pending_return = pending;
02475 else
02476 {
02477 _dbus_connection_detach_pending_call_unlocked (connection, pending);
02478 dbus_pending_call_unref (pending);
02479 }
02480
02481 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02482 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02483
02484
02485 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02486
02487 return TRUE;
02488
02489 error:
02490 CONNECTION_UNLOCK (connection);
02491 error_unlocked:
02492 dbus_pending_call_unref (pending);
02493 return FALSE;
02494 }
02495
02496
02497
02498
02499 static DBusMessage*
02500 check_for_reply_unlocked (DBusConnection *connection,
02501 dbus_uint32_t client_serial)
02502 {
02503 DBusList *link;
02504
02505 HAVE_LOCK_CHECK (connection);
02506
02507 link = _dbus_list_get_first_link (&connection->incoming_messages);
02508
02509 while (link != NULL)
02510 {
02511 DBusMessage *reply = link->data;
02512
02513 if (dbus_message_get_reply_serial (reply) == client_serial)
02514 {
02515 _dbus_list_remove_link (&connection->incoming_messages, link);
02516 connection->n_incoming -= 1;
02517 return reply;
02518 }
02519 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02520 }
02521
02522 return NULL;
02523 }
02524
02534 static void
02535 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02536 {
02537 if (timeout_milliseconds == -1)
02538 _dbus_sleep_milliseconds (1000);
02539 else if (timeout_milliseconds < 100)
02540 ;
02541 else if (timeout_milliseconds <= 1000)
02542 _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02543 else
02544 _dbus_sleep_milliseconds (1000);
02545 }
02546
02561 void
02562 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02563 {
02564 long start_tv_sec, start_tv_usec;
02565 long end_tv_sec, end_tv_usec;
02566 long tv_sec, tv_usec;
02567 DBusDispatchStatus status;
02568 DBusConnection *connection;
02569 dbus_uint32_t client_serial;
02570 int timeout_milliseconds;
02571
02572 _dbus_assert (pending != NULL);
02573
02574 if (dbus_pending_call_get_completed (pending))
02575 return;
02576
02577 if (pending->connection == NULL)
02578 return;
02579
02580 dbus_pending_call_ref (pending);
02581
02582 connection = pending->connection;
02583 client_serial = pending->reply_serial;
02584
02585
02586
02587
02588
02589 timeout_milliseconds = dbus_timeout_get_interval (pending->timeout);
02590
02591
02592 dbus_connection_flush (connection);
02593
02594 CONNECTION_LOCK (connection);
02595
02596 _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02597 end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
02598 end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
02599 end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
02600 end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
02601
02602 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec to %ld sec %ld usec\n",
02603 timeout_milliseconds,
02604 client_serial,
02605 start_tv_sec, start_tv_usec,
02606 end_tv_sec, end_tv_usec);
02607
02608
02609
02610 _dbus_connection_do_iteration_unlocked (connection,
02611 DBUS_ITERATION_DO_READING |
02612 DBUS_ITERATION_BLOCK,
02613 timeout_milliseconds);
02614
02615 recheck_status:
02616
02617 _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME);
02618
02619 HAVE_LOCK_CHECK (connection);
02620
02621
02622
02623 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02624
02625
02626
02627
02628 if (dbus_pending_call_get_completed (pending))
02629 {
02630 _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME);
02631 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02632 dbus_pending_call_unref (pending);
02633 return;
02634 }
02635
02636 if (status == DBUS_DISPATCH_DATA_REMAINS)
02637 {
02638 DBusMessage *reply;
02639
02640 reply = check_for_reply_unlocked (connection, client_serial);
02641 if (reply != NULL)
02642 {
02643 _dbus_verbose ("%s checked for reply\n", _DBUS_FUNCTION_NAME);
02644
02645 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02646
02647 _dbus_pending_call_complete_and_unlock (pending, reply);
02648 dbus_message_unref (reply);
02649
02650 CONNECTION_LOCK (connection);
02651 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02652 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02653 dbus_pending_call_unref (pending);
02654
02655 return;
02656 }
02657 }
02658
02659 _dbus_get_current_time (&tv_sec, &tv_usec);
02660
02661 if (!_dbus_connection_get_is_connected_unlocked (connection))
02662 {
02663
02664
02665
02666
02667
02668 _dbus_pending_call_complete_and_unlock (pending, NULL);
02669 dbus_pending_call_unref (pending);
02670 return;
02671 }
02672 else if (tv_sec < start_tv_sec)
02673 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02674 else if (connection->disconnect_message_link == NULL)
02675 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02676 else if (tv_sec < end_tv_sec ||
02677 (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
02678 {
02679 timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
02680 (end_tv_usec - tv_usec) / 1000;
02681 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
02682 _dbus_assert (timeout_milliseconds >= 0);
02683
02684 if (status == DBUS_DISPATCH_NEED_MEMORY)
02685 {
02686
02687
02688
02689
02690 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02691
02692 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02693 }
02694 else
02695 {
02696
02697 _dbus_connection_do_iteration_unlocked (connection,
02698 DBUS_ITERATION_DO_READING |
02699 DBUS_ITERATION_BLOCK,
02700 timeout_milliseconds);
02701 }
02702
02703 goto recheck_status;
02704 }
02705
02706 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
02707 (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
02708
02709 _dbus_assert (!dbus_pending_call_get_completed (pending));
02710
02711
02712 _dbus_pending_call_complete_and_unlock (pending, NULL);
02713
02714
02715 CONNECTION_LOCK (connection);
02716 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02717 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02718 dbus_pending_call_unref (pending);
02719 }
02720
02743 DBusMessage*
02744 dbus_connection_send_with_reply_and_block (DBusConnection *connection,
02745 DBusMessage *message,
02746 int timeout_milliseconds,
02747 DBusError *error)
02748 {
02749 DBusMessage *reply;
02750 DBusPendingCall *pending;
02751
02752 _dbus_return_val_if_fail (connection != NULL, NULL);
02753 _dbus_return_val_if_fail (message != NULL, NULL);
02754 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02755 _dbus_return_val_if_error_is_set (error, NULL);
02756
02757 if (!dbus_connection_send_with_reply (connection, message,
02758 &pending, timeout_milliseconds))
02759 {
02760 _DBUS_SET_OOM (error);
02761 return NULL;
02762 }
02763
02764 _dbus_assert (pending != NULL);
02765
02766 dbus_pending_call_block (pending);
02767
02768 reply = dbus_pending_call_steal_reply (pending);
02769 dbus_pending_call_unref (pending);
02770
02771
02772
02773
02774 _dbus_assert (reply != NULL);
02775
02776 if (dbus_set_error_from_message (error, reply))
02777 {
02778 dbus_message_unref (reply);
02779 return NULL;
02780 }
02781 else
02782 return reply;
02783 }
02784
02790 void
02791 dbus_connection_flush (DBusConnection *connection)
02792 {
02793
02794
02795
02796
02797
02798 DBusDispatchStatus status;
02799
02800 _dbus_return_if_fail (connection != NULL);
02801
02802 CONNECTION_LOCK (connection);
02803 while (connection->n_outgoing > 0 &&
02804 _dbus_connection_get_is_connected_unlocked (connection))
02805 {
02806 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
02807 HAVE_LOCK_CHECK (connection);
02808 _dbus_connection_do_iteration_unlocked (connection,
02809 DBUS_ITERATION_DO_READING |
02810 DBUS_ITERATION_DO_WRITING |
02811 DBUS_ITERATION_BLOCK,
02812 -1);
02813 }
02814
02815 HAVE_LOCK_CHECK (connection);
02816 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02817 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02818
02819 HAVE_LOCK_CHECK (connection);
02820
02821 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02822
02823 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
02824 }
02825
02857 dbus_bool_t
02858 dbus_connection_read_write_dispatch (DBusConnection *connection,
02859 int timeout_milliseconds)
02860 {
02861 DBusDispatchStatus dstatus;
02862 dbus_bool_t dispatched_disconnected;
02863
02864 _dbus_return_val_if_fail (connection != NULL, FALSE);
02865 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02866 dstatus = dbus_connection_get_dispatch_status (connection);
02867
02868 if (dstatus == DBUS_DISPATCH_DATA_REMAINS)
02869 {
02870 _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME);
02871 dbus_connection_dispatch (connection);
02872 CONNECTION_LOCK (connection);
02873 }
02874 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
02875 {
02876 _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME);
02877 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02878 CONNECTION_LOCK (connection);
02879 }
02880 else
02881 {
02882 CONNECTION_LOCK (connection);
02883 if (_dbus_connection_get_is_connected_unlocked (connection))
02884 {
02885 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
02886 _dbus_connection_do_iteration_unlocked (connection,
02887 DBUS_ITERATION_DO_READING |
02888 DBUS_ITERATION_DO_WRITING |
02889 DBUS_ITERATION_BLOCK,
02890 timeout_milliseconds);
02891 }
02892 }
02893
02894 HAVE_LOCK_CHECK (connection);
02895 dispatched_disconnected = connection->n_incoming == 0 &&
02896 connection->disconnect_message_link == NULL;
02897 CONNECTION_UNLOCK (connection);
02898 return !dispatched_disconnected;
02899 }
02900
02920 DBusMessage*
02921 dbus_connection_borrow_message (DBusConnection *connection)
02922 {
02923 DBusDispatchStatus status;
02924 DBusMessage *message;
02925
02926 _dbus_return_val_if_fail (connection != NULL, NULL);
02927
02928 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
02929
02930
02931
02932
02933 status = dbus_connection_get_dispatch_status (connection);
02934 if (status != DBUS_DISPATCH_DATA_REMAINS)
02935 return NULL;
02936
02937 CONNECTION_LOCK (connection);
02938
02939 _dbus_connection_acquire_dispatch (connection);
02940
02941
02942 _dbus_assert (connection->message_borrowed == NULL);
02943
02944 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
02945
02946 message = connection->message_borrowed;
02947
02948
02949 if (message == NULL)
02950 _dbus_connection_release_dispatch (connection);
02951
02952 CONNECTION_UNLOCK (connection);
02953
02954 return message;
02955 }
02956
02965 void
02966 dbus_connection_return_message (DBusConnection *connection,
02967 DBusMessage *message)
02968 {
02969 _dbus_return_if_fail (connection != NULL);
02970 _dbus_return_if_fail (message != NULL);
02971 _dbus_return_if_fail (message == connection->message_borrowed);
02972 _dbus_return_if_fail (connection->dispatch_acquired);
02973
02974 CONNECTION_LOCK (connection);
02975
02976 _dbus_assert (message == connection->message_borrowed);
02977
02978 connection->message_borrowed = NULL;
02979
02980 _dbus_connection_release_dispatch (connection);
02981
02982 CONNECTION_UNLOCK (connection);
02983 }
02984
02994 void
02995 dbus_connection_steal_borrowed_message (DBusConnection *connection,
02996 DBusMessage *message)
02997 {
02998 DBusMessage *pop_message;
02999
03000 _dbus_return_if_fail (connection != NULL);
03001 _dbus_return_if_fail (message != NULL);
03002 _dbus_return_if_fail (message == connection->message_borrowed);
03003 _dbus_return_if_fail (connection->dispatch_acquired);
03004
03005 CONNECTION_LOCK (connection);
03006
03007 _dbus_assert (message == connection->message_borrowed);
03008
03009 pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03010 _dbus_assert (message == pop_message);
03011
03012 connection->n_incoming -= 1;
03013
03014 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03015 message, connection->n_incoming);
03016
03017 connection->message_borrowed = NULL;
03018
03019 _dbus_connection_release_dispatch (connection);
03020
03021 CONNECTION_UNLOCK (connection);
03022 }
03023
03024
03025
03026
03027 static DBusList*
03028 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03029 {
03030 HAVE_LOCK_CHECK (connection);
03031
03032 _dbus_assert (connection->message_borrowed == NULL);
03033
03034 if (connection->n_incoming > 0)
03035 {
03036 DBusList *link;
03037
03038 link = _dbus_list_pop_first_link (&connection->incoming_messages);
03039 connection->n_incoming -= 1;
03040
03041 _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03042 link->data,
03043 dbus_message_get_type (link->data),
03044 dbus_message_get_path (link->data),
03045 dbus_message_get_interface (link->data) ?
03046 dbus_message_get_interface (link->data) :
03047 "no interface",
03048 dbus_message_get_member (link->data) ?
03049 dbus_message_get_member (link->data) :
03050 "no member",
03051 dbus_message_get_signature (link->data),
03052 connection, connection->n_incoming);
03053
03054 return link;
03055 }
03056 else
03057 return NULL;
03058 }
03059
03060
03061
03062
03063 static DBusMessage*
03064 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03065 {
03066 DBusList *link;
03067
03068 HAVE_LOCK_CHECK (connection);
03069
03070 link = _dbus_connection_pop_message_link_unlocked (connection);
03071
03072 if (link != NULL)
03073 {
03074 DBusMessage *message;
03075
03076 message = link->data;
03077
03078 _dbus_list_free_link (link);
03079
03080 return message;
03081 }
03082 else
03083 return NULL;
03084 }
03085
03086 static void
03087 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03088 DBusList *message_link)
03089 {
03090 HAVE_LOCK_CHECK (connection);
03091
03092 _dbus_assert (message_link != NULL);
03093
03094 _dbus_assert (connection->message_borrowed == NULL);
03095
03096 _dbus_assert (connection->dispatch_acquired);
03097
03098 _dbus_list_prepend_link (&connection->incoming_messages,
03099 message_link);
03100 connection->n_incoming += 1;
03101
03102 _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
03103 message_link->data,
03104 dbus_message_get_type (message_link->data),
03105 dbus_message_get_interface (message_link->data) ?
03106 dbus_message_get_interface (message_link->data) :
03107 "no interface",
03108 dbus_message_get_member (message_link->data) ?
03109 dbus_message_get_member (message_link->data) :
03110 "no member",
03111 dbus_message_get_signature (message_link->data),
03112 connection, connection->n_incoming);
03113 }
03114
03134 DBusMessage*
03135 dbus_connection_pop_message (DBusConnection *connection)
03136 {
03137 DBusMessage *message;
03138 DBusDispatchStatus status;
03139
03140 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03141
03142
03143
03144
03145 status = dbus_connection_get_dispatch_status (connection);
03146 if (status != DBUS_DISPATCH_DATA_REMAINS)
03147 return NULL;
03148
03149 CONNECTION_LOCK (connection);
03150 _dbus_connection_acquire_dispatch (connection);
03151 HAVE_LOCK_CHECK (connection);
03152
03153 message = _dbus_connection_pop_message_unlocked (connection);
03154
03155 _dbus_verbose ("Returning popped message %p\n", message);
03156
03157 _dbus_connection_release_dispatch (connection);
03158 CONNECTION_UNLOCK (connection);
03159
03160 return message;
03161 }
03162
03170 static void
03171 _dbus_connection_acquire_dispatch (DBusConnection *connection)
03172 {
03173 HAVE_LOCK_CHECK (connection);
03174
03175 _dbus_connection_ref_unlocked (connection);
03176 CONNECTION_UNLOCK (connection);
03177
03178 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03179 _dbus_mutex_lock (connection->dispatch_mutex);
03180
03181 while (connection->dispatch_acquired)
03182 {
03183 _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
03184 _dbus_condvar_wait (connection->dispatch_cond, connection->dispatch_mutex);
03185 }
03186
03187 _dbus_assert (!connection->dispatch_acquired);
03188
03189 connection->dispatch_acquired = TRUE;
03190
03191 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03192 _dbus_mutex_unlock (connection->dispatch_mutex);
03193
03194 CONNECTION_LOCK (connection);
03195 _dbus_connection_unref_unlocked (connection);
03196 }
03197
03205 static void
03206 _dbus_connection_release_dispatch (DBusConnection *connection)
03207 {
03208 HAVE_LOCK_CHECK (connection);
03209
03210 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03211 _dbus_mutex_lock (connection->dispatch_mutex);
03212
03213 _dbus_assert (connection->dispatch_acquired);
03214
03215 connection->dispatch_acquired = FALSE;
03216 _dbus_condvar_wake_one (connection->dispatch_cond);
03217
03218 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03219 _dbus_mutex_unlock (connection->dispatch_mutex);
03220 }
03221
03222 static void
03223 _dbus_connection_failed_pop (DBusConnection *connection,
03224 DBusList *message_link)
03225 {
03226 _dbus_list_prepend_link (&connection->incoming_messages,
03227 message_link);
03228 connection->n_incoming += 1;
03229 }
03230
03231 static DBusDispatchStatus
03232 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
03233 {
03234 HAVE_LOCK_CHECK (connection);
03235
03236 if (connection->n_incoming > 0)
03237 return DBUS_DISPATCH_DATA_REMAINS;
03238 else if (!_dbus_transport_queue_messages (connection->transport))
03239 return DBUS_DISPATCH_NEED_MEMORY;
03240 else
03241 {
03242 DBusDispatchStatus status;
03243 dbus_bool_t is_connected;
03244
03245 status = _dbus_transport_get_dispatch_status (connection->transport);
03246 is_connected = _dbus_transport_get_is_connected (connection->transport);
03247
03248 _dbus_verbose ("dispatch status = %s is_connected = %d\n",
03249 DISPATCH_STATUS_NAME (status), is_connected);
03250
03251 if (!is_connected)
03252 {
03253 if (status == DBUS_DISPATCH_COMPLETE &&
03254 connection->disconnect_message_link)
03255 {
03256 _dbus_verbose ("Sending disconnect message from %s\n",
03257 _DBUS_FUNCTION_NAME);
03258
03259 connection_forget_shared_unlocked (connection);
03260
03261
03262
03263
03264 _dbus_connection_queue_synthesized_message_link (connection,
03265 connection->disconnect_message_link);
03266 connection->disconnect_message_link = NULL;
03267 }
03268
03269
03270
03271
03272
03273 if (connection->n_outgoing > 0)
03274 {
03275 DBusList *link;
03276
03277 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
03278 connection->n_outgoing);
03279
03280 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
03281 {
03282 _dbus_connection_message_sent (connection, link->data);
03283 }
03284 }
03285 }
03286
03287 if (status != DBUS_DISPATCH_COMPLETE)
03288 return status;
03289 else if (connection->n_incoming > 0)
03290 return DBUS_DISPATCH_DATA_REMAINS;
03291 else
03292 return DBUS_DISPATCH_COMPLETE;
03293 }
03294 }
03295
03296 static void
03297 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
03298 DBusDispatchStatus new_status)
03299 {
03300 dbus_bool_t changed;
03301 DBusDispatchStatusFunction function;
03302 void *data;
03303
03304 HAVE_LOCK_CHECK (connection);
03305
03306 _dbus_connection_ref_unlocked (connection);
03307
03308 changed = new_status != connection->last_dispatch_status;
03309
03310 connection->last_dispatch_status = new_status;
03311
03312 function = connection->dispatch_status_function;
03313 data = connection->dispatch_status_data;
03314
03315
03316 CONNECTION_UNLOCK (connection);
03317
03318 if (changed && function)
03319 {
03320 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
03321 connection, new_status,
03322 DISPATCH_STATUS_NAME (new_status));
03323 (* function) (connection, new_status, data);
03324 }
03325
03326 dbus_connection_unref (connection);
03327 }
03328
03337 DBusDispatchStatus
03338 dbus_connection_get_dispatch_status (DBusConnection *connection)
03339 {
03340 DBusDispatchStatus status;
03341
03342 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
03343
03344 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03345
03346 CONNECTION_LOCK (connection);
03347
03348 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03349
03350 CONNECTION_UNLOCK (connection);
03351
03352 return status;
03353 }
03354
03358 static DBusHandlerResult
03359 _dbus_connection_peer_filter (DBusConnection *connection,
03360 DBusMessage *message)
03361 {
03362 if (dbus_message_is_method_call (message,
03363 DBUS_INTERFACE_PEER,
03364 "Ping"))
03365 {
03366 DBusMessage *ret;
03367 dbus_bool_t sent;
03368
03369 ret = dbus_message_new_method_return (message);
03370 if (ret == NULL)
03371 return DBUS_HANDLER_RESULT_NEED_MEMORY;
03372
03373 sent = dbus_connection_send (connection, ret, NULL);
03374 dbus_message_unref (ret);
03375
03376 if (!sent)
03377 return DBUS_HANDLER_RESULT_NEED_MEMORY;
03378
03379 return DBUS_HANDLER_RESULT_HANDLED;
03380 }
03381
03382
03383 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03384 }
03385
03392 static DBusHandlerResult
03393 _dbus_connection_run_builtin_filters (DBusConnection *connection,
03394 DBusMessage *message)
03395 {
03396
03397
03398
03399 return _dbus_connection_peer_filter (connection, message);
03400 }
03401
03425 DBusDispatchStatus
03426 dbus_connection_dispatch (DBusConnection *connection)
03427 {
03428 DBusMessage *message;
03429 DBusList *link, *filter_list_copy, *message_link;
03430 DBusHandlerResult result;
03431 DBusPendingCall *pending;
03432 dbus_int32_t reply_serial;
03433 DBusDispatchStatus status;
03434
03435 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
03436
03437 _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
03438
03439 CONNECTION_LOCK (connection);
03440 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03441 if (status != DBUS_DISPATCH_DATA_REMAINS)
03442 {
03443
03444 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03445 return status;
03446 }
03447
03448
03449
03450
03451 _dbus_connection_ref_unlocked (connection);
03452
03453 _dbus_connection_acquire_dispatch (connection);
03454 HAVE_LOCK_CHECK (connection);
03455
03456 message_link = _dbus_connection_pop_message_link_unlocked (connection);
03457 if (message_link == NULL)
03458 {
03459
03460
03461 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
03462
03463 _dbus_connection_release_dispatch (connection);
03464
03465 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03466
03467 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03468
03469 dbus_connection_unref (connection);
03470
03471 return status;
03472 }
03473
03474 message = message_link->data;
03475
03476 _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
03477 message,
03478 dbus_message_get_type (message),
03479 dbus_message_get_interface (message) ?
03480 dbus_message_get_interface (message) :
03481 "no interface",
03482 dbus_message_get_member (message) ?
03483 dbus_message_get_member (message) :
03484 "no member",
03485 dbus_message_get_signature (message));
03486
03487 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03488
03489
03490
03491
03492
03493
03494
03495
03496 reply_serial = dbus_message_get_reply_serial (message);
03497 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
03498 reply_serial);
03499 if (pending)
03500 {
03501 _dbus_verbose ("Dispatching a pending reply\n");
03502 _dbus_pending_call_complete_and_unlock (pending, message);
03503 pending = NULL;
03504
03505 CONNECTION_LOCK (connection);
03506 _dbus_verbose ("pending call completed in dispatch\n");
03507 result = DBUS_HANDLER_RESULT_HANDLED;
03508 goto out;
03509 }
03510
03511 result = _dbus_connection_run_builtin_filters (connection, message);
03512 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03513 goto out;
03514
03515 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
03516 {
03517 _dbus_connection_release_dispatch (connection);
03518 HAVE_LOCK_CHECK (connection);
03519
03520 _dbus_connection_failed_pop (connection, message_link);
03521
03522
03523 _dbus_connection_update_dispatch_status_and_unlock (connection,
03524 DBUS_DISPATCH_NEED_MEMORY);
03525
03526 if (pending)
03527 dbus_pending_call_unref (pending);
03528 dbus_connection_unref (connection);
03529
03530 return DBUS_DISPATCH_NEED_MEMORY;
03531 }
03532
03533 _dbus_list_foreach (&filter_list_copy,
03534 (DBusForeachFunction)_dbus_message_filter_ref,
03535 NULL);
03536
03537
03538
03539
03540 CONNECTION_UNLOCK (connection);
03541
03542 link = _dbus_list_get_first_link (&filter_list_copy);
03543 while (link != NULL)
03544 {
03545 DBusMessageFilter *filter = link->data;
03546 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
03547
03548 _dbus_verbose (" running filter on message %p\n", message);
03549 result = (* filter->function) (connection, message, filter->user_data);
03550
03551 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03552 break;
03553
03554 link = next;
03555 }
03556
03557 _dbus_list_foreach (&filter_list_copy,
03558 (DBusForeachFunction)_dbus_message_filter_unref,
03559 NULL);
03560 _dbus_list_clear (&filter_list_copy);
03561
03562 CONNECTION_LOCK (connection);
03563
03564 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
03565 {
03566 _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
03567 goto out;
03568 }
03569 else if (result == DBUS_HANDLER_RESULT_HANDLED)
03570 {
03571 _dbus_verbose ("filter handled message in dispatch\n");
03572 goto out;
03573 }
03574
03575
03576
03577
03578 _dbus_verbose (" running object path dispatch on message %p (%d %s %s '%s')\n",
03579 message,
03580 dbus_message_get_type (message),
03581 dbus_message_get_interface (message) ?
03582 dbus_message_get_interface (message) :
03583 "no interface",
03584 dbus_message_get_member (message) ?
03585 dbus_message_get_member (message) :
03586 "no member",
03587 dbus_message_get_signature (message));
03588
03589 HAVE_LOCK_CHECK (connection);
03590 result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
03591 message);
03592
03593 CONNECTION_LOCK (connection);
03594
03595 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03596 {
03597 _dbus_verbose ("object tree handled message in dispatch\n");
03598 goto out;
03599 }
03600
03601 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
03602 {
03603 DBusMessage *reply;
03604 DBusString str;
03605 DBusPreallocatedSend *preallocated;
03606
03607 _dbus_verbose (" sending error %s\n",
03608 DBUS_ERROR_UNKNOWN_METHOD);
03609
03610 if (!_dbus_string_init (&str))
03611 {
03612 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03613 _dbus_verbose ("no memory for error string in dispatch\n");
03614 goto out;
03615 }
03616
03617 if (!_dbus_string_append_printf (&str,
03618 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
03619 dbus_message_get_member (message),
03620 dbus_message_get_signature (message),
03621 dbus_message_get_interface (message)))
03622 {
03623 _dbus_string_free (&str);
03624 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03625 _dbus_verbose ("no memory for error string in dispatch\n");
03626 goto out;
03627 }
03628
03629 reply = dbus_message_new_error (message,
03630 DBUS_ERROR_UNKNOWN_METHOD,
03631 _dbus_string_get_const_data (&str));
03632 _dbus_string_free (&str);
03633
03634 if (reply == NULL)
03635 {
03636 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03637 _dbus_verbose ("no memory for error reply in dispatch\n");
03638 goto out;
03639 }
03640
03641 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03642
03643 if (preallocated == NULL)
03644 {
03645 dbus_message_unref (reply);
03646 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03647 _dbus_verbose ("no memory for error send in dispatch\n");
03648 goto out;
03649 }
03650
03651 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
03652 reply, NULL);
03653
03654 dbus_message_unref (reply);
03655
03656 result = DBUS_HANDLER_RESULT_HANDLED;
03657 }
03658
03659 _dbus_verbose (" done dispatching %p (%d %s %s '%s') on connection %p\n", message,
03660 dbus_message_get_type (message),
03661 dbus_message_get_interface (message) ?
03662 dbus_message_get_interface (message) :
03663 "no interface",
03664 dbus_message_get_member (message) ?
03665 dbus_message_get_member (message) :
03666 "no member",
03667 dbus_message_get_signature (message),
03668 connection);
03669
03670 out:
03671 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
03672 {
03673 _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
03674
03675
03676
03677
03678
03679 _dbus_connection_putback_message_link_unlocked (connection,
03680 message_link);
03681 }
03682 else
03683 {
03684 _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
03685
03686 if (connection->exit_on_disconnect &&
03687 dbus_message_is_signal (message,
03688 DBUS_INTERFACE_LOCAL,
03689 "Disconnected"))
03690 {
03691 _dbus_verbose ("Exiting on Disconnected signal\n");
03692 CONNECTION_UNLOCK (connection);
03693 _dbus_exit (1);
03694 _dbus_assert_not_reached ("Call to exit() returned");
03695 }
03696
03697 _dbus_list_free_link (message_link);
03698 dbus_message_unref (message);
03699
03700
03701 }
03702
03703 _dbus_connection_release_dispatch (connection);
03704 HAVE_LOCK_CHECK (connection);
03705
03706 _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
03707 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03708
03709
03710 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03711
03712 dbus_connection_unref (connection);
03713
03714 return status;
03715 }
03716
03775 dbus_bool_t
03776 dbus_connection_set_watch_functions (DBusConnection *connection,
03777 DBusAddWatchFunction add_function,
03778 DBusRemoveWatchFunction remove_function,
03779 DBusWatchToggledFunction toggled_function,
03780 void *data,
03781 DBusFreeFunction free_data_function)
03782 {
03783 dbus_bool_t retval;
03784 DBusWatchList *watches;
03785
03786 _dbus_return_val_if_fail (connection != NULL, FALSE);
03787
03788 CONNECTION_LOCK (connection);
03789
03790 #ifndef DBUS_DISABLE_CHECKS
03791 if (connection->watches == NULL)
03792 {
03793 _dbus_warn ("Re-entrant call to %s is not allowed\n",
03794 _DBUS_FUNCTION_NAME);
03795 return FALSE;
03796 }
03797 #endif
03798
03799
03800 _dbus_connection_ref_unlocked (connection);
03801
03802
03803
03804
03805
03806 watches = connection->watches;
03807 connection->watches = NULL;
03808 CONNECTION_UNLOCK (connection);
03809
03810 retval = _dbus_watch_list_set_functions (watches,
03811 add_function, remove_function,
03812 toggled_function,
03813 data, free_data_function);
03814 CONNECTION_LOCK (connection);
03815 connection->watches = watches;
03816
03817 CONNECTION_UNLOCK (connection);
03818
03819 dbus_connection_unref (connection);
03820
03821 return retval;
03822 }
03823
03857 dbus_bool_t
03858 dbus_connection_set_timeout_functions (DBusConnection *connection,
03859 DBusAddTimeoutFunction add_function,
03860 DBusRemoveTimeoutFunction remove_function,
03861 DBusTimeoutToggledFunction toggled_function,
03862 void *data,
03863 DBusFreeFunction free_data_function)
03864 {
03865 dbus_bool_t retval;
03866 DBusTimeoutList *timeouts;
03867
03868 _dbus_return_val_if_fail (connection != NULL, FALSE);
03869
03870 CONNECTION_LOCK (connection);
03871
03872 #ifndef DBUS_DISABLE_CHECKS
03873 if (connection->timeouts == NULL)
03874 {
03875 _dbus_warn ("Re-entrant call to %s is not allowed\n",
03876 _DBUS_FUNCTION_NAME);
03877 return FALSE;
03878 }
03879 #endif
03880
03881
03882 _dbus_connection_ref_unlocked (connection);
03883
03884 timeouts = connection->timeouts;
03885 connection->timeouts = NULL;
03886 CONNECTION_UNLOCK (connection);
03887
03888 retval = _dbus_timeout_list_set_functions (timeouts,
03889 add_function, remove_function,
03890 toggled_function,
03891 data, free_data_function);
03892 CONNECTION_LOCK (connection);
03893 connection->timeouts = timeouts;
03894
03895 CONNECTION_UNLOCK (connection);
03896
03897 dbus_connection_unref (connection);
03898
03899 return retval;
03900 }
03901
03916 void
03917 dbus_connection_set_wakeup_main_function (DBusConnection *connection,
03918 DBusWakeupMainFunction wakeup_main_function,
03919 void *data,
03920 DBusFreeFunction free_data_function)
03921 {
03922 void *old_data;
03923 DBusFreeFunction old_free_data;
03924
03925 _dbus_return_if_fail (connection != NULL);
03926
03927 CONNECTION_LOCK (connection);
03928 old_data = connection->wakeup_main_data;
03929 old_free_data = connection->free_wakeup_main_data;
03930
03931 connection->wakeup_main_function = wakeup_main_function;
03932 connection->wakeup_main_data = data;
03933 connection->free_wakeup_main_data = free_data_function;
03934
03935 CONNECTION_UNLOCK (connection);
03936
03937
03938 if (old_free_data)
03939 (*old_free_data) (old_data);
03940 }
03941
03958 void
03959 dbus_connection_set_dispatch_status_function (DBusConnection *connection,
03960 DBusDispatchStatusFunction function,
03961 void *data,
03962 DBusFreeFunction free_data_function)
03963 {
03964 void *old_data;
03965 DBusFreeFunction old_free_data;
03966
03967 _dbus_return_if_fail (connection != NULL);
03968
03969 CONNECTION_LOCK (connection);
03970 old_data = connection->dispatch_status_data;
03971 old_free_data = connection->free_dispatch_status_data;
03972
03973 connection->dispatch_status_function = function;
03974 connection->dispatch_status_data = data;
03975 connection->free_dispatch_status_data = free_data_function;
03976
03977 CONNECTION_UNLOCK (connection);
03978
03979
03980 if (old_free_data)
03981 (*old_free_data) (old_data);
03982 }
03983
03996 dbus_bool_t
03997 dbus_connection_get_unix_fd (DBusConnection *connection,
03998 int *fd)
03999 {
04000 dbus_bool_t retval;
04001
04002 _dbus_return_val_if_fail (connection != NULL, FALSE);
04003 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04004
04005 CONNECTION_LOCK (connection);
04006
04007 retval = _dbus_transport_get_unix_fd (connection->transport,
04008 fd);
04009
04010 CONNECTION_UNLOCK (connection);
04011
04012 return retval;
04013 }
04014
04026 dbus_bool_t
04027 dbus_connection_get_unix_user (DBusConnection *connection,
04028 unsigned long *uid)
04029 {
04030 dbus_bool_t result;
04031
04032 _dbus_return_val_if_fail (connection != NULL, FALSE);
04033 _dbus_return_val_if_fail (uid != NULL, FALSE);
04034
04035 CONNECTION_LOCK (connection);
04036
04037 if (!_dbus_transport_get_is_authenticated (connection->transport))
04038 result = FALSE;
04039 else
04040 result = _dbus_transport_get_unix_user (connection->transport,
04041 uid);
04042 CONNECTION_UNLOCK (connection);
04043
04044 return result;
04045 }
04046
04057 dbus_bool_t
04058 dbus_connection_get_unix_process_id (DBusConnection *connection,
04059 unsigned long *pid)
04060 {
04061 dbus_bool_t result;
04062
04063 _dbus_return_val_if_fail (connection != NULL, FALSE);
04064 _dbus_return_val_if_fail (pid != NULL, FALSE);
04065
04066 CONNECTION_LOCK (connection);
04067
04068 if (!_dbus_transport_get_is_authenticated (connection->transport))
04069 result = FALSE;
04070 else
04071 result = _dbus_transport_get_unix_process_id (connection->transport,
04072 pid);
04073 CONNECTION_UNLOCK (connection);
04074
04075 return result;
04076 }
04077
04094 void
04095 dbus_connection_set_unix_user_function (DBusConnection *connection,
04096 DBusAllowUnixUserFunction function,
04097 void *data,
04098 DBusFreeFunction free_data_function)
04099 {
04100 void *old_data = NULL;
04101 DBusFreeFunction old_free_function = NULL;
04102
04103 _dbus_return_if_fail (connection != NULL);
04104
04105 CONNECTION_LOCK (connection);
04106 _dbus_transport_set_unix_user_function (connection->transport,
04107 function, data, free_data_function,
04108 &old_data, &old_free_function);
04109 CONNECTION_UNLOCK (connection);
04110
04111 if (old_free_function != NULL)
04112 (* old_free_function) (old_data);
04113 }
04114
04136 dbus_bool_t
04137 dbus_connection_add_filter (DBusConnection *connection,
04138 DBusHandleMessageFunction function,
04139 void *user_data,
04140 DBusFreeFunction free_data_function)
04141 {
04142 DBusMessageFilter *filter;
04143
04144 _dbus_return_val_if_fail (connection != NULL, FALSE);
04145 _dbus_return_val_if_fail (function != NULL, FALSE);
04146
04147 filter = dbus_new0 (DBusMessageFilter, 1);
04148 if (filter == NULL)
04149 return FALSE;
04150
04151 filter->refcount.value = 1;
04152
04153 CONNECTION_LOCK (connection);
04154
04155 if (!_dbus_list_append (&connection->filter_list,
04156 filter))
04157 {
04158 _dbus_message_filter_unref (filter);
04159 CONNECTION_UNLOCK (connection);
04160 return FALSE;
04161 }
04162
04163
04164
04165
04166
04167
04168 filter->function = function;
04169 filter->user_data = user_data;
04170 filter->free_user_data_function = free_data_function;
04171
04172 CONNECTION_UNLOCK (connection);
04173 return TRUE;
04174 }
04175
04188 void
04189 dbus_connection_remove_filter (DBusConnection *connection,
04190 DBusHandleMessageFunction function,
04191 void *user_data)
04192 {
04193 DBusList *link;
04194 DBusMessageFilter *filter;
04195
04196 _dbus_return_if_fail (connection != NULL);
04197 _dbus_return_if_fail (function != NULL);
04198
04199 CONNECTION_LOCK (connection);
04200
04201 filter = NULL;
04202
04203 link = _dbus_list_get_last_link (&connection->filter_list);
04204 while (link != NULL)
04205 {
04206 filter = link->data;
04207
04208 if (filter->function == function &&
04209 filter->user_data == user_data)
04210 {
04211 _dbus_list_remove_link (&connection->filter_list, link);
04212 filter->function = NULL;
04213
04214 break;
04215 }
04216
04217 link = _dbus_list_get_prev_link (&connection->filter_list, link);
04218 }
04219
04220 CONNECTION_UNLOCK (connection);
04221
04222 #ifndef DBUS_DISABLE_CHECKS
04223 if (filter == NULL)
04224 {
04225 _dbus_warn ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
04226 function, user_data);
04227 return;
04228 }
04229 #endif
04230
04231
04232 if (filter->free_user_data_function)
04233 (* filter->free_user_data_function) (filter->user_data);
04234
04235 filter->free_user_data_function = NULL;
04236 filter->user_data = NULL;
04237
04238 _dbus_message_filter_unref (filter);
04239 }
04240
04252 dbus_bool_t
04253 dbus_connection_register_object_path (DBusConnection *connection,
04254 const char *path,
04255 const DBusObjectPathVTable *vtable,
04256 void *user_data)
04257 {
04258 char **decomposed_path;
04259 dbus_bool_t retval;
04260
04261 _dbus_return_val_if_fail (connection != NULL, FALSE);
04262 _dbus_return_val_if_fail (path != NULL, FALSE);
04263 _dbus_return_val_if_fail (path[0] == '/', FALSE);
04264 _dbus_return_val_if_fail (vtable != NULL, FALSE);
04265
04266 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04267 return FALSE;
04268
04269 CONNECTION_LOCK (connection);
04270
04271 retval = _dbus_object_tree_register (connection->objects,
04272 FALSE,
04273 (const char **) decomposed_path, vtable,
04274 user_data);
04275
04276 CONNECTION_UNLOCK (connection);
04277
04278 dbus_free_string_array (decomposed_path);
04279
04280 return retval;
04281 }
04282
04295 dbus_bool_t
04296 dbus_connection_register_fallback (DBusConnection *connection,
04297 const char *path,
04298 const DBusObjectPathVTable *vtable,
04299 void *user_data)
04300 {
04301 char **decomposed_path;
04302 dbus_bool_t retval;
04303
04304 _dbus_return_val_if_fail (connection != NULL, FALSE);
04305 _dbus_return_val_if_fail (path != NULL, FALSE);
04306 _dbus_return_val_if_fail (path[0] == '/', FALSE);
04307 _dbus_return_val_if_fail (vtable != NULL, FALSE);
04308
04309 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04310 return FALSE;
04311
04312 CONNECTION_LOCK (connection);
04313
04314 retval = _dbus_object_tree_register (connection->objects,
04315 TRUE,
04316 (const char **) decomposed_path, vtable,
04317 user_data);
04318
04319 CONNECTION_UNLOCK (connection);
04320
04321 dbus_free_string_array (decomposed_path);
04322
04323 return retval;
04324 }
04325
04335 dbus_bool_t
04336 dbus_connection_unregister_object_path (DBusConnection *connection,
04337 const char *path)
04338 {
04339 char **decomposed_path;
04340
04341 _dbus_return_val_if_fail (connection != NULL, FALSE);
04342 _dbus_return_val_if_fail (path != NULL, FALSE);
04343 _dbus_return_val_if_fail (path[0] == '/', FALSE);
04344
04345 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04346 return FALSE;
04347
04348 CONNECTION_LOCK (connection);
04349
04350 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
04351
04352 dbus_free_string_array (decomposed_path);
04353
04354 return TRUE;
04355 }
04356
04367 dbus_bool_t
04368 dbus_connection_get_object_path_data (DBusConnection *connection,
04369 const char *path,
04370 void **data_p)
04371 {
04372 char **decomposed_path;
04373
04374 _dbus_return_val_if_fail (connection != NULL, FALSE);
04375 _dbus_return_val_if_fail (path != NULL, FALSE);
04376 _dbus_return_val_if_fail (data_p != NULL, FALSE);
04377
04378 *data_p = NULL;
04379
04380 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04381 return FALSE;
04382
04383 CONNECTION_LOCK (connection);
04384
04385 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
04386
04387 CONNECTION_UNLOCK (connection);
04388
04389 dbus_free_string_array (decomposed_path);
04390
04391 return TRUE;
04392 }
04393
04404 dbus_bool_t
04405 dbus_connection_list_registered (DBusConnection *connection,
04406 const char *parent_path,
04407 char ***child_entries)
04408 {
04409 char **decomposed_path;
04410 dbus_bool_t retval;
04411 _dbus_return_val_if_fail (connection != NULL, FALSE);
04412 _dbus_return_val_if_fail (parent_path != NULL, FALSE);
04413 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
04414 _dbus_return_val_if_fail (child_entries != NULL, FALSE);
04415
04416 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
04417 return FALSE;
04418
04419 CONNECTION_LOCK (connection);
04420
04421 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
04422 (const char **) decomposed_path,
04423 child_entries);
04424 dbus_free_string_array (decomposed_path);
04425
04426 return retval;
04427 }
04428
04429 static DBusDataSlotAllocator slot_allocator;
04430 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
04431
04446 dbus_bool_t
04447 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
04448 {
04449 return _dbus_data_slot_allocator_alloc (&slot_allocator,
04450 _DBUS_LOCK_NAME (connection_slots),
04451 slot_p);
04452 }
04453
04465 void
04466 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
04467 {
04468 _dbus_return_if_fail (*slot_p >= 0);
04469
04470 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
04471 }
04472
04486 dbus_bool_t
04487 dbus_connection_set_data (DBusConnection *connection,
04488 dbus_int32_t slot,
04489 void *data,
04490 DBusFreeFunction free_data_func)
04491 {
04492 DBusFreeFunction old_free_func;
04493 void *old_data;
04494 dbus_bool_t retval;
04495
04496 _dbus_return_val_if_fail (connection != NULL, FALSE);
04497 _dbus_return_val_if_fail (slot >= 0, FALSE);
04498
04499 CONNECTION_LOCK (connection);
04500
04501 retval = _dbus_data_slot_list_set (&slot_allocator,
04502 &connection->slot_list,
04503 slot, data, free_data_func,
04504 &old_free_func, &old_data);
04505
04506 CONNECTION_UNLOCK (connection);
04507
04508 if (retval)
04509 {
04510
04511 if (old_free_func)
04512 (* old_free_func) (old_data);
04513 }
04514
04515 return retval;
04516 }
04517
04526 void*
04527 dbus_connection_get_data (DBusConnection *connection,
04528 dbus_int32_t slot)
04529 {
04530 void *res;
04531
04532 _dbus_return_val_if_fail (connection != NULL, NULL);
04533
04534 CONNECTION_LOCK (connection);
04535
04536 res = _dbus_data_slot_list_get (&slot_allocator,
04537 &connection->slot_list,
04538 slot);
04539
04540 CONNECTION_UNLOCK (connection);
04541
04542 return res;
04543 }
04544
04551 void
04552 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
04553 {
04554 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
04555 }
04556
04565 void
04566 dbus_connection_set_max_message_size (DBusConnection *connection,
04567 long size)
04568 {
04569 _dbus_return_if_fail (connection != NULL);
04570
04571 CONNECTION_LOCK (connection);
04572 _dbus_transport_set_max_message_size (connection->transport,
04573 size);
04574 CONNECTION_UNLOCK (connection);
04575 }
04576
04583 long
04584 dbus_connection_get_max_message_size (DBusConnection *connection)
04585 {
04586 long res;
04587
04588 _dbus_return_val_if_fail (connection != NULL, 0);
04589
04590 CONNECTION_LOCK (connection);
04591 res = _dbus_transport_get_max_message_size (connection->transport);
04592 CONNECTION_UNLOCK (connection);
04593 return res;
04594 }
04595
04621 void
04622 dbus_connection_set_max_received_size (DBusConnection *connection,
04623 long size)
04624 {
04625 _dbus_return_if_fail (connection != NULL);
04626
04627 CONNECTION_LOCK (connection);
04628 _dbus_transport_set_max_received_size (connection->transport,
04629 size);
04630 CONNECTION_UNLOCK (connection);
04631 }
04632
04639 long
04640 dbus_connection_get_max_received_size (DBusConnection *connection)
04641 {
04642 long res;
04643
04644 _dbus_return_val_if_fail (connection != NULL, 0);
04645
04646 CONNECTION_LOCK (connection);
04647 res = _dbus_transport_get_max_received_size (connection->transport);
04648 CONNECTION_UNLOCK (connection);
04649 return res;
04650 }
04651
04662 long
04663 dbus_connection_get_outgoing_size (DBusConnection *connection)
04664 {
04665 long res;
04666
04667 _dbus_return_val_if_fail (connection != NULL, 0);
04668
04669 CONNECTION_LOCK (connection);
04670 res = _dbus_counter_get_value (connection->outgoing_counter);
04671 CONNECTION_UNLOCK (connection);
04672 return res;
04673 }
04674