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_unlocked (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_path (message) :
00396 "no path",
00397 dbus_message_get_interface (message) ?
00398 dbus_message_get_interface (message) :
00399 "no interface",
00400 dbus_message_get_member (message) ?
00401 dbus_message_get_member (message) :
00402 "no member",
00403 dbus_message_get_signature (message),
00404 dbus_message_get_reply_serial (message),
00405 connection,
00406 connection->n_incoming);
00407 }
00408
00419 static void
00420 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00421 DBusList *link)
00422 {
00423 HAVE_LOCK_CHECK (connection);
00424
00425 _dbus_list_append_link (&connection->incoming_messages, link);
00426
00427 connection->n_incoming += 1;
00428
00429 _dbus_connection_wakeup_mainloop (connection);
00430
00431 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00432 link->data, connection, connection->n_incoming);
00433 }
00434
00435
00443 dbus_bool_t
00444 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00445 {
00446 HAVE_LOCK_CHECK (connection);
00447 return connection->outgoing_messages != NULL;
00448 }
00449
00456 dbus_bool_t
00457 dbus_connection_has_messages_to_send (DBusConnection *connection)
00458 {
00459 dbus_bool_t v;
00460
00461 _dbus_return_val_if_fail (connection != NULL, FALSE);
00462
00463 CONNECTION_LOCK (connection);
00464 v = _dbus_connection_has_messages_to_send_unlocked (connection);
00465 CONNECTION_UNLOCK (connection);
00466
00467 return v;
00468 }
00469
00477 DBusMessage*
00478 _dbus_connection_get_message_to_send (DBusConnection *connection)
00479 {
00480 HAVE_LOCK_CHECK (connection);
00481
00482 return _dbus_list_get_last (&connection->outgoing_messages);
00483 }
00484
00493 void
00494 _dbus_connection_message_sent (DBusConnection *connection,
00495 DBusMessage *message)
00496 {
00497 DBusList *link;
00498
00499 HAVE_LOCK_CHECK (connection);
00500
00501
00502
00503
00504
00505
00506 link = _dbus_list_get_last_link (&connection->outgoing_messages);
00507 _dbus_assert (link != NULL);
00508 _dbus_assert (link->data == message);
00509
00510
00511 _dbus_list_unlink (&connection->outgoing_messages,
00512 link);
00513 _dbus_list_prepend_link (&connection->link_cache, link);
00514
00515 connection->n_outgoing -= 1;
00516
00517 _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00518 message,
00519 dbus_message_get_type (message),
00520 dbus_message_get_path (message) ?
00521 dbus_message_get_path (message) :
00522 "no path",
00523 dbus_message_get_interface (message) ?
00524 dbus_message_get_interface (message) :
00525 "no interface",
00526 dbus_message_get_member (message) ?
00527 dbus_message_get_member (message) :
00528 "no member",
00529 dbus_message_get_signature (message),
00530 connection, connection->n_outgoing);
00531
00532
00533 _dbus_message_remove_size_counter (message, connection->outgoing_counter,
00534 &link);
00535 _dbus_list_prepend_link (&connection->link_cache, link);
00536
00537 dbus_message_unref (message);
00538 }
00539
00540 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list,
00541 DBusWatch *watch);
00542 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list,
00543 DBusWatch *watch);
00544 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list,
00545 DBusWatch *watch,
00546 dbus_bool_t enabled);
00547
00548 static dbus_bool_t
00549 protected_change_watch (DBusConnection *connection,
00550 DBusWatch *watch,
00551 DBusWatchAddFunction add_function,
00552 DBusWatchRemoveFunction remove_function,
00553 DBusWatchToggleFunction toggle_function,
00554 dbus_bool_t enabled)
00555 {
00556 DBusWatchList *watches;
00557 dbus_bool_t retval;
00558
00559 HAVE_LOCK_CHECK (connection);
00560
00561
00562
00563
00564
00565 watches = connection->watches;
00566 if (watches)
00567 {
00568 connection->watches = NULL;
00569 _dbus_connection_ref_unlocked (connection);
00570 CONNECTION_UNLOCK (connection);
00571
00572 if (add_function)
00573 retval = (* add_function) (watches, watch);
00574 else if (remove_function)
00575 {
00576 retval = TRUE;
00577 (* remove_function) (watches, watch);
00578 }
00579 else
00580 {
00581 retval = TRUE;
00582 (* toggle_function) (watches, watch, enabled);
00583 }
00584
00585 CONNECTION_LOCK (connection);
00586 connection->watches = watches;
00587 _dbus_connection_unref_unlocked (connection);
00588
00589 return retval;
00590 }
00591 else
00592 return FALSE;
00593 }
00594
00595
00607 dbus_bool_t
00608 _dbus_connection_add_watch_unlocked (DBusConnection *connection,
00609 DBusWatch *watch)
00610 {
00611 return protected_change_watch (connection, watch,
00612 _dbus_watch_list_add_watch,
00613 NULL, NULL, FALSE);
00614 }
00615
00625 void
00626 _dbus_connection_remove_watch_unlocked (DBusConnection *connection,
00627 DBusWatch *watch)
00628 {
00629 protected_change_watch (connection, watch,
00630 NULL,
00631 _dbus_watch_list_remove_watch,
00632 NULL, FALSE);
00633 }
00634
00645 void
00646 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
00647 DBusWatch *watch,
00648 dbus_bool_t enabled)
00649 {
00650 _dbus_assert (watch != NULL);
00651
00652 protected_change_watch (connection, watch,
00653 NULL, NULL,
00654 _dbus_watch_list_toggle_watch,
00655 enabled);
00656 }
00657
00658 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list,
00659 DBusTimeout *timeout);
00660 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00661 DBusTimeout *timeout);
00662 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00663 DBusTimeout *timeout,
00664 dbus_bool_t enabled);
00665
00666 static dbus_bool_t
00667 protected_change_timeout (DBusConnection *connection,
00668 DBusTimeout *timeout,
00669 DBusTimeoutAddFunction add_function,
00670 DBusTimeoutRemoveFunction remove_function,
00671 DBusTimeoutToggleFunction toggle_function,
00672 dbus_bool_t enabled)
00673 {
00674 DBusTimeoutList *timeouts;
00675 dbus_bool_t retval;
00676
00677 HAVE_LOCK_CHECK (connection);
00678
00679
00680
00681
00682
00683 timeouts = connection->timeouts;
00684 if (timeouts)
00685 {
00686 connection->timeouts = NULL;
00687 _dbus_connection_ref_unlocked (connection);
00688 CONNECTION_UNLOCK (connection);
00689
00690 if (add_function)
00691 retval = (* add_function) (timeouts, timeout);
00692 else if (remove_function)
00693 {
00694 retval = TRUE;
00695 (* remove_function) (timeouts, timeout);
00696 }
00697 else
00698 {
00699 retval = TRUE;
00700 (* toggle_function) (timeouts, timeout, enabled);
00701 }
00702
00703 CONNECTION_LOCK (connection);
00704 connection->timeouts = timeouts;
00705 _dbus_connection_unref_unlocked (connection);
00706
00707 return retval;
00708 }
00709 else
00710 return FALSE;
00711 }
00712
00725 dbus_bool_t
00726 _dbus_connection_add_timeout_unlocked (DBusConnection *connection,
00727 DBusTimeout *timeout)
00728 {
00729 return protected_change_timeout (connection, timeout,
00730 _dbus_timeout_list_add_timeout,
00731 NULL, NULL, FALSE);
00732 }
00733
00743 void
00744 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
00745 DBusTimeout *timeout)
00746 {
00747 protected_change_timeout (connection, timeout,
00748 NULL,
00749 _dbus_timeout_list_remove_timeout,
00750 NULL, FALSE);
00751 }
00752
00763 void
00764 _dbus_connection_toggle_timeout_unlocked (DBusConnection *connection,
00765 DBusTimeout *timeout,
00766 dbus_bool_t enabled)
00767 {
00768 protected_change_timeout (connection, timeout,
00769 NULL, NULL,
00770 _dbus_timeout_list_toggle_timeout,
00771 enabled);
00772 }
00773
00774 static dbus_bool_t
00775 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection,
00776 DBusPendingCall *pending)
00777 {
00778 HAVE_LOCK_CHECK (connection);
00779
00780 _dbus_assert (pending->reply_serial != 0);
00781
00782 if (!_dbus_connection_add_timeout_unlocked (connection, pending->timeout))
00783 return FALSE;
00784
00785 if (!_dbus_hash_table_insert_int (connection->pending_replies,
00786 pending->reply_serial,
00787 pending))
00788 {
00789 _dbus_connection_remove_timeout_unlocked (connection, pending->timeout);
00790
00791 HAVE_LOCK_CHECK (connection);
00792 return FALSE;
00793 }
00794
00795 pending->timeout_added = TRUE;
00796 pending->connection = connection;
00797
00798 dbus_pending_call_ref (pending);
00799
00800 HAVE_LOCK_CHECK (connection);
00801
00802 return TRUE;
00803 }
00804
00805 static void
00806 free_pending_call_on_hash_removal (void *data)
00807 {
00808 DBusPendingCall *pending;
00809
00810 if (data == NULL)
00811 return;
00812
00813 pending = data;
00814
00815 if (pending->connection)
00816 {
00817 if (pending->timeout_added)
00818 {
00819 _dbus_connection_remove_timeout_unlocked (pending->connection,
00820 pending->timeout);
00821 pending->timeout_added = FALSE;
00822 }
00823
00824 pending->connection = NULL;
00825
00826 dbus_pending_call_unref (pending);
00827 }
00828 }
00829
00830 static void
00831 _dbus_connection_detach_pending_call_unlocked (DBusConnection *connection,
00832 DBusPendingCall *pending)
00833 {
00834
00835
00836 dbus_pending_call_ref (pending);
00837 _dbus_hash_table_remove_int (connection->pending_replies,
00838 pending->reply_serial);
00839 _dbus_assert (pending->connection == NULL);
00840 dbus_pending_call_unref (pending);
00841 }
00842
00843 static void
00844 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection,
00845 DBusPendingCall *pending)
00846 {
00847
00848
00849
00850
00851 dbus_pending_call_ref (pending);
00852 _dbus_hash_table_remove_int (connection->pending_replies,
00853 pending->reply_serial);
00854 _dbus_assert (pending->connection == NULL);
00855 CONNECTION_UNLOCK (connection);
00856 dbus_pending_call_unref (pending);
00857 }
00858
00867 void
00868 _dbus_connection_remove_pending_call (DBusConnection *connection,
00869 DBusPendingCall *pending)
00870 {
00871 CONNECTION_LOCK (connection);
00872 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
00873 }
00874
00883 void
00884 _dbus_pending_call_complete_and_unlock (DBusPendingCall *pending,
00885 DBusMessage *message)
00886 {
00887 if (message == NULL)
00888 {
00889 message = pending->timeout_link->data;
00890 _dbus_list_clear (&pending->timeout_link);
00891 }
00892 else
00893 dbus_message_ref (message);
00894
00895 _dbus_verbose (" handing message %p (%s) to pending call serial %u\n",
00896 message,
00897 dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN ?
00898 "method return" :
00899 dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ?
00900 "error" : "other type",
00901 pending->reply_serial);
00902
00903 _dbus_assert (pending->reply == NULL);
00904 _dbus_assert (pending->reply_serial == dbus_message_get_reply_serial (message));
00905 pending->reply = message;
00906
00907 dbus_pending_call_ref (pending);
00908 _dbus_connection_detach_pending_call_and_unlock (pending->connection, pending);
00909
00910
00911 _dbus_pending_call_notify (pending);
00912 dbus_pending_call_unref (pending);
00913 }
00914
00924 static dbus_bool_t
00925 _dbus_connection_acquire_io_path (DBusConnection *connection,
00926 int timeout_milliseconds)
00927 {
00928 dbus_bool_t we_acquired;
00929
00930 HAVE_LOCK_CHECK (connection);
00931
00932
00933 _dbus_connection_ref_unlocked (connection);
00934
00935
00936 CONNECTION_UNLOCK (connection);
00937
00938 _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00939 _dbus_mutex_lock (connection->io_path_mutex);
00940
00941 _dbus_verbose ("%s start connection->io_path_acquired = %d timeout = %d\n",
00942 _DBUS_FUNCTION_NAME, connection->io_path_acquired, timeout_milliseconds);
00943
00944 we_acquired = FALSE;
00945
00946 if (connection->io_path_acquired)
00947 {
00948 if (timeout_milliseconds != -1)
00949 {
00950 _dbus_verbose ("%s waiting %d for IO path to be acquirable\n",
00951 _DBUS_FUNCTION_NAME, timeout_milliseconds);
00952 _dbus_condvar_wait_timeout (connection->io_path_cond,
00953 connection->io_path_mutex,
00954 timeout_milliseconds);
00955 }
00956 else
00957 {
00958 while (connection->io_path_acquired)
00959 {
00960 _dbus_verbose ("%s waiting for IO path to be acquirable\n", _DBUS_FUNCTION_NAME);
00961 _dbus_condvar_wait (connection->io_path_cond, connection->io_path_mutex);
00962 }
00963 }
00964 }
00965
00966 if (!connection->io_path_acquired)
00967 {
00968 we_acquired = TRUE;
00969 connection->io_path_acquired = TRUE;
00970 }
00971
00972 _dbus_verbose ("%s end connection->io_path_acquired = %d we_acquired = %d\n",
00973 _DBUS_FUNCTION_NAME, connection->io_path_acquired, we_acquired);
00974
00975 _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00976 _dbus_mutex_unlock (connection->io_path_mutex);
00977
00978 CONNECTION_LOCK (connection);
00979
00980 HAVE_LOCK_CHECK (connection);
00981
00982 _dbus_connection_unref_unlocked (connection);
00983
00984 return we_acquired;
00985 }
00986
00994 static void
00995 _dbus_connection_release_io_path (DBusConnection *connection)
00996 {
00997 HAVE_LOCK_CHECK (connection);
00998
00999 _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01000 _dbus_mutex_lock (connection->io_path_mutex);
01001
01002 _dbus_assert (connection->io_path_acquired);
01003
01004 _dbus_verbose ("%s start connection->io_path_acquired = %d\n",
01005 _DBUS_FUNCTION_NAME, connection->io_path_acquired);
01006
01007 connection->io_path_acquired = FALSE;
01008 _dbus_condvar_wake_one (connection->io_path_cond);
01009
01010 _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01011 _dbus_mutex_unlock (connection->io_path_mutex);
01012 }
01013
01042 void
01043 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01044 unsigned int flags,
01045 int timeout_milliseconds)
01046 {
01047 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01048
01049 HAVE_LOCK_CHECK (connection);
01050
01051 if (connection->n_outgoing == 0)
01052 flags &= ~DBUS_ITERATION_DO_WRITING;
01053
01054 if (_dbus_connection_acquire_io_path (connection,
01055 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01056 {
01057 HAVE_LOCK_CHECK (connection);
01058
01059 _dbus_transport_do_iteration (connection->transport,
01060 flags, timeout_milliseconds);
01061 _dbus_connection_release_io_path (connection);
01062 }
01063
01064 HAVE_LOCK_CHECK (connection);
01065
01066 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01067 }
01068
01078 DBusConnection*
01079 _dbus_connection_new_for_transport (DBusTransport *transport)
01080 {
01081 DBusConnection *connection;
01082 DBusWatchList *watch_list;
01083 DBusTimeoutList *timeout_list;
01084 DBusHashTable *pending_replies;
01085 DBusMutex *mutex;
01086 DBusMutex *io_path_mutex;
01087 DBusMutex *dispatch_mutex;
01088 DBusCondVar *dispatch_cond;
01089 DBusCondVar *io_path_cond;
01090 DBusList *disconnect_link;
01091 DBusMessage *disconnect_message;
01092 DBusCounter *outgoing_counter;
01093 DBusObjectTree *objects;
01094
01095 watch_list = NULL;
01096 connection = NULL;
01097 pending_replies = NULL;
01098 timeout_list = NULL;
01099 mutex = NULL;
01100 io_path_mutex = NULL;
01101 dispatch_mutex = NULL;
01102 dispatch_cond = NULL;
01103 io_path_cond = NULL;
01104 disconnect_link = NULL;
01105 disconnect_message = NULL;
01106 outgoing_counter = NULL;
01107 objects = NULL;
01108
01109 watch_list = _dbus_watch_list_new ();
01110 if (watch_list == NULL)
01111 goto error;
01112
01113 timeout_list = _dbus_timeout_list_new ();
01114 if (timeout_list == NULL)
01115 goto error;
01116
01117 pending_replies =
01118 _dbus_hash_table_new (DBUS_HASH_INT,
01119 NULL,
01120 (DBusFreeFunction)free_pending_call_on_hash_removal);
01121 if (pending_replies == NULL)
01122 goto error;
01123
01124 connection = dbus_new0 (DBusConnection, 1);
01125 if (connection == NULL)
01126 goto error;
01127
01128 mutex = _dbus_mutex_new ();
01129 if (mutex == NULL)
01130 goto error;
01131
01132 io_path_mutex = _dbus_mutex_new ();
01133 if (io_path_mutex == NULL)
01134 goto error;
01135
01136 dispatch_mutex = _dbus_mutex_new ();
01137 if (dispatch_mutex == NULL)
01138 goto error;
01139
01140 dispatch_cond = _dbus_condvar_new ();
01141 if (dispatch_cond == NULL)
01142 goto error;
01143
01144 io_path_cond = _dbus_condvar_new ();
01145 if (io_path_cond == NULL)
01146 goto error;
01147
01148 disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01149 DBUS_INTERFACE_LOCAL,
01150 "Disconnected");
01151
01152 if (disconnect_message == NULL)
01153 goto error;
01154
01155 disconnect_link = _dbus_list_alloc_link (disconnect_message);
01156 if (disconnect_link == NULL)
01157 goto error;
01158
01159 outgoing_counter = _dbus_counter_new ();
01160 if (outgoing_counter == NULL)
01161 goto error;
01162
01163 objects = _dbus_object_tree_new (connection);
01164 if (objects == NULL)
01165 goto error;
01166
01167 if (_dbus_modify_sigpipe)
01168 _dbus_disable_sigpipe ();
01169
01170 connection->refcount.value = 1;
01171 connection->mutex = mutex;
01172 connection->dispatch_cond = dispatch_cond;
01173 connection->dispatch_mutex = dispatch_mutex;
01174 connection->io_path_cond = io_path_cond;
01175 connection->io_path_mutex = io_path_mutex;
01176 connection->transport = transport;
01177 connection->watches = watch_list;
01178 connection->timeouts = timeout_list;
01179 connection->pending_replies = pending_replies;
01180 connection->outgoing_counter = outgoing_counter;
01181 connection->filter_list = NULL;
01182 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE;
01183 connection->objects = objects;
01184 connection->exit_on_disconnect = FALSE;
01185 connection->shareable = FALSE;
01186 #ifndef DBUS_DISABLE_CHECKS
01187 connection->generation = _dbus_current_generation;
01188 #endif
01189
01190 _dbus_data_slot_list_init (&connection->slot_list);
01191
01192 connection->client_serial = 1;
01193
01194 connection->disconnect_message_link = disconnect_link;
01195
01196 CONNECTION_LOCK (connection);
01197
01198 if (!_dbus_transport_set_connection (transport, connection))
01199 goto error;
01200
01201 _dbus_transport_ref (transport);
01202
01203 CONNECTION_UNLOCK (connection);
01204
01205 return connection;
01206
01207 error:
01208 if (disconnect_message != NULL)
01209 dbus_message_unref (disconnect_message);
01210
01211 if (disconnect_link != NULL)
01212 _dbus_list_free_link (disconnect_link);
01213
01214 if (io_path_cond != NULL)
01215 _dbus_condvar_free (io_path_cond);
01216
01217 if (dispatch_cond != NULL)
01218 _dbus_condvar_free (dispatch_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_path (message) :
02172 "no path",
02173 dbus_message_get_interface (message) ?
02174 dbus_message_get_interface (message) :
02175 "no interface",
02176 dbus_message_get_member (message) ?
02177 dbus_message_get_member (message) :
02178 "no member",
02179 sig,
02180 dbus_message_get_destination (message) ?
02181 dbus_message_get_destination (message) :
02182 "null",
02183 connection,
02184 connection->n_outgoing);
02185
02186 if (dbus_message_get_serial (message) == 0)
02187 {
02188 serial = _dbus_connection_get_next_client_serial (connection);
02189 _dbus_message_set_serial (message, serial);
02190 if (client_serial)
02191 *client_serial = serial;
02192 }
02193 else
02194 {
02195 if (client_serial)
02196 *client_serial = dbus_message_get_serial (message);
02197 }
02198
02199 _dbus_verbose ("Message %p serial is %u\n",
02200 message, dbus_message_get_serial (message));
02201
02202 _dbus_message_lock (message);
02203
02204
02205
02206
02207 _dbus_connection_do_iteration_unlocked (connection,
02208 DBUS_ITERATION_DO_WRITING,
02209 -1);
02210
02211
02212 if (connection->n_outgoing > 0)
02213 _dbus_connection_wakeup_mainloop (connection);
02214 }
02215
02216 static void
02217 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection,
02218 DBusPreallocatedSend *preallocated,
02219 DBusMessage *message,
02220 dbus_uint32_t *client_serial)
02221 {
02222 DBusDispatchStatus status;
02223
02224 HAVE_LOCK_CHECK (connection);
02225
02226 _dbus_connection_send_preallocated_unlocked_no_update (connection,
02227 preallocated,
02228 message, client_serial);
02229
02230 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02231 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02232
02233
02234 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02235 }
02236
02249 void
02250 dbus_connection_send_preallocated (DBusConnection *connection,
02251 DBusPreallocatedSend *preallocated,
02252 DBusMessage *message,
02253 dbus_uint32_t *client_serial)
02254 {
02255 _dbus_return_if_fail (connection != NULL);
02256 _dbus_return_if_fail (preallocated != NULL);
02257 _dbus_return_if_fail (message != NULL);
02258 _dbus_return_if_fail (preallocated->connection == connection);
02259 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
02260 dbus_message_get_member (message) != NULL);
02261 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
02262 (dbus_message_get_interface (message) != NULL &&
02263 dbus_message_get_member (message) != NULL));
02264
02265 CONNECTION_LOCK (connection);
02266 _dbus_connection_send_preallocated_and_unlock (connection,
02267 preallocated,
02268 message, client_serial);
02269 }
02270
02271 static dbus_bool_t
02272 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
02273 DBusMessage *message,
02274 dbus_uint32_t *client_serial)
02275 {
02276 DBusPreallocatedSend *preallocated;
02277
02278 _dbus_assert (connection != NULL);
02279 _dbus_assert (message != NULL);
02280
02281 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02282 if (preallocated == NULL)
02283 return FALSE;
02284
02285 _dbus_connection_send_preallocated_unlocked_no_update (connection,
02286 preallocated,
02287 message,
02288 client_serial);
02289 return TRUE;
02290 }
02291
02292 dbus_bool_t
02293 _dbus_connection_send_and_unlock (DBusConnection *connection,
02294 DBusMessage *message,
02295 dbus_uint32_t *client_serial)
02296 {
02297 DBusPreallocatedSend *preallocated;
02298
02299 _dbus_assert (connection != NULL);
02300 _dbus_assert (message != NULL);
02301
02302 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02303 if (preallocated == NULL)
02304 {
02305 CONNECTION_UNLOCK (connection);
02306 return FALSE;
02307 }
02308
02309 _dbus_connection_send_preallocated_and_unlock (connection,
02310 preallocated,
02311 message,
02312 client_serial);
02313 return TRUE;
02314 }
02315
02334 dbus_bool_t
02335 dbus_connection_send (DBusConnection *connection,
02336 DBusMessage *message,
02337 dbus_uint32_t *client_serial)
02338 {
02339 _dbus_return_val_if_fail (connection != NULL, FALSE);
02340 _dbus_return_val_if_fail (message != NULL, FALSE);
02341
02342 CONNECTION_LOCK (connection);
02343
02344 return _dbus_connection_send_and_unlock (connection,
02345 message,
02346 client_serial);
02347 }
02348
02349 static dbus_bool_t
02350 reply_handler_timeout (void *data)
02351 {
02352 DBusConnection *connection;
02353 DBusDispatchStatus status;
02354 DBusPendingCall *pending = data;
02355
02356 connection = pending->connection;
02357
02358 CONNECTION_LOCK (connection);
02359 if (pending->timeout_link)
02360 {
02361 _dbus_connection_queue_synthesized_message_link (connection,
02362 pending->timeout_link);
02363 pending->timeout_link = NULL;
02364 }
02365
02366 _dbus_connection_remove_timeout_unlocked (connection,
02367 pending->timeout);
02368 pending->timeout_added = FALSE;
02369
02370 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02371 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02372
02373
02374 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02375
02376 return TRUE;
02377 }
02378
02416 dbus_bool_t
02417 dbus_connection_send_with_reply (DBusConnection *connection,
02418 DBusMessage *message,
02419 DBusPendingCall **pending_return,
02420 int timeout_milliseconds)
02421 {
02422 DBusPendingCall *pending;
02423 DBusMessage *reply;
02424 DBusList *reply_link;
02425 dbus_int32_t serial = -1;
02426 DBusDispatchStatus status;
02427
02428 _dbus_return_val_if_fail (connection != NULL, FALSE);
02429 _dbus_return_val_if_fail (message != NULL, FALSE);
02430 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02431
02432 if (pending_return)
02433 *pending_return = NULL;
02434
02435 pending = _dbus_pending_call_new (connection,
02436 timeout_milliseconds,
02437 reply_handler_timeout);
02438
02439 if (pending == NULL)
02440 return FALSE;
02441
02442 CONNECTION_LOCK (connection);
02443
02444
02445 if (dbus_message_get_serial (message) == 0)
02446 {
02447 serial = _dbus_connection_get_next_client_serial (connection);
02448 _dbus_message_set_serial (message, serial);
02449 }
02450
02451 pending->reply_serial = serial;
02452
02453 reply = dbus_message_new_error (message, DBUS_ERROR_NO_REPLY,
02454 "No reply within specified time");
02455 if (reply == NULL)
02456 goto error;
02457
02458 reply_link = _dbus_list_alloc_link (reply);
02459 if (reply_link == NULL)
02460 {
02461 CONNECTION_UNLOCK (connection);
02462 dbus_message_unref (reply);
02463 goto error_unlocked;
02464 }
02465
02466 pending->timeout_link = reply_link;
02467
02468
02469
02470
02471
02472 if (!_dbus_connection_attach_pending_call_unlocked (connection,
02473 pending))
02474 goto error;
02475
02476 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
02477 {
02478 _dbus_connection_detach_pending_call_and_unlock (connection,
02479 pending);
02480 goto error_unlocked;
02481 }
02482
02483 if (pending_return)
02484 *pending_return = pending;
02485 else
02486 {
02487 _dbus_connection_detach_pending_call_unlocked (connection, pending);
02488 dbus_pending_call_unref (pending);
02489 }
02490
02491 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02492 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02493
02494
02495 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02496
02497 return TRUE;
02498
02499 error:
02500 CONNECTION_UNLOCK (connection);
02501 error_unlocked:
02502 dbus_pending_call_unref (pending);
02503 return FALSE;
02504 }
02505
02506
02507
02508
02509 static DBusMessage*
02510 check_for_reply_unlocked (DBusConnection *connection,
02511 dbus_uint32_t client_serial)
02512 {
02513 DBusList *link;
02514
02515 HAVE_LOCK_CHECK (connection);
02516
02517 link = _dbus_list_get_first_link (&connection->incoming_messages);
02518
02519 while (link != NULL)
02520 {
02521 DBusMessage *reply = link->data;
02522
02523 if (dbus_message_get_reply_serial (reply) == client_serial)
02524 {
02525 _dbus_list_remove_link (&connection->incoming_messages, link);
02526 connection->n_incoming -= 1;
02527 return reply;
02528 }
02529 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02530 }
02531
02532 return NULL;
02533 }
02534
02544 static void
02545 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02546 {
02547 if (timeout_milliseconds == -1)
02548 _dbus_sleep_milliseconds (1000);
02549 else if (timeout_milliseconds < 100)
02550 ;
02551 else if (timeout_milliseconds <= 1000)
02552 _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02553 else
02554 _dbus_sleep_milliseconds (1000);
02555 }
02556
02571 void
02572 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02573 {
02574 long start_tv_sec, start_tv_usec;
02575 long end_tv_sec, end_tv_usec;
02576 long tv_sec, tv_usec;
02577 DBusDispatchStatus status;
02578 DBusConnection *connection;
02579 dbus_uint32_t client_serial;
02580 int timeout_milliseconds;
02581
02582 _dbus_assert (pending != NULL);
02583
02584 if (dbus_pending_call_get_completed (pending))
02585 return;
02586
02587 if (pending->connection == NULL)
02588 return;
02589
02590 dbus_pending_call_ref (pending);
02591
02592 connection = pending->connection;
02593 client_serial = pending->reply_serial;
02594
02595
02596
02597
02598
02599 timeout_milliseconds = dbus_timeout_get_interval (pending->timeout);
02600
02601
02602 dbus_connection_flush (connection);
02603
02604 CONNECTION_LOCK (connection);
02605
02606 _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02607 end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
02608 end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
02609 end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
02610 end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
02611
02612 _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",
02613 timeout_milliseconds,
02614 client_serial,
02615 start_tv_sec, start_tv_usec,
02616 end_tv_sec, end_tv_usec);
02617
02618
02619
02620 _dbus_connection_do_iteration_unlocked (connection,
02621 DBUS_ITERATION_DO_READING |
02622 DBUS_ITERATION_BLOCK,
02623 timeout_milliseconds);
02624
02625 recheck_status:
02626
02627 _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME);
02628
02629 HAVE_LOCK_CHECK (connection);
02630
02631
02632
02633 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02634
02635
02636
02637
02638 if (dbus_pending_call_get_completed (pending))
02639 {
02640 _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME);
02641 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02642 dbus_pending_call_unref (pending);
02643 return;
02644 }
02645
02646 if (status == DBUS_DISPATCH_DATA_REMAINS)
02647 {
02648 DBusMessage *reply;
02649
02650 reply = check_for_reply_unlocked (connection, client_serial);
02651 if (reply != NULL)
02652 {
02653 _dbus_verbose ("%s checked for reply\n", _DBUS_FUNCTION_NAME);
02654
02655 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02656
02657 _dbus_pending_call_complete_and_unlock (pending, reply);
02658 dbus_message_unref (reply);
02659
02660 CONNECTION_LOCK (connection);
02661 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02662 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02663 dbus_pending_call_unref (pending);
02664
02665 return;
02666 }
02667 }
02668
02669 _dbus_get_current_time (&tv_sec, &tv_usec);
02670
02671 if (!_dbus_connection_get_is_connected_unlocked (connection))
02672 {
02673
02674
02675
02676
02677
02678 _dbus_pending_call_complete_and_unlock (pending, NULL);
02679 dbus_pending_call_unref (pending);
02680 return;
02681 }
02682 else if (tv_sec < start_tv_sec)
02683 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02684 else if (connection->disconnect_message_link == NULL)
02685 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02686 else if (tv_sec < end_tv_sec ||
02687 (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
02688 {
02689 timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
02690 (end_tv_usec - tv_usec) / 1000;
02691 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
02692 _dbus_assert (timeout_milliseconds >= 0);
02693
02694 if (status == DBUS_DISPATCH_NEED_MEMORY)
02695 {
02696
02697
02698
02699
02700 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02701
02702 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02703 }
02704 else
02705 {
02706
02707 _dbus_connection_do_iteration_unlocked (connection,
02708 DBUS_ITERATION_DO_READING |
02709 DBUS_ITERATION_BLOCK,
02710 timeout_milliseconds);
02711 }
02712
02713 goto recheck_status;
02714 }
02715
02716 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
02717 (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
02718
02719 _dbus_assert (!dbus_pending_call_get_completed (pending));
02720
02721
02722 _dbus_pending_call_complete_and_unlock (pending, NULL);
02723
02724
02725 CONNECTION_LOCK (connection);
02726 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02727 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02728 dbus_pending_call_unref (pending);
02729 }
02730
02753 DBusMessage*
02754 dbus_connection_send_with_reply_and_block (DBusConnection *connection,
02755 DBusMessage *message,
02756 int timeout_milliseconds,
02757 DBusError *error)
02758 {
02759 DBusMessage *reply;
02760 DBusPendingCall *pending;
02761
02762 _dbus_return_val_if_fail (connection != NULL, NULL);
02763 _dbus_return_val_if_fail (message != NULL, NULL);
02764 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
02765 _dbus_return_val_if_error_is_set (error, NULL);
02766
02767 if (!dbus_connection_send_with_reply (connection, message,
02768 &pending, timeout_milliseconds))
02769 {
02770 _DBUS_SET_OOM (error);
02771 return NULL;
02772 }
02773
02774 _dbus_assert (pending != NULL);
02775
02776 dbus_pending_call_block (pending);
02777
02778 reply = dbus_pending_call_steal_reply (pending);
02779 dbus_pending_call_unref (pending);
02780
02781
02782
02783
02784 _dbus_assert (reply != NULL);
02785
02786 if (dbus_set_error_from_message (error, reply))
02787 {
02788 dbus_message_unref (reply);
02789 return NULL;
02790 }
02791 else
02792 return reply;
02793 }
02794
02800 void
02801 dbus_connection_flush (DBusConnection *connection)
02802 {
02803
02804
02805
02806
02807
02808 DBusDispatchStatus status;
02809
02810 _dbus_return_if_fail (connection != NULL);
02811
02812 CONNECTION_LOCK (connection);
02813 while (connection->n_outgoing > 0 &&
02814 _dbus_connection_get_is_connected_unlocked (connection))
02815 {
02816 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
02817 HAVE_LOCK_CHECK (connection);
02818 _dbus_connection_do_iteration_unlocked (connection,
02819 DBUS_ITERATION_DO_READING |
02820 DBUS_ITERATION_DO_WRITING |
02821 DBUS_ITERATION_BLOCK,
02822 -1);
02823 }
02824
02825 HAVE_LOCK_CHECK (connection);
02826 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02827 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02828
02829 HAVE_LOCK_CHECK (connection);
02830
02831 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02832
02833 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
02834 }
02835
02868 dbus_bool_t
02869 _dbus_connection_read_write_dispatch (DBusConnection *connection,
02870 int timeout_milliseconds,
02871 dbus_bool_t dispatch)
02872 {
02873 DBusDispatchStatus dstatus;
02874 dbus_bool_t dispatched_disconnected;
02875
02876 _dbus_return_val_if_fail (connection != NULL, FALSE);
02877 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02878 dstatus = dbus_connection_get_dispatch_status (connection);
02879
02880 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
02881 {
02882 _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME);
02883 dbus_connection_dispatch (connection);
02884 CONNECTION_LOCK (connection);
02885 }
02886 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
02887 {
02888 _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME);
02889 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02890 CONNECTION_LOCK (connection);
02891 }
02892 else
02893 {
02894 CONNECTION_LOCK (connection);
02895 if (_dbus_connection_get_is_connected_unlocked (connection))
02896 {
02897 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
02898 _dbus_connection_do_iteration_unlocked (connection,
02899 DBUS_ITERATION_DO_READING |
02900 DBUS_ITERATION_DO_WRITING |
02901 DBUS_ITERATION_BLOCK,
02902 timeout_milliseconds);
02903 }
02904 }
02905
02906 HAVE_LOCK_CHECK (connection);
02907 dispatched_disconnected = connection->n_incoming == 0 &&
02908 connection->disconnect_message_link == NULL;
02909 CONNECTION_UNLOCK (connection);
02910 return !dispatched_disconnected;
02911 }
02912
02913
02945 dbus_bool_t
02946 dbus_connection_read_write_dispatch (DBusConnection *connection,
02947 int timeout_milliseconds)
02948 {
02949 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
02950 }
02951
02968 dbus_bool_t
02969 dbus_connection_read_write (DBusConnection *connection,
02970 int timeout_milliseconds)
02971 {
02972 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
02973 }
02974
02994 DBusMessage*
02995 dbus_connection_borrow_message (DBusConnection *connection)
02996 {
02997 DBusDispatchStatus status;
02998 DBusMessage *message;
02999
03000 _dbus_return_val_if_fail (connection != NULL, NULL);
03001
03002 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03003
03004
03005
03006
03007 status = dbus_connection_get_dispatch_status (connection);
03008 if (status != DBUS_DISPATCH_DATA_REMAINS)
03009 return NULL;
03010
03011 CONNECTION_LOCK (connection);
03012
03013 _dbus_connection_acquire_dispatch (connection);
03014
03015
03016 _dbus_assert (connection->message_borrowed == NULL);
03017
03018 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03019
03020 message = connection->message_borrowed;
03021
03022
03023 if (message == NULL)
03024 _dbus_connection_release_dispatch (connection);
03025
03026 CONNECTION_UNLOCK (connection);
03027
03028 return message;
03029 }
03030
03039 void
03040 dbus_connection_return_message (DBusConnection *connection,
03041 DBusMessage *message)
03042 {
03043 _dbus_return_if_fail (connection != NULL);
03044 _dbus_return_if_fail (message != NULL);
03045 _dbus_return_if_fail (message == connection->message_borrowed);
03046 _dbus_return_if_fail (connection->dispatch_acquired);
03047
03048 CONNECTION_LOCK (connection);
03049
03050 _dbus_assert (message == connection->message_borrowed);
03051
03052 connection->message_borrowed = NULL;
03053
03054 _dbus_connection_release_dispatch (connection);
03055
03056 CONNECTION_UNLOCK (connection);
03057 }
03058
03068 void
03069 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03070 DBusMessage *message)
03071 {
03072 DBusMessage *pop_message;
03073
03074 _dbus_return_if_fail (connection != NULL);
03075 _dbus_return_if_fail (message != NULL);
03076 _dbus_return_if_fail (message == connection->message_borrowed);
03077 _dbus_return_if_fail (connection->dispatch_acquired);
03078
03079 CONNECTION_LOCK (connection);
03080
03081 _dbus_assert (message == connection->message_borrowed);
03082
03083 pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03084 _dbus_assert (message == pop_message);
03085
03086 connection->n_incoming -= 1;
03087
03088 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03089 message, connection->n_incoming);
03090
03091 connection->message_borrowed = NULL;
03092
03093 _dbus_connection_release_dispatch (connection);
03094
03095 CONNECTION_UNLOCK (connection);
03096 }
03097
03098
03099
03100
03101 static DBusList*
03102 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03103 {
03104 HAVE_LOCK_CHECK (connection);
03105
03106 _dbus_assert (connection->message_borrowed == NULL);
03107
03108 if (connection->n_incoming > 0)
03109 {
03110 DBusList *link;
03111
03112 link = _dbus_list_pop_first_link (&connection->incoming_messages);
03113 connection->n_incoming -= 1;
03114
03115 _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03116 link->data,
03117 dbus_message_get_type (link->data),
03118 dbus_message_get_path (link->data) ?
03119 dbus_message_get_path (link->data) :
03120 "no path",
03121 dbus_message_get_interface (link->data) ?
03122 dbus_message_get_interface (link->data) :
03123 "no interface",
03124 dbus_message_get_member (link->data) ?
03125 dbus_message_get_member (link->data) :
03126 "no member",
03127 dbus_message_get_signature (link->data),
03128 connection, connection->n_incoming);
03129
03130 return link;
03131 }
03132 else
03133 return NULL;
03134 }
03135
03136
03137
03138
03139 static DBusMessage*
03140 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03141 {
03142 DBusList *link;
03143
03144 HAVE_LOCK_CHECK (connection);
03145
03146 link = _dbus_connection_pop_message_link_unlocked (connection);
03147
03148 if (link != NULL)
03149 {
03150 DBusMessage *message;
03151
03152 message = link->data;
03153
03154 _dbus_list_free_link (link);
03155
03156 return message;
03157 }
03158 else
03159 return NULL;
03160 }
03161
03162 static void
03163 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03164 DBusList *message_link)
03165 {
03166 HAVE_LOCK_CHECK (connection);
03167
03168 _dbus_assert (message_link != NULL);
03169
03170 _dbus_assert (connection->message_borrowed == NULL);
03171
03172 _dbus_assert (connection->dispatch_acquired);
03173
03174 _dbus_list_prepend_link (&connection->incoming_messages,
03175 message_link);
03176 connection->n_incoming += 1;
03177
03178 _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
03179 message_link->data,
03180 dbus_message_get_type (message_link->data),
03181 dbus_message_get_interface (message_link->data) ?
03182 dbus_message_get_interface (message_link->data) :
03183 "no interface",
03184 dbus_message_get_member (message_link->data) ?
03185 dbus_message_get_member (message_link->data) :
03186 "no member",
03187 dbus_message_get_signature (message_link->data),
03188 connection, connection->n_incoming);
03189 }
03190
03210 DBusMessage*
03211 dbus_connection_pop_message (DBusConnection *connection)
03212 {
03213 DBusMessage *message;
03214 DBusDispatchStatus status;
03215
03216 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03217
03218
03219
03220
03221 status = dbus_connection_get_dispatch_status (connection);
03222 if (status != DBUS_DISPATCH_DATA_REMAINS)
03223 return NULL;
03224
03225 CONNECTION_LOCK (connection);
03226 _dbus_connection_acquire_dispatch (connection);
03227 HAVE_LOCK_CHECK (connection);
03228
03229 message = _dbus_connection_pop_message_unlocked (connection);
03230
03231 _dbus_verbose ("Returning popped message %p\n", message);
03232
03233 _dbus_connection_release_dispatch (connection);
03234 CONNECTION_UNLOCK (connection);
03235
03236 return message;
03237 }
03238
03246 static void
03247 _dbus_connection_acquire_dispatch (DBusConnection *connection)
03248 {
03249 HAVE_LOCK_CHECK (connection);
03250
03251 _dbus_connection_ref_unlocked (connection);
03252 CONNECTION_UNLOCK (connection);
03253
03254 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03255 _dbus_mutex_lock (connection->dispatch_mutex);
03256
03257 while (connection->dispatch_acquired)
03258 {
03259 _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
03260 _dbus_condvar_wait (connection->dispatch_cond, connection->dispatch_mutex);
03261 }
03262
03263 _dbus_assert (!connection->dispatch_acquired);
03264
03265 connection->dispatch_acquired = TRUE;
03266
03267 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03268 _dbus_mutex_unlock (connection->dispatch_mutex);
03269
03270 CONNECTION_LOCK (connection);
03271 _dbus_connection_unref_unlocked (connection);
03272 }
03273
03281 static void
03282 _dbus_connection_release_dispatch (DBusConnection *connection)
03283 {
03284 HAVE_LOCK_CHECK (connection);
03285
03286 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03287 _dbus_mutex_lock (connection->dispatch_mutex);
03288
03289 _dbus_assert (connection->dispatch_acquired);
03290
03291 connection->dispatch_acquired = FALSE;
03292 _dbus_condvar_wake_one (connection->dispatch_cond);
03293
03294 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03295 _dbus_mutex_unlock (connection->dispatch_mutex);
03296 }
03297
03298 static void
03299 _dbus_connection_failed_pop (DBusConnection *connection,
03300 DBusList *message_link)
03301 {
03302 _dbus_list_prepend_link (&connection->incoming_messages,
03303 message_link);
03304 connection->n_incoming += 1;
03305 }
03306
03307 static DBusDispatchStatus
03308 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
03309 {
03310 HAVE_LOCK_CHECK (connection);
03311
03312 if (connection->n_incoming > 0)
03313 return DBUS_DISPATCH_DATA_REMAINS;
03314 else if (!_dbus_transport_queue_messages (connection->transport))
03315 return DBUS_DISPATCH_NEED_MEMORY;
03316 else
03317 {
03318 DBusDispatchStatus status;
03319 dbus_bool_t is_connected;
03320
03321 status = _dbus_transport_get_dispatch_status (connection->transport);
03322 is_connected = _dbus_transport_get_is_connected (connection->transport);
03323
03324 _dbus_verbose ("dispatch status = %s is_connected = %d\n",
03325 DISPATCH_STATUS_NAME (status), is_connected);
03326
03327 if (!is_connected)
03328 {
03329 if (status == DBUS_DISPATCH_COMPLETE &&
03330 connection->disconnect_message_link)
03331 {
03332 _dbus_verbose ("Sending disconnect message from %s\n",
03333 _DBUS_FUNCTION_NAME);
03334
03335 connection_forget_shared_unlocked (connection);
03336
03337
03338
03339
03340 _dbus_connection_queue_synthesized_message_link (connection,
03341 connection->disconnect_message_link);
03342 connection->disconnect_message_link = NULL;
03343
03344 status = DBUS_DISPATCH_DATA_REMAINS;
03345 }
03346
03347
03348
03349
03350
03351 if (connection->n_outgoing > 0)
03352 {
03353 DBusList *link;
03354
03355 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
03356 connection->n_outgoing);
03357
03358 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
03359 {
03360 _dbus_connection_message_sent (connection, link->data);
03361 }
03362 }
03363 }
03364
03365 if (status != DBUS_DISPATCH_COMPLETE)
03366 return status;
03367 else if (connection->n_incoming > 0)
03368 return DBUS_DISPATCH_DATA_REMAINS;
03369 else
03370 return DBUS_DISPATCH_COMPLETE;
03371 }
03372 }
03373
03374 static void
03375 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
03376 DBusDispatchStatus new_status)
03377 {
03378 dbus_bool_t changed;
03379 DBusDispatchStatusFunction function;
03380 void *data;
03381
03382 HAVE_LOCK_CHECK (connection);
03383
03384 _dbus_connection_ref_unlocked (connection);
03385
03386 changed = new_status != connection->last_dispatch_status;
03387
03388 connection->last_dispatch_status = new_status;
03389
03390 function = connection->dispatch_status_function;
03391 data = connection->dispatch_status_data;
03392
03393
03394 CONNECTION_UNLOCK (connection);
03395
03396 if (changed && function)
03397 {
03398 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
03399 connection, new_status,
03400 DISPATCH_STATUS_NAME (new_status));
03401 (* function) (connection, new_status, data);
03402 }
03403
03404 dbus_connection_unref (connection);
03405 }
03406
03415 DBusDispatchStatus
03416 dbus_connection_get_dispatch_status (DBusConnection *connection)
03417 {
03418 DBusDispatchStatus status;
03419
03420 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
03421
03422 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03423
03424 CONNECTION_LOCK (connection);
03425
03426 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03427
03428 CONNECTION_UNLOCK (connection);
03429
03430 return status;
03431 }
03432
03436 static DBusHandlerResult
03437 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
03438 DBusMessage *message)
03439 {
03440 if (dbus_message_is_method_call (message,
03441 DBUS_INTERFACE_PEER,
03442 "Ping"))
03443 {
03444 DBusMessage *ret;
03445 dbus_bool_t sent;
03446
03447 ret = dbus_message_new_method_return (message);
03448 if (ret == NULL)
03449 return DBUS_HANDLER_RESULT_NEED_MEMORY;
03450
03451 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
03452
03453 dbus_message_unref (ret);
03454
03455 if (!sent)
03456 return DBUS_HANDLER_RESULT_NEED_MEMORY;
03457
03458 return DBUS_HANDLER_RESULT_HANDLED;
03459 }
03460
03461
03462 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03463 }
03464
03471 static DBusHandlerResult
03472 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
03473 DBusMessage *message)
03474 {
03475
03476
03477
03478 return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
03479 }
03480
03504 DBusDispatchStatus
03505 dbus_connection_dispatch (DBusConnection *connection)
03506 {
03507 DBusMessage *message;
03508 DBusList *link, *filter_list_copy, *message_link;
03509 DBusHandlerResult result;
03510 DBusPendingCall *pending;
03511 dbus_int32_t reply_serial;
03512 DBusDispatchStatus status;
03513
03514 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
03515
03516 _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
03517
03518 CONNECTION_LOCK (connection);
03519 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03520 if (status != DBUS_DISPATCH_DATA_REMAINS)
03521 {
03522
03523 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03524 return status;
03525 }
03526
03527
03528
03529
03530 _dbus_connection_ref_unlocked (connection);
03531
03532 _dbus_connection_acquire_dispatch (connection);
03533 HAVE_LOCK_CHECK (connection);
03534
03535 message_link = _dbus_connection_pop_message_link_unlocked (connection);
03536 if (message_link == NULL)
03537 {
03538
03539
03540 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
03541
03542 _dbus_connection_release_dispatch (connection);
03543
03544 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03545
03546 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03547
03548 dbus_connection_unref (connection);
03549
03550 return status;
03551 }
03552
03553 message = message_link->data;
03554
03555 _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
03556 message,
03557 dbus_message_get_type (message),
03558 dbus_message_get_interface (message) ?
03559 dbus_message_get_interface (message) :
03560 "no interface",
03561 dbus_message_get_member (message) ?
03562 dbus_message_get_member (message) :
03563 "no member",
03564 dbus_message_get_signature (message));
03565
03566 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03567
03568
03569
03570
03571
03572
03573
03574
03575 reply_serial = dbus_message_get_reply_serial (message);
03576 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
03577 reply_serial);
03578 if (pending)
03579 {
03580 _dbus_verbose ("Dispatching a pending reply\n");
03581 _dbus_pending_call_complete_and_unlock (pending, message);
03582 pending = NULL;
03583
03584 CONNECTION_LOCK (connection);
03585 _dbus_verbose ("pending call completed in dispatch\n");
03586 result = DBUS_HANDLER_RESULT_HANDLED;
03587 goto out;
03588 }
03589
03590 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
03591 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03592 goto out;
03593
03594 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
03595 {
03596 _dbus_connection_release_dispatch (connection);
03597 HAVE_LOCK_CHECK (connection);
03598
03599 _dbus_connection_failed_pop (connection, message_link);
03600
03601
03602 _dbus_connection_update_dispatch_status_and_unlock (connection,
03603 DBUS_DISPATCH_NEED_MEMORY);
03604
03605 if (pending)
03606 dbus_pending_call_unref (pending);
03607 dbus_connection_unref (connection);
03608
03609 return DBUS_DISPATCH_NEED_MEMORY;
03610 }
03611
03612 _dbus_list_foreach (&filter_list_copy,
03613 (DBusForeachFunction)_dbus_message_filter_ref,
03614 NULL);
03615
03616
03617
03618
03619 CONNECTION_UNLOCK (connection);
03620
03621 link = _dbus_list_get_first_link (&filter_list_copy);
03622 while (link != NULL)
03623 {
03624 DBusMessageFilter *filter = link->data;
03625 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
03626
03627 _dbus_verbose (" running filter on message %p\n", message);
03628 result = (* filter->function) (connection, message, filter->user_data);
03629
03630 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03631 break;
03632
03633 link = next;
03634 }
03635
03636 _dbus_list_foreach (&filter_list_copy,
03637 (DBusForeachFunction)_dbus_message_filter_unref,
03638 NULL);
03639 _dbus_list_clear (&filter_list_copy);
03640
03641 CONNECTION_LOCK (connection);
03642
03643 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
03644 {
03645 _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
03646 goto out;
03647 }
03648 else if (result == DBUS_HANDLER_RESULT_HANDLED)
03649 {
03650 _dbus_verbose ("filter handled message in dispatch\n");
03651 goto out;
03652 }
03653
03654
03655
03656
03657 _dbus_verbose (" running object path dispatch on message %p (%d %s %s '%s')\n",
03658 message,
03659 dbus_message_get_type (message),
03660 dbus_message_get_interface (message) ?
03661 dbus_message_get_interface (message) :
03662 "no interface",
03663 dbus_message_get_member (message) ?
03664 dbus_message_get_member (message) :
03665 "no member",
03666 dbus_message_get_signature (message));
03667
03668 HAVE_LOCK_CHECK (connection);
03669 result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
03670 message);
03671
03672 CONNECTION_LOCK (connection);
03673
03674 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03675 {
03676 _dbus_verbose ("object tree handled message in dispatch\n");
03677 goto out;
03678 }
03679
03680 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
03681 {
03682 DBusMessage *reply;
03683 DBusString str;
03684 DBusPreallocatedSend *preallocated;
03685
03686 _dbus_verbose (" sending error %s\n",
03687 DBUS_ERROR_UNKNOWN_METHOD);
03688
03689 if (!_dbus_string_init (&str))
03690 {
03691 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03692 _dbus_verbose ("no memory for error string in dispatch\n");
03693 goto out;
03694 }
03695
03696 if (!_dbus_string_append_printf (&str,
03697 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
03698 dbus_message_get_member (message),
03699 dbus_message_get_signature (message),
03700 dbus_message_get_interface (message)))
03701 {
03702 _dbus_string_free (&str);
03703 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03704 _dbus_verbose ("no memory for error string in dispatch\n");
03705 goto out;
03706 }
03707
03708 reply = dbus_message_new_error (message,
03709 DBUS_ERROR_UNKNOWN_METHOD,
03710 _dbus_string_get_const_data (&str));
03711 _dbus_string_free (&str);
03712
03713 if (reply == NULL)
03714 {
03715 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03716 _dbus_verbose ("no memory for error reply in dispatch\n");
03717 goto out;
03718 }
03719
03720 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03721
03722 if (preallocated == NULL)
03723 {
03724 dbus_message_unref (reply);
03725 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03726 _dbus_verbose ("no memory for error send in dispatch\n");
03727 goto out;
03728 }
03729
03730 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
03731 reply, NULL);
03732
03733 dbus_message_unref (reply);
03734
03735 result = DBUS_HANDLER_RESULT_HANDLED;
03736 }
03737
03738 _dbus_verbose (" done dispatching %p (%d %s %s '%s') on connection %p\n", message,
03739 dbus_message_get_type (message),
03740 dbus_message_get_interface (message) ?
03741 dbus_message_get_interface (message) :
03742 "no interface",
03743 dbus_message_get_member (message) ?
03744 dbus_message_get_member (message) :
03745 "no member",
03746 dbus_message_get_signature (message),
03747 connection);
03748
03749 out:
03750 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
03751 {
03752 _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
03753
03754
03755
03756
03757
03758 _dbus_connection_putback_message_link_unlocked (connection,
03759 message_link);
03760 }
03761 else
03762 {
03763 _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
03764
03765 if (connection->exit_on_disconnect &&
03766 dbus_message_is_signal (message,
03767 DBUS_INTERFACE_LOCAL,
03768 "Disconnected"))
03769 {
03770 _dbus_verbose ("Exiting on Disconnected signal\n");
03771 CONNECTION_UNLOCK (connection);
03772 _dbus_exit (1);
03773 _dbus_assert_not_reached ("Call to exit() returned");
03774 }
03775
03776 _dbus_list_free_link (message_link);
03777 dbus_message_unref (message);
03778
03779
03780 }
03781
03782 _dbus_connection_release_dispatch (connection);
03783 HAVE_LOCK_CHECK (connection);
03784
03785 _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
03786 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03787
03788
03789 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03790
03791 dbus_connection_unref (connection);
03792
03793 return status;
03794 }
03795
03854 dbus_bool_t
03855 dbus_connection_set_watch_functions (DBusConnection *connection,
03856 DBusAddWatchFunction add_function,
03857 DBusRemoveWatchFunction remove_function,
03858 DBusWatchToggledFunction toggled_function,
03859 void *data,
03860 DBusFreeFunction free_data_function)
03861 {
03862 dbus_bool_t retval;
03863 DBusWatchList *watches;
03864
03865 _dbus_return_val_if_fail (connection != NULL, FALSE);
03866
03867 CONNECTION_LOCK (connection);
03868
03869 #ifndef DBUS_DISABLE_CHECKS
03870 if (connection->watches == NULL)
03871 {
03872 _dbus_warn ("Re-entrant call to %s is not allowed\n",
03873 _DBUS_FUNCTION_NAME);
03874 return FALSE;
03875 }
03876 #endif
03877
03878
03879 _dbus_connection_ref_unlocked (connection);
03880
03881
03882
03883
03884
03885 watches = connection->watches;
03886 connection->watches = NULL;
03887 CONNECTION_UNLOCK (connection);
03888
03889 retval = _dbus_watch_list_set_functions (watches,
03890 add_function, remove_function,
03891 toggled_function,
03892 data, free_data_function);
03893 CONNECTION_LOCK (connection);
03894 connection->watches = watches;
03895
03896 CONNECTION_UNLOCK (connection);
03897
03898 dbus_connection_unref (connection);
03899
03900 return retval;
03901 }
03902
03936 dbus_bool_t
03937 dbus_connection_set_timeout_functions (DBusConnection *connection,
03938 DBusAddTimeoutFunction add_function,
03939 DBusRemoveTimeoutFunction remove_function,
03940 DBusTimeoutToggledFunction toggled_function,
03941 void *data,
03942 DBusFreeFunction free_data_function)
03943 {
03944 dbus_bool_t retval;
03945 DBusTimeoutList *timeouts;
03946
03947 _dbus_return_val_if_fail (connection != NULL, FALSE);
03948
03949 CONNECTION_LOCK (connection);
03950
03951 #ifndef DBUS_DISABLE_CHECKS
03952 if (connection->timeouts == NULL)
03953 {
03954 _dbus_warn ("Re-entrant call to %s is not allowed\n",
03955 _DBUS_FUNCTION_NAME);
03956 return FALSE;
03957 }
03958 #endif
03959
03960
03961 _dbus_connection_ref_unlocked (connection);
03962
03963 timeouts = connection->timeouts;
03964 connection->timeouts = NULL;
03965 CONNECTION_UNLOCK (connection);
03966
03967 retval = _dbus_timeout_list_set_functions (timeouts,
03968 add_function, remove_function,
03969 toggled_function,
03970 data, free_data_function);
03971 CONNECTION_LOCK (connection);
03972 connection->timeouts = timeouts;
03973
03974 CONNECTION_UNLOCK (connection);
03975
03976 dbus_connection_unref (connection);
03977
03978 return retval;
03979 }
03980
03995 void
03996 dbus_connection_set_wakeup_main_function (DBusConnection *connection,
03997 DBusWakeupMainFunction wakeup_main_function,
03998 void *data,
03999 DBusFreeFunction free_data_function)
04000 {
04001 void *old_data;
04002 DBusFreeFunction old_free_data;
04003
04004 _dbus_return_if_fail (connection != NULL);
04005
04006 CONNECTION_LOCK (connection);
04007 old_data = connection->wakeup_main_data;
04008 old_free_data = connection->free_wakeup_main_data;
04009
04010 connection->wakeup_main_function = wakeup_main_function;
04011 connection->wakeup_main_data = data;
04012 connection->free_wakeup_main_data = free_data_function;
04013
04014 CONNECTION_UNLOCK (connection);
04015
04016
04017 if (old_free_data)
04018 (*old_free_data) (old_data);
04019 }
04020
04037 void
04038 dbus_connection_set_dispatch_status_function (DBusConnection *connection,
04039 DBusDispatchStatusFunction function,
04040 void *data,
04041 DBusFreeFunction free_data_function)
04042 {
04043 void *old_data;
04044 DBusFreeFunction old_free_data;
04045
04046 _dbus_return_if_fail (connection != NULL);
04047
04048 CONNECTION_LOCK (connection);
04049 old_data = connection->dispatch_status_data;
04050 old_free_data = connection->free_dispatch_status_data;
04051
04052 connection->dispatch_status_function = function;
04053 connection->dispatch_status_data = data;
04054 connection->free_dispatch_status_data = free_data_function;
04055
04056 CONNECTION_UNLOCK (connection);
04057
04058
04059 if (old_free_data)
04060 (*old_free_data) (old_data);
04061 }
04062
04075 dbus_bool_t
04076 dbus_connection_get_unix_fd (DBusConnection *connection,
04077 int *fd)
04078 {
04079 dbus_bool_t retval;
04080
04081 _dbus_return_val_if_fail (connection != NULL, FALSE);
04082 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04083
04084 CONNECTION_LOCK (connection);
04085
04086 retval = _dbus_transport_get_unix_fd (connection->transport,
04087 fd);
04088
04089 CONNECTION_UNLOCK (connection);
04090
04091 return retval;
04092 }
04093
04105 dbus_bool_t
04106 dbus_connection_get_unix_user (DBusConnection *connection,
04107 unsigned long *uid)
04108 {
04109 dbus_bool_t result;
04110
04111 _dbus_return_val_if_fail (connection != NULL, FALSE);
04112 _dbus_return_val_if_fail (uid != NULL, FALSE);
04113
04114 CONNECTION_LOCK (connection);
04115
04116 if (!_dbus_transport_get_is_authenticated (connection->transport))
04117 result = FALSE;
04118 else
04119 result = _dbus_transport_get_unix_user (connection->transport,
04120 uid);
04121 CONNECTION_UNLOCK (connection);
04122
04123 return result;
04124 }
04125
04136 dbus_bool_t
04137 dbus_connection_get_unix_process_id (DBusConnection *connection,
04138 unsigned long *pid)
04139 {
04140 dbus_bool_t result;
04141
04142 _dbus_return_val_if_fail (connection != NULL, FALSE);
04143 _dbus_return_val_if_fail (pid != NULL, FALSE);
04144
04145 CONNECTION_LOCK (connection);
04146
04147 if (!_dbus_transport_get_is_authenticated (connection->transport))
04148 result = FALSE;
04149 else
04150 result = _dbus_transport_get_unix_process_id (connection->transport,
04151 pid);
04152 CONNECTION_UNLOCK (connection);
04153
04154 return result;
04155 }
04156
04173 void
04174 dbus_connection_set_unix_user_function (DBusConnection *connection,
04175 DBusAllowUnixUserFunction function,
04176 void *data,
04177 DBusFreeFunction free_data_function)
04178 {
04179 void *old_data = NULL;
04180 DBusFreeFunction old_free_function = NULL;
04181
04182 _dbus_return_if_fail (connection != NULL);
04183
04184 CONNECTION_LOCK (connection);
04185 _dbus_transport_set_unix_user_function (connection->transport,
04186 function, data, free_data_function,
04187 &old_data, &old_free_function);
04188 CONNECTION_UNLOCK (connection);
04189
04190 if (old_free_function != NULL)
04191 (* old_free_function) (old_data);
04192 }
04193
04215 dbus_bool_t
04216 dbus_connection_add_filter (DBusConnection *connection,
04217 DBusHandleMessageFunction function,
04218 void *user_data,
04219 DBusFreeFunction free_data_function)
04220 {
04221 DBusMessageFilter *filter;
04222
04223 _dbus_return_val_if_fail (connection != NULL, FALSE);
04224 _dbus_return_val_if_fail (function != NULL, FALSE);
04225
04226 filter = dbus_new0 (DBusMessageFilter, 1);
04227 if (filter == NULL)
04228 return FALSE;
04229
04230 filter->refcount.value = 1;
04231
04232 CONNECTION_LOCK (connection);
04233
04234 if (!_dbus_list_append (&connection->filter_list,
04235 filter))
04236 {
04237 _dbus_message_filter_unref (filter);
04238 CONNECTION_UNLOCK (connection);
04239 return FALSE;
04240 }
04241
04242
04243
04244
04245
04246
04247 filter->function = function;
04248 filter->user_data = user_data;
04249 filter->free_user_data_function = free_data_function;
04250
04251 CONNECTION_UNLOCK (connection);
04252 return TRUE;
04253 }
04254
04267 void
04268 dbus_connection_remove_filter (DBusConnection *connection,
04269 DBusHandleMessageFunction function,
04270 void *user_data)
04271 {
04272 DBusList *link;
04273 DBusMessageFilter *filter;
04274
04275 _dbus_return_if_fail (connection != NULL);
04276 _dbus_return_if_fail (function != NULL);
04277
04278 CONNECTION_LOCK (connection);
04279
04280 filter = NULL;
04281
04282 link = _dbus_list_get_last_link (&connection->filter_list);
04283 while (link != NULL)
04284 {
04285 filter = link->data;
04286
04287 if (filter->function == function &&
04288 filter->user_data == user_data)
04289 {
04290 _dbus_list_remove_link (&connection->filter_list, link);
04291 filter->function = NULL;
04292
04293 break;
04294 }
04295
04296 link = _dbus_list_get_prev_link (&connection->filter_list, link);
04297 }
04298
04299 CONNECTION_UNLOCK (connection);
04300
04301 #ifndef DBUS_DISABLE_CHECKS
04302 if (filter == NULL)
04303 {
04304 _dbus_warn ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
04305 function, user_data);
04306 return;
04307 }
04308 #endif
04309
04310
04311 if (filter->free_user_data_function)
04312 (* filter->free_user_data_function) (filter->user_data);
04313
04314 filter->free_user_data_function = NULL;
04315 filter->user_data = NULL;
04316
04317 _dbus_message_filter_unref (filter);
04318 }
04319
04331 dbus_bool_t
04332 dbus_connection_register_object_path (DBusConnection *connection,
04333 const char *path,
04334 const DBusObjectPathVTable *vtable,
04335 void *user_data)
04336 {
04337 char **decomposed_path;
04338 dbus_bool_t retval;
04339
04340 _dbus_return_val_if_fail (connection != NULL, FALSE);
04341 _dbus_return_val_if_fail (path != NULL, FALSE);
04342 _dbus_return_val_if_fail (path[0] == '/', FALSE);
04343 _dbus_return_val_if_fail (vtable != NULL, FALSE);
04344
04345 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04346 return FALSE;
04347
04348 CONNECTION_LOCK (connection);
04349
04350 retval = _dbus_object_tree_register (connection->objects,
04351 FALSE,
04352 (const char **) decomposed_path, vtable,
04353 user_data);
04354
04355 CONNECTION_UNLOCK (connection);
04356
04357 dbus_free_string_array (decomposed_path);
04358
04359 return retval;
04360 }
04361
04374 dbus_bool_t
04375 dbus_connection_register_fallback (DBusConnection *connection,
04376 const char *path,
04377 const DBusObjectPathVTable *vtable,
04378 void *user_data)
04379 {
04380 char **decomposed_path;
04381 dbus_bool_t retval;
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 (path[0] == '/', FALSE);
04386 _dbus_return_val_if_fail (vtable != NULL, FALSE);
04387
04388 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04389 return FALSE;
04390
04391 CONNECTION_LOCK (connection);
04392
04393 retval = _dbus_object_tree_register (connection->objects,
04394 TRUE,
04395 (const char **) decomposed_path, vtable,
04396 user_data);
04397
04398 CONNECTION_UNLOCK (connection);
04399
04400 dbus_free_string_array (decomposed_path);
04401
04402 return retval;
04403 }
04404
04414 dbus_bool_t
04415 dbus_connection_unregister_object_path (DBusConnection *connection,
04416 const char *path)
04417 {
04418 char **decomposed_path;
04419
04420 _dbus_return_val_if_fail (connection != NULL, FALSE);
04421 _dbus_return_val_if_fail (path != NULL, FALSE);
04422 _dbus_return_val_if_fail (path[0] == '/', FALSE);
04423
04424 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04425 return FALSE;
04426
04427 CONNECTION_LOCK (connection);
04428
04429 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
04430
04431 dbus_free_string_array (decomposed_path);
04432
04433 return TRUE;
04434 }
04435
04446 dbus_bool_t
04447 dbus_connection_get_object_path_data (DBusConnection *connection,
04448 const char *path,
04449 void **data_p)
04450 {
04451 char **decomposed_path;
04452
04453 _dbus_return_val_if_fail (connection != NULL, FALSE);
04454 _dbus_return_val_if_fail (path != NULL, FALSE);
04455 _dbus_return_val_if_fail (data_p != NULL, FALSE);
04456
04457 *data_p = NULL;
04458
04459 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04460 return FALSE;
04461
04462 CONNECTION_LOCK (connection);
04463
04464 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
04465
04466 CONNECTION_UNLOCK (connection);
04467
04468 dbus_free_string_array (decomposed_path);
04469
04470 return TRUE;
04471 }
04472
04483 dbus_bool_t
04484 dbus_connection_list_registered (DBusConnection *connection,
04485 const char *parent_path,
04486 char ***child_entries)
04487 {
04488 char **decomposed_path;
04489 dbus_bool_t retval;
04490 _dbus_return_val_if_fail (connection != NULL, FALSE);
04491 _dbus_return_val_if_fail (parent_path != NULL, FALSE);
04492 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
04493 _dbus_return_val_if_fail (child_entries != NULL, FALSE);
04494
04495 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
04496 return FALSE;
04497
04498 CONNECTION_LOCK (connection);
04499
04500 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
04501 (const char **) decomposed_path,
04502 child_entries);
04503 dbus_free_string_array (decomposed_path);
04504
04505 return retval;
04506 }
04507
04508 static DBusDataSlotAllocator slot_allocator;
04509 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
04510
04525 dbus_bool_t
04526 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
04527 {
04528 return _dbus_data_slot_allocator_alloc (&slot_allocator,
04529 _DBUS_LOCK_NAME (connection_slots),
04530 slot_p);
04531 }
04532
04544 void
04545 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
04546 {
04547 _dbus_return_if_fail (*slot_p >= 0);
04548
04549 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
04550 }
04551
04565 dbus_bool_t
04566 dbus_connection_set_data (DBusConnection *connection,
04567 dbus_int32_t slot,
04568 void *data,
04569 DBusFreeFunction free_data_func)
04570 {
04571 DBusFreeFunction old_free_func;
04572 void *old_data;
04573 dbus_bool_t retval;
04574
04575 _dbus_return_val_if_fail (connection != NULL, FALSE);
04576 _dbus_return_val_if_fail (slot >= 0, FALSE);
04577
04578 CONNECTION_LOCK (connection);
04579
04580 retval = _dbus_data_slot_list_set (&slot_allocator,
04581 &connection->slot_list,
04582 slot, data, free_data_func,
04583 &old_free_func, &old_data);
04584
04585 CONNECTION_UNLOCK (connection);
04586
04587 if (retval)
04588 {
04589
04590 if (old_free_func)
04591 (* old_free_func) (old_data);
04592 }
04593
04594 return retval;
04595 }
04596
04605 void*
04606 dbus_connection_get_data (DBusConnection *connection,
04607 dbus_int32_t slot)
04608 {
04609 void *res;
04610
04611 _dbus_return_val_if_fail (connection != NULL, NULL);
04612
04613 CONNECTION_LOCK (connection);
04614
04615 res = _dbus_data_slot_list_get (&slot_allocator,
04616 &connection->slot_list,
04617 slot);
04618
04619 CONNECTION_UNLOCK (connection);
04620
04621 return res;
04622 }
04623
04630 void
04631 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
04632 {
04633 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
04634 }
04635
04644 void
04645 dbus_connection_set_max_message_size (DBusConnection *connection,
04646 long size)
04647 {
04648 _dbus_return_if_fail (connection != NULL);
04649
04650 CONNECTION_LOCK (connection);
04651 _dbus_transport_set_max_message_size (connection->transport,
04652 size);
04653 CONNECTION_UNLOCK (connection);
04654 }
04655
04662 long
04663 dbus_connection_get_max_message_size (DBusConnection *connection)
04664 {
04665 long res;
04666
04667 _dbus_return_val_if_fail (connection != NULL, 0);
04668
04669 CONNECTION_LOCK (connection);
04670 res = _dbus_transport_get_max_message_size (connection->transport);
04671 CONNECTION_UNLOCK (connection);
04672 return res;
04673 }
04674
04700 void
04701 dbus_connection_set_max_received_size (DBusConnection *connection,
04702 long size)
04703 {
04704 _dbus_return_if_fail (connection != NULL);
04705
04706 CONNECTION_LOCK (connection);
04707 _dbus_transport_set_max_received_size (connection->transport,
04708 size);
04709 CONNECTION_UNLOCK (connection);
04710 }
04711
04718 long
04719 dbus_connection_get_max_received_size (DBusConnection *connection)
04720 {
04721 long res;
04722
04723 _dbus_return_val_if_fail (connection != NULL, 0);
04724
04725 CONNECTION_LOCK (connection);
04726 res = _dbus_transport_get_max_received_size (connection->transport);
04727 CONNECTION_UNLOCK (connection);
04728 return res;
04729 }
04730
04741 long
04742 dbus_connection_get_outgoing_size (DBusConnection *connection)
04743 {
04744 long res;
04745
04746 _dbus_return_val_if_fail (connection != NULL, 0);
04747
04748 CONNECTION_LOCK (connection);
04749 res = _dbus_counter_get_value (connection->outgoing_counter);
04750 CONNECTION_UNLOCK (connection);
04751 return res;
04752 }
04753