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 *message_returned_cond;
01080 DBusCondVar *dispatch_cond;
01081 DBusCondVar *io_path_cond;
01082 DBusList *disconnect_link;
01083 DBusMessage *disconnect_message;
01084 DBusCounter *outgoing_counter;
01085 DBusObjectTree *objects;
01086
01087 watch_list = NULL;
01088 connection = NULL;
01089 pending_replies = NULL;
01090 timeout_list = NULL;
01091 mutex = NULL;
01092 io_path_mutex = NULL;
01093 dispatch_mutex = NULL;
01094 message_returned_cond = NULL;
01095 dispatch_cond = NULL;
01096 io_path_cond = NULL;
01097 disconnect_link = NULL;
01098 disconnect_message = NULL;
01099 outgoing_counter = NULL;
01100 objects = NULL;
01101
01102 watch_list = _dbus_watch_list_new ();
01103 if (watch_list == NULL)
01104 goto error;
01105
01106 timeout_list = _dbus_timeout_list_new ();
01107 if (timeout_list == NULL)
01108 goto error;
01109
01110 pending_replies =
01111 _dbus_hash_table_new (DBUS_HASH_INT,
01112 NULL,
01113 (DBusFreeFunction)free_pending_call_on_hash_removal);
01114 if (pending_replies == NULL)
01115 goto error;
01116
01117 connection = dbus_new0 (DBusConnection, 1);
01118 if (connection == NULL)
01119 goto error;
01120
01121 mutex = _dbus_mutex_new ();
01122 if (mutex == NULL)
01123 goto error;
01124
01125 io_path_mutex = _dbus_mutex_new ();
01126 if (io_path_mutex == NULL)
01127 goto error;
01128
01129 dispatch_mutex = _dbus_mutex_new ();
01130 if (dispatch_mutex == NULL)
01131 goto error;
01132
01133 message_returned_cond = _dbus_condvar_new ();
01134 if (message_returned_cond == NULL)
01135 goto error;
01136
01137 dispatch_cond = _dbus_condvar_new ();
01138 if (dispatch_cond == NULL)
01139 goto error;
01140
01141 io_path_cond = _dbus_condvar_new ();
01142 if (io_path_cond == NULL)
01143 goto error;
01144
01145 disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01146 DBUS_INTERFACE_LOCAL,
01147 "Disconnected");
01148
01149 if (disconnect_message == NULL)
01150 goto error;
01151
01152 disconnect_link = _dbus_list_alloc_link (disconnect_message);
01153 if (disconnect_link == NULL)
01154 goto error;
01155
01156 outgoing_counter = _dbus_counter_new ();
01157 if (outgoing_counter == NULL)
01158 goto error;
01159
01160 objects = _dbus_object_tree_new (connection);
01161 if (objects == NULL)
01162 goto error;
01163
01164 if (_dbus_modify_sigpipe)
01165 _dbus_disable_sigpipe ();
01166
01167 connection->refcount.value = 1;
01168 connection->mutex = mutex;
01169 connection->dispatch_cond = dispatch_cond;
01170 connection->dispatch_mutex = dispatch_mutex;
01171 connection->io_path_cond = io_path_cond;
01172 connection->io_path_mutex = io_path_mutex;
01173 connection->transport = transport;
01174 connection->watches = watch_list;
01175 connection->timeouts = timeout_list;
01176 connection->pending_replies = pending_replies;
01177 connection->outgoing_counter = outgoing_counter;
01178 connection->filter_list = NULL;
01179 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE;
01180 connection->objects = objects;
01181 connection->exit_on_disconnect = FALSE;
01182 connection->shareable = FALSE;
01183 #ifndef DBUS_DISABLE_CHECKS
01184 connection->generation = _dbus_current_generation;
01185 #endif
01186
01187 _dbus_data_slot_list_init (&connection->slot_list);
01188
01189 connection->client_serial = 1;
01190
01191 connection->disconnect_message_link = disconnect_link;
01192
01193 CONNECTION_LOCK (connection);
01194
01195 if (!_dbus_transport_set_connection (transport, connection))
01196 goto error;
01197
01198 _dbus_transport_ref (transport);
01199
01200 CONNECTION_UNLOCK (connection);
01201
01202 return connection;
01203
01204 error:
01205 if (disconnect_message != NULL)
01206 dbus_message_unref (disconnect_message);
01207
01208 if (disconnect_link != NULL)
01209 _dbus_list_free_link (disconnect_link);
01210
01211 if (io_path_cond != NULL)
01212 _dbus_condvar_free (io_path_cond);
01213
01214 if (dispatch_cond != NULL)
01215 _dbus_condvar_free (dispatch_cond);
01216
01217 if (message_returned_cond != NULL)
01218 _dbus_condvar_free (message_returned_cond);
01219
01220 if (mutex != NULL)
01221 _dbus_mutex_free (mutex);
01222
01223 if (io_path_mutex != NULL)
01224 _dbus_mutex_free (io_path_mutex);
01225
01226 if (dispatch_mutex != NULL)
01227 _dbus_mutex_free (dispatch_mutex);
01228
01229 if (connection != NULL)
01230 dbus_free (connection);
01231
01232 if (pending_replies)
01233 _dbus_hash_table_unref (pending_replies);
01234
01235 if (watch_list)
01236 _dbus_watch_list_free (watch_list);
01237
01238 if (timeout_list)
01239 _dbus_timeout_list_free (timeout_list);
01240
01241 if (outgoing_counter)
01242 _dbus_counter_unref (outgoing_counter);
01243
01244 if (objects)
01245 _dbus_object_tree_unref (objects);
01246
01247 return NULL;
01248 }
01249
01257 DBusConnection *
01258 _dbus_connection_ref_unlocked (DBusConnection *connection)
01259 {
01260 _dbus_assert (connection != NULL);
01261 _dbus_assert (connection->generation == _dbus_current_generation);
01262
01263 HAVE_LOCK_CHECK (connection);
01264
01265 #ifdef DBUS_HAVE_ATOMIC_INT
01266 _dbus_atomic_inc (&connection->refcount);
01267 #else
01268 _dbus_assert (connection->refcount.value > 0);
01269 connection->refcount.value += 1;
01270 #endif
01271
01272 return connection;
01273 }
01274
01281 void
01282 _dbus_connection_unref_unlocked (DBusConnection *connection)
01283 {
01284 dbus_bool_t last_unref;
01285
01286 HAVE_LOCK_CHECK (connection);
01287
01288 _dbus_assert (connection != NULL);
01289
01290
01291
01292
01293
01294 #ifdef DBUS_HAVE_ATOMIC_INT
01295 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01296 #else
01297 _dbus_assert (connection->refcount.value > 0);
01298
01299 connection->refcount.value -= 1;
01300 last_unref = (connection->refcount.value == 0);
01301 #if 0
01302 printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01303 #endif
01304 #endif
01305
01306 if (last_unref)
01307 _dbus_connection_last_unref (connection);
01308 }
01309
01310 static dbus_uint32_t
01311 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01312 {
01313 int serial;
01314
01315 serial = connection->client_serial++;
01316
01317 if (connection->client_serial < 0)
01318 connection->client_serial = 1;
01319
01320 return serial;
01321 }
01322
01336 dbus_bool_t
01337 _dbus_connection_handle_watch (DBusWatch *watch,
01338 unsigned int condition,
01339 void *data)
01340 {
01341 DBusConnection *connection;
01342 dbus_bool_t retval;
01343 DBusDispatchStatus status;
01344
01345 connection = data;
01346
01347 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01348
01349 CONNECTION_LOCK (connection);
01350 _dbus_connection_acquire_io_path (connection, -1);
01351 HAVE_LOCK_CHECK (connection);
01352 retval = _dbus_transport_handle_watch (connection->transport,
01353 watch, condition);
01354
01355 _dbus_connection_release_io_path (connection);
01356
01357 HAVE_LOCK_CHECK (connection);
01358
01359 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01360
01361 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01362
01363
01364 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01365
01366 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01367
01368 return retval;
01369 }
01370
01371 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01372 static DBusHashTable *shared_connections = NULL;
01373
01374 static void
01375 shared_connections_shutdown (void *data)
01376 {
01377 _DBUS_LOCK (shared_connections);
01378
01379 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01380 _dbus_hash_table_unref (shared_connections);
01381 shared_connections = NULL;
01382
01383 _DBUS_UNLOCK (shared_connections);
01384 }
01385
01386 static dbus_bool_t
01387 connection_lookup_shared (DBusAddressEntry *entry,
01388 DBusConnection **result)
01389 {
01390 _dbus_verbose ("checking for existing connection\n");
01391
01392 *result = NULL;
01393
01394 _DBUS_LOCK (shared_connections);
01395
01396 if (shared_connections == NULL)
01397 {
01398 _dbus_verbose ("creating shared_connections hash table\n");
01399
01400 shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01401 dbus_free,
01402 NULL);
01403 if (shared_connections == NULL)
01404 {
01405 _DBUS_UNLOCK (shared_connections);
01406 return FALSE;
01407 }
01408
01409 if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01410 {
01411 _dbus_hash_table_unref (shared_connections);
01412 shared_connections = NULL;
01413 _DBUS_UNLOCK (shared_connections);
01414 return FALSE;
01415 }
01416
01417 _dbus_verbose (" successfully created shared_connections\n");
01418
01419 _DBUS_UNLOCK (shared_connections);
01420 return TRUE;
01421 }
01422 else
01423 {
01424 const char *guid;
01425
01426 guid = dbus_address_entry_get_value (entry, "guid");
01427
01428 if (guid != NULL)
01429 {
01430 *result = _dbus_hash_table_lookup_string (shared_connections,
01431 guid);
01432
01433 if (*result)
01434 {
01435
01436
01437
01438
01439
01440
01441
01442
01443 dbus_connection_ref (*result);
01444
01445 _dbus_verbose ("looked up existing connection to server guid %s\n",
01446 guid);
01447 }
01448 }
01449
01450 _DBUS_UNLOCK (shared_connections);
01451 return TRUE;
01452 }
01453 }
01454
01455 static dbus_bool_t
01456 connection_record_shared_unlocked (DBusConnection *connection,
01457 const char *guid)
01458 {
01459 char *guid_key;
01460 char *guid_in_connection;
01461
01462
01463
01464
01465
01466
01467 _dbus_assert (connection->server_guid == NULL);
01468 _dbus_assert (connection->shareable);
01469
01470 guid_key = _dbus_strdup (guid);
01471 if (guid_key == NULL)
01472 return FALSE;
01473
01474 guid_in_connection = _dbus_strdup (guid);
01475 if (guid_in_connection == NULL)
01476 {
01477 dbus_free (guid_key);
01478 return FALSE;
01479 }
01480
01481 _DBUS_LOCK (shared_connections);
01482 _dbus_assert (shared_connections != NULL);
01483
01484 if (!_dbus_hash_table_insert_string (shared_connections,
01485 guid_key, connection))
01486 {
01487 dbus_free (guid_key);
01488 dbus_free (guid_in_connection);
01489 _DBUS_UNLOCK (shared_connections);
01490 return FALSE;
01491 }
01492
01493 connection->server_guid = guid_in_connection;
01494
01495 _dbus_verbose ("stored connection to %s to be shared\n",
01496 connection->server_guid);
01497
01498 _DBUS_UNLOCK (shared_connections);
01499
01500 _dbus_assert (connection->server_guid != NULL);
01501
01502 return TRUE;
01503 }
01504
01505 static void
01506 connection_forget_shared_unlocked (DBusConnection *connection)
01507 {
01508 HAVE_LOCK_CHECK (connection);
01509
01510 if (connection->server_guid == NULL)
01511 return;
01512
01513 _dbus_verbose ("dropping connection to %s out of the shared table\n",
01514 connection->server_guid);
01515
01516 _DBUS_LOCK (shared_connections);
01517
01518 if (!_dbus_hash_table_remove_string (shared_connections,
01519 connection->server_guid))
01520 _dbus_assert_not_reached ("connection was not in the shared table");
01521
01522 dbus_free (connection->server_guid);
01523 connection->server_guid = NULL;
01524
01525 _DBUS_UNLOCK (shared_connections);
01526 }
01527
01528 static DBusConnection*
01529 connection_try_from_address_entry (DBusAddressEntry *entry,
01530 DBusError *error)
01531 {
01532 DBusTransport *transport;
01533 DBusConnection *connection;
01534
01535 transport = _dbus_transport_open (entry, error);
01536
01537 if (transport == NULL)
01538 {
01539 _DBUS_ASSERT_ERROR_IS_SET (error);
01540 return NULL;
01541 }
01542
01543 connection = _dbus_connection_new_for_transport (transport);
01544
01545 _dbus_transport_unref (transport);
01546
01547 if (connection == NULL)
01548 {
01549 _DBUS_SET_OOM (error);
01550 return NULL;
01551 }
01552
01553 #ifndef DBUS_DISABLE_CHECKS
01554 _dbus_assert (!connection->have_connection_lock);
01555 #endif
01556 return connection;
01557 }
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571 static DBusConnection*
01572 _dbus_connection_open_internal (const char *address,
01573 dbus_bool_t shared,
01574 DBusError *error)
01575 {
01576 DBusConnection *connection;
01577 DBusAddressEntry **entries;
01578 DBusError tmp_error;
01579 DBusError first_error;
01580 int len, i;
01581
01582 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01583
01584 _dbus_verbose ("opening %s connection to: %s\n",
01585 shared ? "shared" : "private", address);
01586
01587 if (!dbus_parse_address (address, &entries, &len, error))
01588 return NULL;
01589
01590 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01591
01592 connection = NULL;
01593
01594 dbus_error_init (&tmp_error);
01595 dbus_error_init (&first_error);
01596 for (i = 0; i < len; i++)
01597 {
01598 if (shared)
01599 {
01600 if (!connection_lookup_shared (entries[i], &connection))
01601 _DBUS_SET_OOM (&tmp_error);
01602 }
01603
01604 if (connection == NULL)
01605 {
01606 connection = connection_try_from_address_entry (entries[i],
01607 &tmp_error);
01608
01609 if (connection != NULL && shared)
01610 {
01611 const char *guid;
01612
01613 connection->shareable = TRUE;
01614
01615 guid = dbus_address_entry_get_value (entries[i], "guid");
01616
01617
01618
01619
01620
01621 if (guid &&
01622 !connection_record_shared_unlocked (connection, guid))
01623 {
01624 _DBUS_SET_OOM (&tmp_error);
01625 dbus_connection_close (connection);
01626 dbus_connection_unref (connection);
01627 connection = NULL;
01628 }
01629
01630
01631
01632
01633 }
01634 }
01635
01636 if (connection)
01637 break;
01638
01639 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01640
01641 if (i == 0)
01642 dbus_move_error (&tmp_error, &first_error);
01643 else
01644 dbus_error_free (&tmp_error);
01645 }
01646
01647
01648
01649 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01650 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01651
01652 if (connection == NULL)
01653 {
01654 _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01655 dbus_move_error (&first_error, error);
01656 }
01657 else
01658 {
01659 dbus_error_free (&first_error);
01660 }
01661
01662 dbus_address_entries_free (entries);
01663 return connection;
01664 }
01665
01693 DBusConnection*
01694 dbus_connection_open (const char *address,
01695 DBusError *error)
01696 {
01697 DBusConnection *connection;
01698
01699 _dbus_return_val_if_fail (address != NULL, NULL);
01700 _dbus_return_val_if_error_is_set (error, NULL);
01701
01702 connection = _dbus_connection_open_internal (address,
01703 TRUE,
01704 error);
01705
01706 return connection;
01707 }
01708
01723 DBusConnection*
01724 dbus_connection_open_private (const char *address,
01725 DBusError *error)
01726 {
01727 DBusConnection *connection;
01728
01729 _dbus_return_val_if_fail (address != NULL, NULL);
01730 _dbus_return_val_if_error_is_set (error, NULL);
01731
01732 connection = _dbus_connection_open_internal (address,
01733 FALSE,
01734 error);
01735
01736 return connection;
01737 }
01738
01745 DBusConnection *
01746 dbus_connection_ref (DBusConnection *connection)
01747 {
01748 _dbus_return_val_if_fail (connection != NULL, NULL);
01749 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
01750
01751
01752
01753
01754
01755 #ifdef DBUS_HAVE_ATOMIC_INT
01756 _dbus_atomic_inc (&connection->refcount);
01757 #else
01758 CONNECTION_LOCK (connection);
01759 _dbus_assert (connection->refcount.value > 0);
01760
01761 connection->refcount.value += 1;
01762 CONNECTION_UNLOCK (connection);
01763 #endif
01764
01765 return connection;
01766 }
01767
01768 static void
01769 free_outgoing_message (void *element,
01770 void *data)
01771 {
01772 DBusMessage *message = element;
01773 DBusConnection *connection = data;
01774
01775 _dbus_message_remove_size_counter (message,
01776 connection->outgoing_counter,
01777 NULL);
01778 dbus_message_unref (message);
01779 }
01780
01781
01782
01783
01784
01785 static void
01786 _dbus_connection_last_unref (DBusConnection *connection)
01787 {
01788 DBusList *link;
01789
01790 _dbus_verbose ("Finalizing connection %p\n", connection);
01791
01792 _dbus_assert (connection->refcount.value == 0);
01793
01794
01795
01796
01797 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
01798 _dbus_assert (connection->server_guid == NULL);
01799
01800
01801 _dbus_object_tree_free_all_unlocked (connection->objects);
01802
01803 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
01804 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
01805 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
01806
01807 _dbus_watch_list_free (connection->watches);
01808 connection->watches = NULL;
01809
01810 _dbus_timeout_list_free (connection->timeouts);
01811 connection->timeouts = NULL;
01812
01813 _dbus_data_slot_list_free (&connection->slot_list);
01814
01815 link = _dbus_list_get_first_link (&connection->filter_list);
01816 while (link != NULL)
01817 {
01818 DBusMessageFilter *filter = link->data;
01819 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
01820
01821 filter->function = NULL;
01822 _dbus_message_filter_unref (filter);
01823 link->data = NULL;
01824
01825 link = next;
01826 }
01827 _dbus_list_clear (&connection->filter_list);
01828
01829
01830
01831 _dbus_object_tree_unref (connection->objects);
01832
01833 _dbus_hash_table_unref (connection->pending_replies);
01834 connection->pending_replies = NULL;
01835
01836 _dbus_list_clear (&connection->filter_list);
01837
01838 _dbus_list_foreach (&connection->outgoing_messages,
01839 free_outgoing_message,
01840 connection);
01841 _dbus_list_clear (&connection->outgoing_messages);
01842
01843 _dbus_list_foreach (&connection->incoming_messages,
01844 (DBusForeachFunction) dbus_message_unref,
01845 NULL);
01846 _dbus_list_clear (&connection->incoming_messages);
01847
01848 _dbus_counter_unref (connection->outgoing_counter);
01849
01850 _dbus_transport_unref (connection->transport);
01851
01852 if (connection->disconnect_message_link)
01853 {
01854 DBusMessage *message = connection->disconnect_message_link->data;
01855 dbus_message_unref (message);
01856 _dbus_list_free_link (connection->disconnect_message_link);
01857 }
01858
01859 _dbus_list_clear (&connection->link_cache);
01860
01861 _dbus_condvar_free (connection->dispatch_cond);
01862 _dbus_condvar_free (connection->io_path_cond);
01863
01864 _dbus_mutex_free (connection->io_path_mutex);
01865 _dbus_mutex_free (connection->dispatch_mutex);
01866
01867 _dbus_mutex_free (connection->mutex);
01868
01869 dbus_free (connection);
01870 }
01871
01883 void
01884 dbus_connection_unref (DBusConnection *connection)
01885 {
01886 dbus_bool_t last_unref;
01887
01888 _dbus_return_if_fail (connection != NULL);
01889 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
01890
01891
01892
01893
01894
01895 #ifdef DBUS_HAVE_ATOMIC_INT
01896 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01897 #else
01898 CONNECTION_LOCK (connection);
01899
01900 _dbus_assert (connection->refcount.value > 0);
01901
01902 connection->refcount.value -= 1;
01903 last_unref = (connection->refcount.value == 0);
01904
01905 #if 0
01906 printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
01907 #endif
01908
01909 CONNECTION_UNLOCK (connection);
01910 #endif
01911
01912 if (last_unref)
01913 _dbus_connection_last_unref (connection);
01914 }
01915
01929 void
01930 dbus_connection_close (DBusConnection *connection)
01931 {
01932 DBusDispatchStatus status;
01933
01934 _dbus_return_if_fail (connection != NULL);
01935 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
01936
01937 _dbus_verbose ("Disconnecting %p\n", connection);
01938
01939 CONNECTION_LOCK (connection);
01940
01941 _dbus_transport_disconnect (connection->transport);
01942
01943 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01944 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01945
01946
01947 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01948 }
01949
01956 void
01957 dbus_connection_disconnect (DBusConnection *connection)
01958 {
01959 dbus_connection_close (connection);
01960 }
01961
01962 static dbus_bool_t
01963 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
01964 {
01965 HAVE_LOCK_CHECK (connection);
01966 return _dbus_transport_get_is_connected (connection->transport);
01967 }
01968
01979 dbus_bool_t
01980 dbus_connection_get_is_connected (DBusConnection *connection)
01981 {
01982 dbus_bool_t res;
01983
01984 _dbus_return_val_if_fail (connection != NULL, FALSE);
01985
01986 CONNECTION_LOCK (connection);
01987 res = _dbus_connection_get_is_connected_unlocked (connection);
01988 CONNECTION_UNLOCK (connection);
01989
01990 return res;
01991 }
01992
02001 dbus_bool_t
02002 dbus_connection_get_is_authenticated (DBusConnection *connection)
02003 {
02004 dbus_bool_t res;
02005
02006 _dbus_return_val_if_fail (connection != NULL, FALSE);
02007
02008 CONNECTION_LOCK (connection);
02009 res = _dbus_transport_get_is_authenticated (connection->transport);
02010 CONNECTION_UNLOCK (connection);
02011
02012 return res;
02013 }
02014
02028 void
02029 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
02030 dbus_bool_t exit_on_disconnect)
02031 {
02032 _dbus_return_if_fail (connection != NULL);
02033
02034 CONNECTION_LOCK (connection);
02035 connection->exit_on_disconnect = exit_on_disconnect != FALSE;
02036 CONNECTION_UNLOCK (connection);
02037 }
02038
02039 static DBusPreallocatedSend*
02040 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
02041 {
02042 DBusPreallocatedSend *preallocated;
02043
02044 HAVE_LOCK_CHECK (connection);
02045
02046 _dbus_assert (connection != NULL);
02047
02048 preallocated = dbus_new (DBusPreallocatedSend, 1);
02049 if (preallocated == NULL)
02050 return NULL;
02051
02052 if (connection->link_cache != NULL)
02053 {
02054 preallocated->queue_link =
02055 _dbus_list_pop_first_link (&connection->link_cache);
02056 preallocated->queue_link->data = NULL;
02057 }
02058 else
02059 {
02060 preallocated->queue_link = _dbus_list_alloc_link (NULL);
02061 if (preallocated->queue_link == NULL)
02062 goto failed_0;
02063 }
02064
02065 if (connection->link_cache != NULL)
02066 {
02067 preallocated->counter_link =
02068 _dbus_list_pop_first_link (&connection->link_cache);
02069 preallocated->counter_link->data = connection->outgoing_counter;
02070 }
02071 else
02072 {
02073 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
02074 if (preallocated->counter_link == NULL)
02075 goto failed_1;
02076 }
02077
02078 _dbus_counter_ref (preallocated->counter_link->data);
02079
02080 preallocated->connection = connection;
02081
02082 return preallocated;
02083
02084 failed_1:
02085 _dbus_list_free_link (preallocated->queue_link);
02086 failed_0:
02087 dbus_free (preallocated);
02088
02089 return NULL;
02090 }
02091
02101 DBusPreallocatedSend*
02102 dbus_connection_preallocate_send (DBusConnection *connection)
02103 {
02104 DBusPreallocatedSend *preallocated;
02105
02106 _dbus_return_val_if_fail (connection != NULL, NULL);
02107
02108 CONNECTION_LOCK (connection);
02109
02110 preallocated =
02111 _dbus_connection_preallocate_send_unlocked (connection);
02112
02113 CONNECTION_UNLOCK (connection);
02114
02115 return preallocated;
02116 }
02117
02127 void
02128 dbus_connection_free_preallocated_send (DBusConnection *connection,
02129 DBusPreallocatedSend *preallocated)
02130 {
02131 _dbus_return_if_fail (connection != NULL);
02132 _dbus_return_if_fail (preallocated != NULL);
02133 _dbus_return_if_fail (connection == preallocated->connection);
02134
02135 _dbus_list_free_link (preallocated->queue_link);
02136 _dbus_counter_unref (preallocated->counter_link->data);
02137 _dbus_list_free_link (preallocated->counter_link);
02138 dbus_free (preallocated);
02139 }
02140
02141
02142 static void
02143 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection,
02144 DBusPreallocatedSend *preallocated,
02145 DBusMessage *message,
02146 dbus_uint32_t *client_serial)
02147 {
02148 dbus_uint32_t serial;
02149 const char *sig;
02150
02151 preallocated->queue_link->data = message;
02152 _dbus_list_prepend_link (&connection->outgoing_messages,
02153 preallocated->queue_link);
02154
02155 _dbus_message_add_size_counter_link (message,
02156 preallocated->counter_link);
02157
02158 dbus_free (preallocated);
02159 preallocated = NULL;
02160
02161 dbus_message_ref (message);
02162
02163 connection->n_outgoing += 1;
02164
02165 sig = dbus_message_get_signature (message);
02166
02167 _dbus_verbose ("Message %p (%d %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
02168 message,
02169 dbus_message_get_type (message),
02170 dbus_message_get_path (message),
02171 dbus_message_get_interface (message) ?
02172 dbus_message_get_interface (message) :
02173 "no interface",
02174 dbus_message_get_member (message) ?
02175 dbus_message_get_member (message) :
02176 "no member",
02177 sig,
02178 dbus_message_get_destination (message) ?
02179 dbus_message_get_destination (message) :
02180 "null",
02181 connection,
02182 connection->n_outgoing);
02183
02184 if (dbus_message_get_serial (message) == 0)
02185 {
02186 serial = _dbus_connection_get_next_client_serial (connection);
02187 _dbus_message_set_serial (message, serial);
02188 if (client_serial)
02189 *client_serial = serial;
02190 }
02191 else
02192 {
02193 if (client_serial)
02194 *client_serial = dbus_message_get_serial (message);
02195 }
02196
02197 _dbus_verbose ("Message %p serial is %u\n",
02198 message, dbus_message_get_serial (message));
02199
02200 _dbus_message_lock (message);
02201
02202
02203
02204
02205 _dbus_connection_do_iteration_unlocked (connection,
02206 DBUS_ITERATION_DO_WRITING,
02207 -1);
02208
02209
02210 if (connection->n_outgoing > 0)
02211 _dbus_connection_wakeup_mainloop (connection);
02212 }
02213
02214 static void
02215 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection,
02216 DBusPreallocatedSend *preallocated,
02217 DBusMessage *message,
02218 dbus_uint32_t *client_serial)
02219 {
02220 DBusDispatchStatus status;
02221
02222 HAVE_LOCK_CHECK (connection);
02223
02224 _dbus_connection_send_preallocated_unlocked_no_update (connection,
02225 preallocated,
02226 message, client_serial);
02227
02228 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02229 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02230
02231
02232 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02233 }
02234
02247 void
02248 dbus_connection_send_preallocated (DBusConnection *connection,
02249 DBusPreallocatedSend *preallocated,
02250 DBusMessage *message,
02251 dbus_uint32_t *client_serial)
02252 {
02253 _dbus_return_if_fail (connection != NULL);
02254 _dbus_return_if_fail (preallocated != NULL);
02255 _dbus_return_if_fail (message != NULL);
02256 _dbus_return_if_fail (preallocated->connection == connection);
02257 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
02258 (dbus_message_get_interface (message) != NULL &&
02259 dbus_message_get_member (message) != NULL));
02260 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
02261 (dbus_message_get_interface (message) != NULL &&
02262 dbus_message_get_member (message) != NULL));
02263
02264 CONNECTION_LOCK (connection);
02265 _dbus_connection_send_preallocated_and_unlock (connection,
02266 preallocated,
02267 message, client_serial);
02268 }
02269
02270 static dbus_bool_t
02271 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
02272 DBusMessage *message,
02273 dbus_uint32_t *client_serial)
02274 {
02275 DBusPreallocatedSend *preallocated;
02276
02277 _dbus_assert (connection != NULL);
02278 _dbus_assert (message != NULL);
02279
02280 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02281 if (preallocated == NULL)
02282 return FALSE;
02283
02284 _dbus_connection_send_preallocated_unlocked_no_update (connection,
02285 preallocated,
02286 message,
02287 client_serial);
02288 return TRUE;
02289 }
02290
02291 dbus_bool_t
02292 _dbus_connection_send_and_unlock (DBusConnection *connection,
02293 DBusMessage *message,
02294 dbus_uint32_t *client_serial)
02295 {
02296 DBusPreallocatedSend *preallocated;
02297
02298 _dbus_assert (connection != NULL);
02299 _dbus_assert (message != NULL);
02300
02301 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02302 if (preallocated == NULL)
02303 {
02304 CONNECTION_UNLOCK (connection);
02305 return FALSE;
02306 }
02307
02308 _dbus_connection_send_preallocated_and_unlock (connection,
02309 preallocated,
02310 message,
02311 client_serial);
02312 return TRUE;
02313 }
02314
02333 dbus_bool_t
02334 dbus_connection_send (DBusConnection *connection,
02335 DBusMessage *message,
02336 dbus_uint32_t *client_serial)
02337 {
02338 _dbus_return_val_if_fail (connection != NULL, FALSE);
02339 _dbus_return_val_if_fail (message != NULL, FALSE);
02340
02341 CONNECTION_LOCK (connection);
02342
02343 return _dbus_connection_send_and_unlock (connection,
02344 message,
02345 client_serial);
02346 }
02347
02348 static dbus_bool_t
02349 reply_handler_timeout (void *data)
02350 {
02351 DBusConnection *connection;
02352 DBusDispatchStatus status;
02353 DBusPendingCall *pending = data;
02354
02355 connection = pending->connection;
02356
02357 CONNECTION_LOCK (connection);
02358 if (pending->timeout_link)
02359 {
02360 _dbus_connection_queue_synthesized_message_link (connection,
02361 pending->timeout_link);
02362 pending->timeout_link = NULL;
02363 }
02364
02365 _dbus_connection_remove_timeout (connection,
02366 pending->timeout);
02367 pending->timeout_added = FALSE;
02368
02369 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02370 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02371
02372
02373 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02374
02375 return TRUE;
02376 }
02377
02415 dbus_bool_t
02416 dbus_connection_send_with_reply (DBusConnection *connection,
02417 DBusMessage *message,
02418 DBusPendingCall **pending_return,
02419 int timeout_milliseconds)
02420 {
02421 DBusPendingCall *pending;
02422 DBusMessage *reply;
02423 DBusList *reply_link;
02424 dbus_int32_t serial = -1;
02425 DBusDispatchStatus status;
02426
02427 _dbus_return_val_if_fail (connection != NULL, FALSE);
02428 _dbus_return_val_if_fail (message != NULL, FALSE);
02429 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02430
02431 if (pending_return)
02432 *pending_return = NULL;
02433
02434 pending = _dbus_pending_call_new (connection,
02435 timeout_milliseconds,
02436 reply_handler_timeout);
02437
02438 if (pending == NULL)
02439 return FALSE;
02440
02441 CONNECTION_LOCK (connection);
02442
02443
02444 if (dbus_message_get_serial (message) == 0)
02445 {
02446 serial = _dbus_connection_get_next_client_serial (connection);
02447 _dbus_message_set_serial (message, serial);
02448 }
02449
02450 pending->reply_serial = serial;
02451
02452 reply = dbus_message_new_error (message, DBUS_ERROR_NO_REPLY,
02453 "No reply within specified time");
02454 if (reply == NULL)
02455 goto error;
02456
02457 reply_link = _dbus_list_alloc_link (reply);
02458 if (reply_link == NULL)
02459 {
02460 CONNECTION_UNLOCK (connection);
02461 dbus_message_unref (reply);
02462 goto error_unlocked;
02463 }
02464
02465 pending->timeout_link = reply_link;
02466
02467
02468
02469
02470
02471 if (!_dbus_connection_attach_pending_call_unlocked (connection,
02472 pending))
02473 goto error;
02474
02475 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
02476 {
02477 _dbus_connection_detach_pending_call_and_unlock (connection,
02478 pending);
02479 goto error_unlocked;
02480 }
02481
02482 if (pending_return)
02483 *pending_return = pending;
02484 else
02485 {
02486 _dbus_connection_detach_pending_call_unlocked (connection, pending);
02487 dbus_pending_call_unref (pending);
02488 }
02489
02490 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02491 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02492
02493
02494 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02495
02496 return TRUE;
02497
02498 error:
02499 CONNECTION_UNLOCK (connection);
02500 error_unlocked:
02501 dbus_pending_call_unref (pending);
02502 return FALSE;
02503 }
02504
02505
02506
02507
02508 static DBusMessage*
02509 check_for_reply_unlocked (DBusConnection *connection,
02510 dbus_uint32_t client_serial)
02511 {
02512 DBusList *link;
02513
02514 HAVE_LOCK_CHECK (connection);
02515
02516 link = _dbus_list_get_first_link (&connection->incoming_messages);
02517
02518 while (link != NULL)
02519 {
02520 DBusMessage *reply = link->data;
02521
02522 if (dbus_message_get_reply_serial (reply) == client_serial)
02523 {
02524 _dbus_list_remove_link (&connection->incoming_messages, link);
02525 connection->n_incoming -= 1;
02526 return reply;
02527 }
02528 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02529 }
02530
02531 return NULL;
02532 }
02533
02543 static void
02544 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02545 {
02546 if (timeout_milliseconds == -1)
02547 _dbus_sleep_milliseconds (1000);
02548 else if (timeout_milliseconds < 100)
02549 ;
02550 else if (timeout_milliseconds <= 1000)
02551 _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02552 else
02553 _dbus_sleep_milliseconds (1000);
02554 }
02555
02570 void
02571 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02572 {
02573 long start_tv_sec, start_tv_usec;
02574 long end_tv_sec, end_tv_usec;
02575 long tv_sec, tv_usec;
02576 DBusDispatchStatus status;
02577 DBusConnection *connection;
02578 dbus_uint32_t client_serial;
02579 int timeout_milliseconds;
02580
02581 _dbus_assert (pending != NULL);
02582
02583 if (dbus_pending_call_get_completed (pending))
02584 return;
02585
02586 if (pending->connection == NULL)
02587 return;
02588
02589 dbus_pending_call_ref (pending);
02590
02591 connection = pending->connection;
02592 client_serial = pending->reply_serial;
02593
02594
02595
02596
02597
02598 timeout_milliseconds = dbus_timeout_get_interval (pending->timeout);
02599
02600
02601 dbus_connection_flush (connection);
02602
02603 CONNECTION_LOCK (connection);
02604
02605 _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02606 end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
02607 end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
02608 end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
02609 end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
02610
02611 _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",
02612 timeout_milliseconds,
02613 client_serial,
02614 start_tv_sec, start_tv_usec,
02615 end_tv_sec, end_tv_usec);
02616
02617
02618
02619 _dbus_connection_do_iteration_unlocked (connection,
02620 DBUS_ITERATION_DO_READING |
02621 DBUS_ITERATION_BLOCK,
02622 timeout_milliseconds);
02623
02624 recheck_status:
02625
02626 _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME);
02627
02628 HAVE_LOCK_CHECK (connection);
02629
02630
02631
02632 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02633
02634
02635
02636
02637 if (dbus_pending_call_get_completed (pending))
02638 {
02639 _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME);
02640 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02641 dbus_pending_call_unref (pending);
02642 return;
02643 }
02644
02645 if (status == DBUS_DISPATCH_DATA_REMAINS)
02646 {
02647 DBusMessage *reply;
02648
02649 reply = check_for_reply_unlocked (connection, client_serial);
02650 if (reply != NULL)
02651 {
02652 _dbus_verbose ("%s checked for reply\n", _DBUS_FUNCTION_NAME);
02653
02654 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02655
02656 _dbus_pending_call_complete_and_unlock (pending, reply);
02657 dbus_message_unref (reply);
02658
02659 CONNECTION_LOCK (connection);
02660 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02661 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02662 dbus_pending_call_unref (pending);
02663
02664 return;
02665 }
02666 }
02667
02668 _dbus_get_current_time (&tv_sec, &tv_usec);
02669
02670 if (!_dbus_connection_get_is_connected_unlocked (connection))
02671 {
02672
02673
02674
02675
02676
02677 _dbus_pending_call_complete_and_unlock (pending, NULL);
02678 dbus_pending_call_unref (pending);
02679 return;
02680 }
02681 else if (tv_sec < start_tv_sec)
02682 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02683 else if (connection->disconnect_message_link == NULL)
02684 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02685 else if (tv_sec < end_tv_sec ||
02686 (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
02687 {
02688 timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
02689 (end_tv_usec - tv_usec) / 1000;
02690 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
02691 _dbus_assert (timeout_milliseconds >= 0);
02692
02693 if (status == DBUS_DISPATCH_NEED_MEMORY)
02694 {
02695
02696
02697
02698
02699 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02700
02701 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02702 }
02703 else
02704 {
02705
02706 _dbus_connection_do_iteration_unlocked (connection,
02707 DBUS_ITERATION_DO_READING |
02708 DBUS_ITERATION_BLOCK,
02709 timeout_milliseconds);
02710 }
02711
02712 goto recheck_status;
02713 }
02714
02715 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
02716 (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
02717
02718 _dbus_assert (!dbus_pending_call_get_completed (pending));
02719
02720
02721 _dbus_pending_call_complete_and_unlock (pending, NULL);
02722
02723
02724 CONNECTION_LOCK (connection);
02725 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02726 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02727 dbus_pending_call_unref (pending);
02728 }
02729
02752 DBusMessage*
02753 dbus_connection_send_with_reply_and_block (DBusConnection *connection,
02754 DBusMessage *message,
02755 int timeout_milliseconds,
02756 DBusError *error)
02757 {
02758 DBusMessage *reply;
02759 DBusPendingCall *pending;
02760
02761 _dbus_return_val_if_fail (connection != NULL, NULL);
02762 _dbus_return_val_if_fail (message != NULL, NULL);
02763 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02764 _dbus_return_val_if_error_is_set (error, NULL);
02765
02766 if (!dbus_connection_send_with_reply (connection, message,
02767 &pending, timeout_milliseconds))
02768 {
02769 _DBUS_SET_OOM (error);
02770 return NULL;
02771 }
02772
02773 _dbus_assert (pending != NULL);
02774
02775 dbus_pending_call_block (pending);
02776
02777 reply = dbus_pending_call_steal_reply (pending);
02778 dbus_pending_call_unref (pending);
02779
02780
02781
02782
02783 _dbus_assert (reply != NULL);
02784
02785 if (dbus_set_error_from_message (error, reply))
02786 {
02787 dbus_message_unref (reply);
02788 return NULL;
02789 }
02790 else
02791 return reply;
02792 }
02793
02799 void
02800 dbus_connection_flush (DBusConnection *connection)
02801 {
02802
02803
02804
02805
02806
02807 DBusDispatchStatus status;
02808
02809 _dbus_return_if_fail (connection != NULL);
02810
02811 CONNECTION_LOCK (connection);
02812 while (connection->n_outgoing > 0 &&
02813 _dbus_connection_get_is_connected_unlocked (connection))
02814 {
02815 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
02816 HAVE_LOCK_CHECK (connection);
02817 _dbus_connection_do_iteration_unlocked (connection,
02818 DBUS_ITERATION_DO_READING |
02819 DBUS_ITERATION_DO_WRITING |
02820 DBUS_ITERATION_BLOCK,
02821 -1);
02822 }
02823
02824 HAVE_LOCK_CHECK (connection);
02825 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02826 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02827
02828 HAVE_LOCK_CHECK (connection);
02829
02830 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02831
02832 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
02833 }
02834
02866 dbus_bool_t
02867 dbus_connection_read_write_dispatch (DBusConnection *connection,
02868 int timeout_milliseconds)
02869 {
02870 DBusDispatchStatus dstatus;
02871 dbus_bool_t dispatched_disconnected;
02872
02873 _dbus_return_val_if_fail (connection != NULL, FALSE);
02874 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02875 dstatus = dbus_connection_get_dispatch_status (connection);
02876
02877 if (dstatus == DBUS_DISPATCH_DATA_REMAINS)
02878 {
02879 _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME);
02880 dbus_connection_dispatch (connection);
02881 CONNECTION_LOCK (connection);
02882 }
02883 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
02884 {
02885 _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME);
02886 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02887 CONNECTION_LOCK (connection);
02888 }
02889 else
02890 {
02891 CONNECTION_LOCK (connection);
02892 if (_dbus_connection_get_is_connected_unlocked (connection))
02893 {
02894 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
02895 _dbus_connection_do_iteration_unlocked (connection,
02896 DBUS_ITERATION_DO_READING |
02897 DBUS_ITERATION_DO_WRITING |
02898 DBUS_ITERATION_BLOCK,
02899 timeout_milliseconds);
02900 }
02901 }
02902
02903 HAVE_LOCK_CHECK (connection);
02904 dispatched_disconnected = connection->n_incoming == 0 &&
02905 connection->disconnect_message_link == NULL;
02906 CONNECTION_UNLOCK (connection);
02907 return !dispatched_disconnected;
02908 }
02909
02929 DBusMessage*
02930 dbus_connection_borrow_message (DBusConnection *connection)
02931 {
02932 DBusDispatchStatus status;
02933 DBusMessage *message;
02934
02935 _dbus_return_val_if_fail (connection != NULL, NULL);
02936
02937 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
02938
02939
02940
02941
02942 status = dbus_connection_get_dispatch_status (connection);
02943 if (status != DBUS_DISPATCH_DATA_REMAINS)
02944 return NULL;
02945
02946 CONNECTION_LOCK (connection);
02947
02948 _dbus_connection_acquire_dispatch (connection);
02949
02950
02951 _dbus_assert (connection->message_borrowed == NULL);
02952
02953 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
02954
02955 message = connection->message_borrowed;
02956
02957
02958 if (message == NULL)
02959 _dbus_connection_release_dispatch (connection);
02960
02961 CONNECTION_UNLOCK (connection);
02962
02963 return message;
02964 }
02965
02974 void
02975 dbus_connection_return_message (DBusConnection *connection,
02976 DBusMessage *message)
02977 {
02978 _dbus_return_if_fail (connection != NULL);
02979 _dbus_return_if_fail (message != NULL);
02980 _dbus_return_if_fail (message == connection->message_borrowed);
02981 _dbus_return_if_fail (connection->dispatch_acquired);
02982
02983 CONNECTION_LOCK (connection);
02984
02985 _dbus_assert (message == connection->message_borrowed);
02986
02987 connection->message_borrowed = NULL;
02988
02989 _dbus_connection_release_dispatch (connection);
02990
02991 CONNECTION_UNLOCK (connection);
02992 }
02993
03003 void
03004 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03005 DBusMessage *message)
03006 {
03007 DBusMessage *pop_message;
03008
03009 _dbus_return_if_fail (connection != NULL);
03010 _dbus_return_if_fail (message != NULL);
03011 _dbus_return_if_fail (message == connection->message_borrowed);
03012 _dbus_return_if_fail (connection->dispatch_acquired);
03013
03014 CONNECTION_LOCK (connection);
03015
03016 _dbus_assert (message == connection->message_borrowed);
03017
03018 pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03019 _dbus_assert (message == pop_message);
03020
03021 connection->n_incoming -= 1;
03022
03023 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03024 message, connection->n_incoming);
03025
03026 connection->message_borrowed = NULL;
03027
03028 _dbus_connection_release_dispatch (connection);
03029
03030 CONNECTION_UNLOCK (connection);
03031 }
03032
03033
03034
03035
03036 static DBusList*
03037 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03038 {
03039 HAVE_LOCK_CHECK (connection);
03040
03041 _dbus_assert (connection->message_borrowed == NULL);
03042
03043 if (connection->n_incoming > 0)
03044 {
03045 DBusList *link;
03046
03047 link = _dbus_list_pop_first_link (&connection->incoming_messages);
03048 connection->n_incoming -= 1;
03049
03050 _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03051 link->data,
03052 dbus_message_get_type (link->data),
03053 dbus_message_get_path (link->data),
03054 dbus_message_get_interface (link->data) ?
03055 dbus_message_get_interface (link->data) :
03056 "no interface",
03057 dbus_message_get_member (link->data) ?
03058 dbus_message_get_member (link->data) :
03059 "no member",
03060 dbus_message_get_signature (link->data),
03061 connection, connection->n_incoming);
03062
03063 return link;
03064 }
03065 else
03066 return NULL;
03067 }
03068
03069
03070
03071
03072 static DBusMessage*
03073 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03074 {
03075 DBusList *link;
03076
03077 HAVE_LOCK_CHECK (connection);
03078
03079 link = _dbus_connection_pop_message_link_unlocked (connection);
03080
03081 if (link != NULL)
03082 {
03083 DBusMessage *message;
03084
03085 message = link->data;
03086
03087 _dbus_list_free_link (link);
03088
03089 return message;
03090 }
03091 else
03092 return NULL;
03093 }
03094
03095 static void
03096 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03097 DBusList *message_link)
03098 {
03099 HAVE_LOCK_CHECK (connection);
03100
03101 _dbus_assert (message_link != NULL);
03102
03103 _dbus_assert (connection->message_borrowed == NULL);
03104
03105 _dbus_assert (connection->dispatch_acquired);
03106
03107 _dbus_list_prepend_link (&connection->incoming_messages,
03108 message_link);
03109 connection->n_incoming += 1;
03110
03111 _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
03112 message_link->data,
03113 dbus_message_get_type (message_link->data),
03114 dbus_message_get_interface (message_link->data) ?
03115 dbus_message_get_interface (message_link->data) :
03116 "no interface",
03117 dbus_message_get_member (message_link->data) ?
03118 dbus_message_get_member (message_link->data) :
03119 "no member",
03120 dbus_message_get_signature (message_link->data),
03121 connection, connection->n_incoming);
03122 }
03123
03143 DBusMessage*
03144 dbus_connection_pop_message (DBusConnection *connection)
03145 {
03146 DBusMessage *message;
03147 DBusDispatchStatus status;
03148
03149 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03150
03151
03152
03153
03154 status = dbus_connection_get_dispatch_status (connection);
03155 if (status != DBUS_DISPATCH_DATA_REMAINS)
03156 return NULL;
03157
03158 CONNECTION_LOCK (connection);
03159 _dbus_connection_acquire_dispatch (connection);
03160 HAVE_LOCK_CHECK (connection);
03161
03162 message = _dbus_connection_pop_message_unlocked (connection);
03163
03164 _dbus_verbose ("Returning popped message %p\n", message);
03165
03166 _dbus_connection_release_dispatch (connection);
03167 CONNECTION_UNLOCK (connection);
03168
03169 return message;
03170 }
03171
03179 static void
03180 _dbus_connection_acquire_dispatch (DBusConnection *connection)
03181 {
03182 HAVE_LOCK_CHECK (connection);
03183
03184 _dbus_connection_ref_unlocked (connection);
03185 CONNECTION_UNLOCK (connection);
03186
03187 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03188 _dbus_mutex_lock (connection->dispatch_mutex);
03189
03190 while (connection->dispatch_acquired)
03191 {
03192 _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
03193 _dbus_condvar_wait (connection->dispatch_cond, connection->dispatch_mutex);
03194 }
03195
03196 _dbus_assert (!connection->dispatch_acquired);
03197
03198 connection->dispatch_acquired = TRUE;
03199
03200 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03201 _dbus_mutex_unlock (connection->dispatch_mutex);
03202
03203 CONNECTION_LOCK (connection);
03204 _dbus_connection_unref_unlocked (connection);
03205 }
03206
03214 static void
03215 _dbus_connection_release_dispatch (DBusConnection *connection)
03216 {
03217 HAVE_LOCK_CHECK (connection);
03218
03219 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03220 _dbus_mutex_lock (connection->dispatch_mutex);
03221
03222 _dbus_assert (connection->dispatch_acquired);
03223
03224 connection->dispatch_acquired = FALSE;
03225 _dbus_condvar_wake_one (connection->dispatch_cond);
03226
03227 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03228 _dbus_mutex_unlock (connection->dispatch_mutex);
03229 }
03230
03231 static void
03232 _dbus_connection_failed_pop (DBusConnection *connection,
03233 DBusList *message_link)
03234 {
03235 _dbus_list_prepend_link (&connection->incoming_messages,
03236 message_link);
03237 connection->n_incoming += 1;
03238 }
03239
03240 static DBusDispatchStatus
03241 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
03242 {
03243 HAVE_LOCK_CHECK (connection);
03244
03245 if (connection->n_incoming > 0)
03246 return DBUS_DISPATCH_DATA_REMAINS;
03247 else if (!_dbus_transport_queue_messages (connection->transport))
03248 return DBUS_DISPATCH_NEED_MEMORY;
03249 else
03250 {
03251 DBusDispatchStatus status;
03252 dbus_bool_t is_connected;
03253
03254 status = _dbus_transport_get_dispatch_status (connection->transport);
03255 is_connected = _dbus_transport_get_is_connected (connection->transport);
03256
03257 _dbus_verbose ("dispatch status = %s is_connected = %d\n",
03258 DISPATCH_STATUS_NAME (status), is_connected);
03259
03260 if (!is_connected)
03261 {
03262 if (status == DBUS_DISPATCH_COMPLETE &&
03263 connection->disconnect_message_link)
03264 {
03265 _dbus_verbose ("Sending disconnect message from %s\n",
03266 _DBUS_FUNCTION_NAME);
03267
03268 connection_forget_shared_unlocked (connection);
03269
03270
03271
03272
03273 _dbus_connection_queue_synthesized_message_link (connection,
03274 connection->disconnect_message_link);
03275 connection->disconnect_message_link = NULL;
03276 }
03277
03278
03279
03280
03281
03282 if (connection->n_outgoing > 0)
03283 {
03284 DBusList *link;
03285
03286 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
03287 connection->n_outgoing);
03288
03289 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
03290 {
03291 _dbus_connection_message_sent (connection, link->data);
03292 }
03293 }
03294 }
03295
03296 if (status != DBUS_DISPATCH_COMPLETE)
03297 return status;
03298 else if (connection->n_incoming > 0)
03299 return DBUS_DISPATCH_DATA_REMAINS;
03300 else
03301 return DBUS_DISPATCH_COMPLETE;
03302 }
03303 }
03304
03305 static void
03306 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
03307 DBusDispatchStatus new_status)
03308 {
03309 dbus_bool_t changed;
03310 DBusDispatchStatusFunction function;
03311 void *data;
03312
03313 HAVE_LOCK_CHECK (connection);
03314
03315 _dbus_connection_ref_unlocked (connection);
03316
03317 changed = new_status != connection->last_dispatch_status;
03318
03319 connection->last_dispatch_status = new_status;
03320
03321 function = connection->dispatch_status_function;
03322 data = connection->dispatch_status_data;
03323
03324
03325 CONNECTION_UNLOCK (connection);
03326
03327 if (changed && function)
03328 {
03329 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
03330 connection, new_status,
03331 DISPATCH_STATUS_NAME (new_status));
03332 (* function) (connection, new_status, data);
03333 }
03334
03335 dbus_connection_unref (connection);
03336 }
03337
03346 DBusDispatchStatus
03347 dbus_connection_get_dispatch_status (DBusConnection *connection)
03348 {
03349 DBusDispatchStatus status;
03350
03351 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
03352
03353 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03354
03355 CONNECTION_LOCK (connection);
03356
03357 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03358
03359 CONNECTION_UNLOCK (connection);
03360
03361 return status;
03362 }
03363
03367 static DBusHandlerResult
03368 _dbus_connection_peer_filter (DBusConnection *connection,
03369 DBusMessage *message)
03370 {
03371 if (dbus_message_is_method_call (message,
03372 DBUS_INTERFACE_PEER,
03373 "Ping"))
03374 {
03375 DBusMessage *ret;
03376 dbus_bool_t sent;
03377
03378 ret = dbus_message_new_method_return (message);
03379 if (ret == NULL)
03380 return DBUS_HANDLER_RESULT_NEED_MEMORY;
03381
03382 sent = dbus_connection_send (connection, ret, NULL);
03383 dbus_message_unref (ret);
03384
03385 if (!sent)
03386 return DBUS_HANDLER_RESULT_NEED_MEMORY;
03387
03388 return DBUS_HANDLER_RESULT_HANDLED;
03389 }
03390
03391
03392 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03393 }
03394
03401 static DBusHandlerResult
03402 _dbus_connection_run_builtin_filters (DBusConnection *connection,
03403 DBusMessage *message)
03404 {
03405
03406
03407
03408 return _dbus_connection_peer_filter (connection, message);
03409 }
03410
03434 DBusDispatchStatus
03435 dbus_connection_dispatch (DBusConnection *connection)
03436 {
03437 DBusMessage *message;
03438 DBusList *link, *filter_list_copy, *message_link;
03439 DBusHandlerResult result;
03440 DBusPendingCall *pending;
03441 dbus_int32_t reply_serial;
03442 DBusDispatchStatus status;
03443
03444 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
03445
03446 _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
03447
03448 CONNECTION_LOCK (connection);
03449 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03450 if (status != DBUS_DISPATCH_DATA_REMAINS)
03451 {
03452
03453 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03454 return status;
03455 }
03456
03457
03458
03459
03460 _dbus_connection_ref_unlocked (connection);
03461
03462 _dbus_connection_acquire_dispatch (connection);
03463 HAVE_LOCK_CHECK (connection);
03464
03465 message_link = _dbus_connection_pop_message_link_unlocked (connection);
03466 if (message_link == NULL)
03467 {
03468
03469
03470 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
03471
03472 _dbus_connection_release_dispatch (connection);
03473
03474 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03475
03476 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03477
03478 dbus_connection_unref (connection);
03479
03480 return status;
03481 }
03482
03483 message = message_link->data;
03484
03485 _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
03486 message,
03487 dbus_message_get_type (message),
03488 dbus_message_get_interface (message) ?
03489 dbus_message_get_interface (message) :
03490 "no interface",
03491 dbus_message_get_member (message) ?
03492 dbus_message_get_member (message) :
03493 "no member",
03494 dbus_message_get_signature (message));
03495
03496 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03497
03498
03499
03500
03501
03502
03503
03504
03505 reply_serial = dbus_message_get_reply_serial (message);
03506 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
03507 reply_serial);
03508 if (pending)
03509 {
03510 _dbus_verbose ("Dispatching a pending reply\n");
03511 _dbus_pending_call_complete_and_unlock (pending, message);
03512 pending = NULL;
03513
03514 CONNECTION_LOCK (connection);
03515 _dbus_verbose ("pending call completed in dispatch\n");
03516 result = DBUS_HANDLER_RESULT_HANDLED;
03517 goto out;
03518 }
03519
03520 result = _dbus_connection_run_builtin_filters (connection, message);
03521 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03522 goto out;
03523
03524 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
03525 {
03526 _dbus_connection_release_dispatch (connection);
03527 HAVE_LOCK_CHECK (connection);
03528
03529 _dbus_connection_failed_pop (connection, message_link);
03530
03531
03532 _dbus_connection_update_dispatch_status_and_unlock (connection,
03533 DBUS_DISPATCH_NEED_MEMORY);
03534
03535 if (pending)
03536 dbus_pending_call_unref (pending);
03537 dbus_connection_unref (connection);
03538
03539 return DBUS_DISPATCH_NEED_MEMORY;
03540 }
03541
03542 _dbus_list_foreach (&filter_list_copy,
03543 (DBusForeachFunction)_dbus_message_filter_ref,
03544 NULL);
03545
03546
03547
03548
03549 CONNECTION_UNLOCK (connection);
03550
03551 link = _dbus_list_get_first_link (&filter_list_copy);
03552 while (link != NULL)
03553 {
03554 DBusMessageFilter *filter = link->data;
03555 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
03556
03557 _dbus_verbose (" running filter on message %p\n", message);
03558 result = (* filter->function) (connection, message, filter->user_data);
03559
03560 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03561 break;
03562
03563 link = next;
03564 }
03565
03566 _dbus_list_foreach (&filter_list_copy,
03567 (DBusForeachFunction)_dbus_message_filter_unref,
03568 NULL);
03569 _dbus_list_clear (&filter_list_copy);
03570
03571 CONNECTION_LOCK (connection);
03572
03573 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
03574 {
03575 _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
03576 goto out;
03577 }
03578 else if (result == DBUS_HANDLER_RESULT_HANDLED)
03579 {
03580 _dbus_verbose ("filter handled message in dispatch\n");
03581 goto out;
03582 }
03583
03584
03585
03586
03587 _dbus_verbose (" running object path dispatch on message %p (%d %s %s '%s')\n",
03588 message,
03589 dbus_message_get_type (message),
03590 dbus_message_get_interface (message) ?
03591 dbus_message_get_interface (message) :
03592 "no interface",
03593 dbus_message_get_member (message) ?
03594 dbus_message_get_member (message) :
03595 "no member",
03596 dbus_message_get_signature (message));
03597
03598 HAVE_LOCK_CHECK (connection);
03599 result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
03600 message);
03601
03602 CONNECTION_LOCK (connection);
03603
03604 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03605 {
03606 _dbus_verbose ("object tree handled message in dispatch\n");
03607 goto out;
03608 }
03609
03610 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
03611 {
03612 DBusMessage *reply;
03613 DBusString str;
03614 DBusPreallocatedSend *preallocated;
03615
03616 _dbus_verbose (" sending error %s\n",
03617 DBUS_ERROR_UNKNOWN_METHOD);
03618
03619 if (!_dbus_string_init (&str))
03620 {
03621 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03622 _dbus_verbose ("no memory for error string in dispatch\n");
03623 goto out;
03624 }
03625
03626 if (!_dbus_string_append_printf (&str,
03627 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
03628 dbus_message_get_member (message),
03629 dbus_message_get_signature (message),
03630 dbus_message_get_interface (message)))
03631 {
03632 _dbus_string_free (&str);
03633 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03634 _dbus_verbose ("no memory for error string in dispatch\n");
03635 goto out;
03636 }
03637
03638 reply = dbus_message_new_error (message,
03639 DBUS_ERROR_UNKNOWN_METHOD,
03640 _dbus_string_get_const_data (&str));
03641 _dbus_string_free (&str);
03642
03643 if (reply == NULL)
03644 {
03645 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03646 _dbus_verbose ("no memory for error reply in dispatch\n");
03647 goto out;
03648 }
03649
03650 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03651
03652 if (preallocated == NULL)
03653 {
03654 dbus_message_unref (reply);
03655 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03656 _dbus_verbose ("no memory for error send in dispatch\n");
03657 goto out;
03658 }
03659
03660 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
03661 reply, NULL);
03662
03663 dbus_message_unref (reply);
03664
03665 result = DBUS_HANDLER_RESULT_HANDLED;
03666 }
03667
03668 _dbus_verbose (" done dispatching %p (%d %s %s '%s') on connection %p\n", message,
03669 dbus_message_get_type (message),
03670 dbus_message_get_interface (message) ?
03671 dbus_message_get_interface (message) :
03672 "no interface",
03673 dbus_message_get_member (message) ?
03674 dbus_message_get_member (message) :
03675 "no member",
03676 dbus_message_get_signature (message),
03677 connection);
03678
03679 out:
03680 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
03681 {
03682 _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
03683
03684
03685
03686
03687
03688 _dbus_connection_putback_message_link_unlocked (connection,
03689 message_link);
03690 }
03691 else
03692 {
03693 _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
03694
03695 if (connection->exit_on_disconnect &&
03696 dbus_message_is_signal (message,
03697 DBUS_INTERFACE_LOCAL,
03698 "Disconnected"))
03699 {
03700 _dbus_verbose ("Exiting on Disconnected signal\n");
03701 CONNECTION_UNLOCK (connection);
03702 _dbus_exit (1);
03703 _dbus_assert_not_reached ("Call to exit() returned");
03704 }
03705
03706 _dbus_list_free_link (message_link);
03707 dbus_message_unref (message);
03708
03709
03710 }
03711
03712 _dbus_connection_release_dispatch (connection);
03713 HAVE_LOCK_CHECK (connection);
03714
03715 _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
03716 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03717
03718
03719 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03720
03721 dbus_connection_unref (connection);
03722
03723 return status;
03724 }
03725
03784 dbus_bool_t
03785 dbus_connection_set_watch_functions (DBusConnection *connection,
03786 DBusAddWatchFunction add_function,
03787 DBusRemoveWatchFunction remove_function,
03788 DBusWatchToggledFunction toggled_function,
03789 void *data,
03790 DBusFreeFunction free_data_function)
03791 {
03792 dbus_bool_t retval;
03793 DBusWatchList *watches;
03794
03795 _dbus_return_val_if_fail (connection != NULL, FALSE);
03796
03797 CONNECTION_LOCK (connection);
03798
03799 #ifndef DBUS_DISABLE_CHECKS
03800 if (connection->watches == NULL)
03801 {
03802 _dbus_warn ("Re-entrant call to %s is not allowed\n",
03803 _DBUS_FUNCTION_NAME);
03804 return FALSE;
03805 }
03806 #endif
03807
03808
03809 _dbus_connection_ref_unlocked (connection);
03810
03811
03812
03813
03814
03815 watches = connection->watches;
03816 connection->watches = NULL;
03817 CONNECTION_UNLOCK (connection);
03818
03819 retval = _dbus_watch_list_set_functions (watches,
03820 add_function, remove_function,
03821 toggled_function,
03822 data, free_data_function);
03823 CONNECTION_LOCK (connection);
03824 connection->watches = watches;
03825
03826 CONNECTION_UNLOCK (connection);
03827
03828 dbus_connection_unref (connection);
03829
03830 return retval;
03831 }
03832
03866 dbus_bool_t
03867 dbus_connection_set_timeout_functions (DBusConnection *connection,
03868 DBusAddTimeoutFunction add_function,
03869 DBusRemoveTimeoutFunction remove_function,
03870 DBusTimeoutToggledFunction toggled_function,
03871 void *data,
03872 DBusFreeFunction free_data_function)
03873 {
03874 dbus_bool_t retval;
03875 DBusTimeoutList *timeouts;
03876
03877 _dbus_return_val_if_fail (connection != NULL, FALSE);
03878
03879 CONNECTION_LOCK (connection);
03880
03881 #ifndef DBUS_DISABLE_CHECKS
03882 if (connection->timeouts == NULL)
03883 {
03884 _dbus_warn ("Re-entrant call to %s is not allowed\n",
03885 _DBUS_FUNCTION_NAME);
03886 return FALSE;
03887 }
03888 #endif
03889
03890
03891 _dbus_connection_ref_unlocked (connection);
03892
03893 timeouts = connection->timeouts;
03894 connection->timeouts = NULL;
03895 CONNECTION_UNLOCK (connection);
03896
03897 retval = _dbus_timeout_list_set_functions (timeouts,
03898 add_function, remove_function,
03899 toggled_function,
03900 data, free_data_function);
03901 CONNECTION_LOCK (connection);
03902 connection->timeouts = timeouts;
03903
03904 CONNECTION_UNLOCK (connection);
03905
03906 dbus_connection_unref (connection);
03907
03908 return retval;
03909 }
03910
03925 void
03926 dbus_connection_set_wakeup_main_function (DBusConnection *connection,
03927 DBusWakeupMainFunction wakeup_main_function,
03928 void *data,
03929 DBusFreeFunction free_data_function)
03930 {
03931 void *old_data;
03932 DBusFreeFunction old_free_data;
03933
03934 _dbus_return_if_fail (connection != NULL);
03935
03936 CONNECTION_LOCK (connection);
03937 old_data = connection->wakeup_main_data;
03938 old_free_data = connection->free_wakeup_main_data;
03939
03940 connection->wakeup_main_function = wakeup_main_function;
03941 connection->wakeup_main_data = data;
03942 connection->free_wakeup_main_data = free_data_function;
03943
03944 CONNECTION_UNLOCK (connection);
03945
03946
03947 if (old_free_data)
03948 (*old_free_data) (old_data);
03949 }
03950
03967 void
03968 dbus_connection_set_dispatch_status_function (DBusConnection *connection,
03969 DBusDispatchStatusFunction function,
03970 void *data,
03971 DBusFreeFunction free_data_function)
03972 {
03973 void *old_data;
03974 DBusFreeFunction old_free_data;
03975
03976 _dbus_return_if_fail (connection != NULL);
03977
03978 CONNECTION_LOCK (connection);
03979 old_data = connection->dispatch_status_data;
03980 old_free_data = connection->free_dispatch_status_data;
03981
03982 connection->dispatch_status_function = function;
03983 connection->dispatch_status_data = data;
03984 connection->free_dispatch_status_data = free_data_function;
03985
03986 CONNECTION_UNLOCK (connection);
03987
03988
03989 if (old_free_data)
03990 (*old_free_data) (old_data);
03991 }
03992
04005 dbus_bool_t
04006 dbus_connection_get_unix_fd (DBusConnection *connection,
04007 int *fd)
04008 {
04009 dbus_bool_t retval;
04010
04011 _dbus_return_val_if_fail (connection != NULL, FALSE);
04012 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04013
04014 CONNECTION_LOCK (connection);
04015
04016 retval = _dbus_transport_get_unix_fd (connection->transport,
04017 fd);
04018
04019 CONNECTION_UNLOCK (connection);
04020
04021 return retval;
04022 }
04023
04035 dbus_bool_t
04036 dbus_connection_get_unix_user (DBusConnection *connection,
04037 unsigned long *uid)
04038 {
04039 dbus_bool_t result;
04040
04041 _dbus_return_val_if_fail (connection != NULL, FALSE);
04042 _dbus_return_val_if_fail (uid != NULL, FALSE);
04043
04044 CONNECTION_LOCK (connection);
04045
04046 if (!_dbus_transport_get_is_authenticated (connection->transport))
04047 result = FALSE;
04048 else
04049 result = _dbus_transport_get_unix_user (connection->transport,
04050 uid);
04051 CONNECTION_UNLOCK (connection);
04052
04053 return result;
04054 }
04055
04066 dbus_bool_t
04067 dbus_connection_get_unix_process_id (DBusConnection *connection,
04068 unsigned long *pid)
04069 {
04070 dbus_bool_t result;
04071
04072 _dbus_return_val_if_fail (connection != NULL, FALSE);
04073 _dbus_return_val_if_fail (pid != NULL, FALSE);
04074
04075 CONNECTION_LOCK (connection);
04076
04077 if (!_dbus_transport_get_is_authenticated (connection->transport))
04078 result = FALSE;
04079 else
04080 result = _dbus_transport_get_unix_process_id (connection->transport,
04081 pid);
04082 CONNECTION_UNLOCK (connection);
04083
04084 return result;
04085 }
04086
04103 void
04104 dbus_connection_set_unix_user_function (DBusConnection *connection,
04105 DBusAllowUnixUserFunction function,
04106 void *data,
04107 DBusFreeFunction free_data_function)
04108 {
04109 void *old_data = NULL;
04110 DBusFreeFunction old_free_function = NULL;
04111
04112 _dbus_return_if_fail (connection != NULL);
04113
04114 CONNECTION_LOCK (connection);
04115 _dbus_transport_set_unix_user_function (connection->transport,
04116 function, data, free_data_function,
04117 &old_data, &old_free_function);
04118 CONNECTION_UNLOCK (connection);
04119
04120 if (old_free_function != NULL)
04121 (* old_free_function) (old_data);
04122 }
04123
04145 dbus_bool_t
04146 dbus_connection_add_filter (DBusConnection *connection,
04147 DBusHandleMessageFunction function,
04148 void *user_data,
04149 DBusFreeFunction free_data_function)
04150 {
04151 DBusMessageFilter *filter;
04152
04153 _dbus_return_val_if_fail (connection != NULL, FALSE);
04154 _dbus_return_val_if_fail (function != NULL, FALSE);
04155
04156 filter = dbus_new0 (DBusMessageFilter, 1);
04157 if (filter == NULL)
04158 return FALSE;
04159
04160 filter->refcount.value = 1;
04161
04162 CONNECTION_LOCK (connection);
04163
04164 if (!_dbus_list_append (&connection->filter_list,
04165 filter))
04166 {
04167 _dbus_message_filter_unref (filter);
04168 CONNECTION_UNLOCK (connection);
04169 return FALSE;
04170 }
04171
04172
04173
04174
04175
04176
04177 filter->function = function;
04178 filter->user_data = user_data;
04179 filter->free_user_data_function = free_data_function;
04180
04181 CONNECTION_UNLOCK (connection);
04182 return TRUE;
04183 }
04184
04197 void
04198 dbus_connection_remove_filter (DBusConnection *connection,
04199 DBusHandleMessageFunction function,
04200 void *user_data)
04201 {
04202 DBusList *link;
04203 DBusMessageFilter *filter;
04204
04205 _dbus_return_if_fail (connection != NULL);
04206 _dbus_return_if_fail (function != NULL);
04207
04208 CONNECTION_LOCK (connection);
04209
04210 filter = NULL;
04211
04212 link = _dbus_list_get_last_link (&connection->filter_list);
04213 while (link != NULL)
04214 {
04215 filter = link->data;
04216
04217 if (filter->function == function &&
04218 filter->user_data == user_data)
04219 {
04220 _dbus_list_remove_link (&connection->filter_list, link);
04221 filter->function = NULL;
04222
04223 break;
04224 }
04225
04226 link = _dbus_list_get_prev_link (&connection->filter_list, link);
04227 }
04228
04229 CONNECTION_UNLOCK (connection);
04230
04231 #ifndef DBUS_DISABLE_CHECKS
04232 if (filter == NULL)
04233 {
04234 _dbus_warn ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
04235 function, user_data);
04236 return;
04237 }
04238 #endif
04239
04240
04241 if (filter->free_user_data_function)
04242 (* filter->free_user_data_function) (filter->user_data);
04243
04244 filter->free_user_data_function = NULL;
04245 filter->user_data = NULL;
04246
04247 _dbus_message_filter_unref (filter);
04248 }
04249
04261 dbus_bool_t
04262 dbus_connection_register_object_path (DBusConnection *connection,
04263 const char *path,
04264 const DBusObjectPathVTable *vtable,
04265 void *user_data)
04266 {
04267 char **decomposed_path;
04268 dbus_bool_t retval;
04269
04270 _dbus_return_val_if_fail (connection != NULL, FALSE);
04271 _dbus_return_val_if_fail (path != NULL, FALSE);
04272 _dbus_return_val_if_fail (path[0] == '/', FALSE);
04273 _dbus_return_val_if_fail (vtable != NULL, FALSE);
04274
04275 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04276 return FALSE;
04277
04278 CONNECTION_LOCK (connection);
04279
04280 retval = _dbus_object_tree_register (connection->objects,
04281 FALSE,
04282 (const char **) decomposed_path, vtable,
04283 user_data);
04284
04285 CONNECTION_UNLOCK (connection);
04286
04287 dbus_free_string_array (decomposed_path);
04288
04289 return retval;
04290 }
04291
04304 dbus_bool_t
04305 dbus_connection_register_fallback (DBusConnection *connection,
04306 const char *path,
04307 const DBusObjectPathVTable *vtable,
04308 void *user_data)
04309 {
04310 char **decomposed_path;
04311 dbus_bool_t retval;
04312
04313 _dbus_return_val_if_fail (connection != NULL, FALSE);
04314 _dbus_return_val_if_fail (path != NULL, FALSE);
04315 _dbus_return_val_if_fail (path[0] == '/', FALSE);
04316 _dbus_return_val_if_fail (vtable != NULL, FALSE);
04317
04318 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04319 return FALSE;
04320
04321 CONNECTION_LOCK (connection);
04322
04323 retval = _dbus_object_tree_register (connection->objects,
04324 TRUE,
04325 (const char **) decomposed_path, vtable,
04326 user_data);
04327
04328 CONNECTION_UNLOCK (connection);
04329
04330 dbus_free_string_array (decomposed_path);
04331
04332 return retval;
04333 }
04334
04344 dbus_bool_t
04345 dbus_connection_unregister_object_path (DBusConnection *connection,
04346 const char *path)
04347 {
04348 char **decomposed_path;
04349
04350 _dbus_return_val_if_fail (connection != NULL, FALSE);
04351 _dbus_return_val_if_fail (path != NULL, FALSE);
04352 _dbus_return_val_if_fail (path[0] == '/', FALSE);
04353
04354 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04355 return FALSE;
04356
04357 CONNECTION_LOCK (connection);
04358
04359 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
04360
04361 dbus_free_string_array (decomposed_path);
04362
04363 return TRUE;
04364 }
04365
04376 dbus_bool_t
04377 dbus_connection_get_object_path_data (DBusConnection *connection,
04378 const char *path,
04379 void **data_p)
04380 {
04381 char **decomposed_path;
04382
04383 _dbus_return_val_if_fail (connection != NULL, FALSE);
04384 _dbus_return_val_if_fail (path != NULL, FALSE);
04385 _dbus_return_val_if_fail (data_p != NULL, FALSE);
04386
04387 *data_p = NULL;
04388
04389 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04390 return FALSE;
04391
04392 CONNECTION_LOCK (connection);
04393
04394 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
04395
04396 CONNECTION_UNLOCK (connection);
04397
04398 dbus_free_string_array (decomposed_path);
04399
04400 return TRUE;
04401 }
04402
04413 dbus_bool_t
04414 dbus_connection_list_registered (DBusConnection *connection,
04415 const char *parent_path,
04416 char ***child_entries)
04417 {
04418 char **decomposed_path;
04419 dbus_bool_t retval;
04420 _dbus_return_val_if_fail (connection != NULL, FALSE);
04421 _dbus_return_val_if_fail (parent_path != NULL, FALSE);
04422 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
04423 _dbus_return_val_if_fail (child_entries != NULL, FALSE);
04424
04425 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
04426 return FALSE;
04427
04428 CONNECTION_LOCK (connection);
04429
04430 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
04431 (const char **) decomposed_path,
04432 child_entries);
04433 dbus_free_string_array (decomposed_path);
04434
04435 return retval;
04436 }
04437
04438 static DBusDataSlotAllocator slot_allocator;
04439 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
04440
04455 dbus_bool_t
04456 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
04457 {
04458 return _dbus_data_slot_allocator_alloc (&slot_allocator,
04459 _DBUS_LOCK_NAME (connection_slots),
04460 slot_p);
04461 }
04462
04474 void
04475 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
04476 {
04477 _dbus_return_if_fail (*slot_p >= 0);
04478
04479 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
04480 }
04481
04495 dbus_bool_t
04496 dbus_connection_set_data (DBusConnection *connection,
04497 dbus_int32_t slot,
04498 void *data,
04499 DBusFreeFunction free_data_func)
04500 {
04501 DBusFreeFunction old_free_func;
04502 void *old_data;
04503 dbus_bool_t retval;
04504
04505 _dbus_return_val_if_fail (connection != NULL, FALSE);
04506 _dbus_return_val_if_fail (slot >= 0, FALSE);
04507
04508 CONNECTION_LOCK (connection);
04509
04510 retval = _dbus_data_slot_list_set (&slot_allocator,
04511 &connection->slot_list,
04512 slot, data, free_data_func,
04513 &old_free_func, &old_data);
04514
04515 CONNECTION_UNLOCK (connection);
04516
04517 if (retval)
04518 {
04519
04520 if (old_free_func)
04521 (* old_free_func) (old_data);
04522 }
04523
04524 return retval;
04525 }
04526
04535 void*
04536 dbus_connection_get_data (DBusConnection *connection,
04537 dbus_int32_t slot)
04538 {
04539 void *res;
04540
04541 _dbus_return_val_if_fail (connection != NULL, NULL);
04542
04543 CONNECTION_LOCK (connection);
04544
04545 res = _dbus_data_slot_list_get (&slot_allocator,
04546 &connection->slot_list,
04547 slot);
04548
04549 CONNECTION_UNLOCK (connection);
04550
04551 return res;
04552 }
04553
04560 void
04561 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
04562 {
04563 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
04564 }
04565
04574 void
04575 dbus_connection_set_max_message_size (DBusConnection *connection,
04576 long size)
04577 {
04578 _dbus_return_if_fail (connection != NULL);
04579
04580 CONNECTION_LOCK (connection);
04581 _dbus_transport_set_max_message_size (connection->transport,
04582 size);
04583 CONNECTION_UNLOCK (connection);
04584 }
04585
04592 long
04593 dbus_connection_get_max_message_size (DBusConnection *connection)
04594 {
04595 long res;
04596
04597 _dbus_return_val_if_fail (connection != NULL, 0);
04598
04599 CONNECTION_LOCK (connection);
04600 res = _dbus_transport_get_max_message_size (connection->transport);
04601 CONNECTION_UNLOCK (connection);
04602 return res;
04603 }
04604
04630 void
04631 dbus_connection_set_max_received_size (DBusConnection *connection,
04632 long size)
04633 {
04634 _dbus_return_if_fail (connection != NULL);
04635
04636 CONNECTION_LOCK (connection);
04637 _dbus_transport_set_max_received_size (connection->transport,
04638 size);
04639 CONNECTION_UNLOCK (connection);
04640 }
04641
04648 long
04649 dbus_connection_get_max_received_size (DBusConnection *connection)
04650 {
04651 long res;
04652
04653 _dbus_return_val_if_fail (connection != NULL, 0);
04654
04655 CONNECTION_LOCK (connection);
04656 res = _dbus_transport_get_max_received_size (connection->transport);
04657 CONNECTION_UNLOCK (connection);
04658 return res;
04659 }
04660
04671 long
04672 dbus_connection_get_outgoing_size (DBusConnection *connection)
04673 {
04674 long res;
04675
04676 _dbus_return_val_if_fail (connection != NULL, 0);
04677
04678 CONNECTION_LOCK (connection);
04679 res = _dbus_counter_get_value (connection->outgoing_counter);
04680 CONNECTION_UNLOCK (connection);
04681 return res;
04682 }
04683