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_interface (message) != NULL &&
02261 dbus_message_get_member (message) != NULL));
02262 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
02263 (dbus_message_get_interface (message) != NULL &&
02264 dbus_message_get_member (message) != NULL));
02265
02266 CONNECTION_LOCK (connection);
02267 _dbus_connection_send_preallocated_and_unlock (connection,
02268 preallocated,
02269 message, client_serial);
02270 }
02271
02272 static dbus_bool_t
02273 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
02274 DBusMessage *message,
02275 dbus_uint32_t *client_serial)
02276 {
02277 DBusPreallocatedSend *preallocated;
02278
02279 _dbus_assert (connection != NULL);
02280 _dbus_assert (message != NULL);
02281
02282 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02283 if (preallocated == NULL)
02284 return FALSE;
02285
02286 _dbus_connection_send_preallocated_unlocked_no_update (connection,
02287 preallocated,
02288 message,
02289 client_serial);
02290 return TRUE;
02291 }
02292
02293 dbus_bool_t
02294 _dbus_connection_send_and_unlock (DBusConnection *connection,
02295 DBusMessage *message,
02296 dbus_uint32_t *client_serial)
02297 {
02298 DBusPreallocatedSend *preallocated;
02299
02300 _dbus_assert (connection != NULL);
02301 _dbus_assert (message != NULL);
02302
02303 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02304 if (preallocated == NULL)
02305 {
02306 CONNECTION_UNLOCK (connection);
02307 return FALSE;
02308 }
02309
02310 _dbus_connection_send_preallocated_and_unlock (connection,
02311 preallocated,
02312 message,
02313 client_serial);
02314 return TRUE;
02315 }
02316
02335 dbus_bool_t
02336 dbus_connection_send (DBusConnection *connection,
02337 DBusMessage *message,
02338 dbus_uint32_t *client_serial)
02339 {
02340 _dbus_return_val_if_fail (connection != NULL, FALSE);
02341 _dbus_return_val_if_fail (message != NULL, FALSE);
02342
02343 CONNECTION_LOCK (connection);
02344
02345 return _dbus_connection_send_and_unlock (connection,
02346 message,
02347 client_serial);
02348 }
02349
02350 static dbus_bool_t
02351 reply_handler_timeout (void *data)
02352 {
02353 DBusConnection *connection;
02354 DBusDispatchStatus status;
02355 DBusPendingCall *pending = data;
02356
02357 connection = pending->connection;
02358
02359 CONNECTION_LOCK (connection);
02360 if (pending->timeout_link)
02361 {
02362 _dbus_connection_queue_synthesized_message_link (connection,
02363 pending->timeout_link);
02364 pending->timeout_link = NULL;
02365 }
02366
02367 _dbus_connection_remove_timeout_unlocked (connection,
02368 pending->timeout);
02369 pending->timeout_added = FALSE;
02370
02371 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02372 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02373
02374
02375 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02376
02377 return TRUE;
02378 }
02379
02417 dbus_bool_t
02418 dbus_connection_send_with_reply (DBusConnection *connection,
02419 DBusMessage *message,
02420 DBusPendingCall **pending_return,
02421 int timeout_milliseconds)
02422 {
02423 DBusPendingCall *pending;
02424 DBusMessage *reply;
02425 DBusList *reply_link;
02426 dbus_int32_t serial = -1;
02427 DBusDispatchStatus status;
02428
02429 _dbus_return_val_if_fail (connection != NULL, FALSE);
02430 _dbus_return_val_if_fail (message != NULL, FALSE);
02431 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02432
02433 if (pending_return)
02434 *pending_return = NULL;
02435
02436 pending = _dbus_pending_call_new (connection,
02437 timeout_milliseconds,
02438 reply_handler_timeout);
02439
02440 if (pending == NULL)
02441 return FALSE;
02442
02443 CONNECTION_LOCK (connection);
02444
02445
02446 if (dbus_message_get_serial (message) == 0)
02447 {
02448 serial = _dbus_connection_get_next_client_serial (connection);
02449 _dbus_message_set_serial (message, serial);
02450 }
02451
02452 pending->reply_serial = serial;
02453
02454 reply = dbus_message_new_error (message, DBUS_ERROR_NO_REPLY,
02455 "No reply within specified time");
02456 if (reply == NULL)
02457 goto error;
02458
02459 reply_link = _dbus_list_alloc_link (reply);
02460 if (reply_link == NULL)
02461 {
02462 CONNECTION_UNLOCK (connection);
02463 dbus_message_unref (reply);
02464 goto error_unlocked;
02465 }
02466
02467 pending->timeout_link = reply_link;
02468
02469
02470
02471
02472
02473 if (!_dbus_connection_attach_pending_call_unlocked (connection,
02474 pending))
02475 goto error;
02476
02477 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
02478 {
02479 _dbus_connection_detach_pending_call_and_unlock (connection,
02480 pending);
02481 goto error_unlocked;
02482 }
02483
02484 if (pending_return)
02485 *pending_return = pending;
02486 else
02487 {
02488 _dbus_connection_detach_pending_call_unlocked (connection, pending);
02489 dbus_pending_call_unref (pending);
02490 }
02491
02492 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02493 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02494
02495
02496 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02497
02498 return TRUE;
02499
02500 error:
02501 CONNECTION_UNLOCK (connection);
02502 error_unlocked:
02503 dbus_pending_call_unref (pending);
02504 return FALSE;
02505 }
02506
02507
02508
02509
02510 static DBusMessage*
02511 check_for_reply_unlocked (DBusConnection *connection,
02512 dbus_uint32_t client_serial)
02513 {
02514 DBusList *link;
02515
02516 HAVE_LOCK_CHECK (connection);
02517
02518 link = _dbus_list_get_first_link (&connection->incoming_messages);
02519
02520 while (link != NULL)
02521 {
02522 DBusMessage *reply = link->data;
02523
02524 if (dbus_message_get_reply_serial (reply) == client_serial)
02525 {
02526 _dbus_list_remove_link (&connection->incoming_messages, link);
02527 connection->n_incoming -= 1;
02528 return reply;
02529 }
02530 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02531 }
02532
02533 return NULL;
02534 }
02535
02536 static dbus_bool_t
02537 check_for_reply_and_update_dispatch_unlocked (DBusPendingCall *pending)
02538 {
02539 DBusMessage *reply;
02540 DBusDispatchStatus status;
02541 DBusConnection *connection;
02542
02543 connection = pending->connection;
02544
02545 reply = check_for_reply_unlocked (connection, pending->reply_serial);
02546 if (reply != NULL)
02547 {
02548 _dbus_verbose ("%s checked for reply\n", _DBUS_FUNCTION_NAME);
02549
02550 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02551
02552 _dbus_pending_call_complete_and_unlock (pending, reply);
02553 dbus_message_unref (reply);
02554
02555 CONNECTION_LOCK (connection);
02556 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02557 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02558 dbus_pending_call_unref (pending);
02559
02560 return TRUE;
02561 }
02562
02563 return FALSE;
02564 }
02565
02575 static void
02576 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02577 {
02578 if (timeout_milliseconds == -1)
02579 _dbus_sleep_milliseconds (1000);
02580 else if (timeout_milliseconds < 100)
02581 ;
02582 else if (timeout_milliseconds <= 1000)
02583 _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02584 else
02585 _dbus_sleep_milliseconds (1000);
02586 }
02587
02602 void
02603 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02604 {
02605 long start_tv_sec, start_tv_usec;
02606 long end_tv_sec, end_tv_usec;
02607 long tv_sec, tv_usec;
02608 DBusDispatchStatus status;
02609 DBusConnection *connection;
02610 dbus_uint32_t client_serial;
02611 int timeout_milliseconds;
02612
02613 _dbus_assert (pending != NULL);
02614
02615 if (dbus_pending_call_get_completed (pending))
02616 return;
02617
02618 if (pending->connection == NULL)
02619 return;
02620
02621 dbus_pending_call_ref (pending);
02622
02623 connection = pending->connection;
02624 client_serial = pending->reply_serial;
02625
02626
02627
02628
02629
02630 timeout_milliseconds = dbus_timeout_get_interval (pending->timeout);
02631
02632
02633 dbus_connection_flush (connection);
02634
02635 CONNECTION_LOCK (connection);
02636
02637 _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02638 end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
02639 end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
02640 end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
02641 end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
02642
02643 _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",
02644 timeout_milliseconds,
02645 client_serial,
02646 start_tv_sec, start_tv_usec,
02647 end_tv_sec, end_tv_usec);
02648
02649
02650
02651 if (check_for_reply_and_update_dispatch_unlocked (pending))
02652 return;
02653
02654
02655
02656 _dbus_connection_do_iteration_unlocked (connection,
02657 DBUS_ITERATION_DO_READING |
02658 DBUS_ITERATION_BLOCK,
02659 timeout_milliseconds);
02660
02661 recheck_status:
02662
02663 _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME);
02664
02665 HAVE_LOCK_CHECK (connection);
02666
02667
02668
02669 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02670
02671
02672
02673
02674 if (dbus_pending_call_get_completed (pending))
02675 {
02676 _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME);
02677 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02678 dbus_pending_call_unref (pending);
02679 return;
02680 }
02681
02682 if (status == DBUS_DISPATCH_DATA_REMAINS)
02683 if (check_for_reply_and_update_dispatch_unlocked (pending))
02684 return;
02685
02686 _dbus_get_current_time (&tv_sec, &tv_usec);
02687
02688 if (!_dbus_connection_get_is_connected_unlocked (connection))
02689 {
02690
02691
02692
02693
02694
02695 _dbus_pending_call_complete_and_unlock (pending, NULL);
02696 dbus_pending_call_unref (pending);
02697 return;
02698 }
02699 else if (tv_sec < start_tv_sec)
02700 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02701 else if (connection->disconnect_message_link == NULL)
02702 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02703 else if (tv_sec < end_tv_sec ||
02704 (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
02705 {
02706 timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
02707 (end_tv_usec - tv_usec) / 1000;
02708 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
02709 _dbus_assert (timeout_milliseconds >= 0);
02710
02711 if (status == DBUS_DISPATCH_NEED_MEMORY)
02712 {
02713
02714
02715
02716
02717 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02718
02719 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02720 }
02721 else
02722 {
02723
02724 _dbus_connection_do_iteration_unlocked (connection,
02725 DBUS_ITERATION_DO_READING |
02726 DBUS_ITERATION_BLOCK,
02727 timeout_milliseconds);
02728 }
02729
02730 goto recheck_status;
02731 }
02732
02733 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
02734 (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
02735
02736 _dbus_assert (!dbus_pending_call_get_completed (pending));
02737
02738
02739 _dbus_pending_call_complete_and_unlock (pending, NULL);
02740
02741
02742 CONNECTION_LOCK (connection);
02743 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02744 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02745 dbus_pending_call_unref (pending);
02746 }
02747
02770 DBusMessage*
02771 dbus_connection_send_with_reply_and_block (DBusConnection *connection,
02772 DBusMessage *message,
02773 int timeout_milliseconds,
02774 DBusError *error)
02775 {
02776 DBusMessage *reply;
02777 DBusPendingCall *pending;
02778
02779 _dbus_return_val_if_fail (connection != NULL, NULL);
02780 _dbus_return_val_if_fail (message != NULL, NULL);
02781 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
02782 _dbus_return_val_if_error_is_set (error, NULL);
02783
02784 if (!dbus_connection_send_with_reply (connection, message,
02785 &pending, timeout_milliseconds))
02786 {
02787 _DBUS_SET_OOM (error);
02788 return NULL;
02789 }
02790
02791 _dbus_assert (pending != NULL);
02792
02793 dbus_pending_call_block (pending);
02794
02795 reply = dbus_pending_call_steal_reply (pending);
02796 dbus_pending_call_unref (pending);
02797
02798
02799
02800
02801 _dbus_assert (reply != NULL);
02802
02803 if (dbus_set_error_from_message (error, reply))
02804 {
02805 dbus_message_unref (reply);
02806 return NULL;
02807 }
02808 else
02809 return reply;
02810 }
02811
02817 void
02818 dbus_connection_flush (DBusConnection *connection)
02819 {
02820
02821
02822
02823
02824
02825 DBusDispatchStatus status;
02826
02827 _dbus_return_if_fail (connection != NULL);
02828
02829 CONNECTION_LOCK (connection);
02830 while (connection->n_outgoing > 0 &&
02831 _dbus_connection_get_is_connected_unlocked (connection))
02832 {
02833 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
02834 HAVE_LOCK_CHECK (connection);
02835 _dbus_connection_do_iteration_unlocked (connection,
02836 DBUS_ITERATION_DO_READING |
02837 DBUS_ITERATION_DO_WRITING |
02838 DBUS_ITERATION_BLOCK,
02839 -1);
02840 }
02841
02842 HAVE_LOCK_CHECK (connection);
02843 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02844 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02845
02846 HAVE_LOCK_CHECK (connection);
02847
02848 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02849
02850 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
02851 }
02852
02885 dbus_bool_t
02886 _dbus_connection_read_write_dispatch (DBusConnection *connection,
02887 int timeout_milliseconds,
02888 dbus_bool_t dispatch)
02889 {
02890 DBusDispatchStatus dstatus;
02891 dbus_bool_t dispatched_disconnected;
02892
02893 _dbus_return_val_if_fail (connection != NULL, FALSE);
02894 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02895 dstatus = dbus_connection_get_dispatch_status (connection);
02896
02897 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
02898 {
02899 _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME);
02900 dbus_connection_dispatch (connection);
02901 CONNECTION_LOCK (connection);
02902 }
02903 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
02904 {
02905 _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME);
02906 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02907 CONNECTION_LOCK (connection);
02908 }
02909 else
02910 {
02911 CONNECTION_LOCK (connection);
02912 if (_dbus_connection_get_is_connected_unlocked (connection))
02913 {
02914 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
02915 _dbus_connection_do_iteration_unlocked (connection,
02916 DBUS_ITERATION_DO_READING |
02917 DBUS_ITERATION_DO_WRITING |
02918 DBUS_ITERATION_BLOCK,
02919 timeout_milliseconds);
02920 }
02921 }
02922
02923 HAVE_LOCK_CHECK (connection);
02924 dispatched_disconnected = connection->n_incoming == 0 &&
02925 connection->disconnect_message_link == NULL;
02926 CONNECTION_UNLOCK (connection);
02927 return !dispatched_disconnected;
02928 }
02929
02930
02962 dbus_bool_t
02963 dbus_connection_read_write_dispatch (DBusConnection *connection,
02964 int timeout_milliseconds)
02965 {
02966 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
02967 }
02968
02985 dbus_bool_t
02986 dbus_connection_read_write (DBusConnection *connection,
02987 int timeout_milliseconds)
02988 {
02989 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
02990 }
02991
03011 DBusMessage*
03012 dbus_connection_borrow_message (DBusConnection *connection)
03013 {
03014 DBusDispatchStatus status;
03015 DBusMessage *message;
03016
03017 _dbus_return_val_if_fail (connection != NULL, NULL);
03018
03019 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03020
03021
03022
03023
03024 status = dbus_connection_get_dispatch_status (connection);
03025 if (status != DBUS_DISPATCH_DATA_REMAINS)
03026 return NULL;
03027
03028 CONNECTION_LOCK (connection);
03029
03030 _dbus_connection_acquire_dispatch (connection);
03031
03032
03033 _dbus_assert (connection->message_borrowed == NULL);
03034
03035 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03036
03037 message = connection->message_borrowed;
03038
03039
03040 if (message == NULL)
03041 _dbus_connection_release_dispatch (connection);
03042
03043 CONNECTION_UNLOCK (connection);
03044
03045 return message;
03046 }
03047
03056 void
03057 dbus_connection_return_message (DBusConnection *connection,
03058 DBusMessage *message)
03059 {
03060 _dbus_return_if_fail (connection != NULL);
03061 _dbus_return_if_fail (message != NULL);
03062 _dbus_return_if_fail (message == connection->message_borrowed);
03063 _dbus_return_if_fail (connection->dispatch_acquired);
03064
03065 CONNECTION_LOCK (connection);
03066
03067 _dbus_assert (message == connection->message_borrowed);
03068
03069 connection->message_borrowed = NULL;
03070
03071 _dbus_connection_release_dispatch (connection);
03072
03073 CONNECTION_UNLOCK (connection);
03074 }
03075
03085 void
03086 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03087 DBusMessage *message)
03088 {
03089 DBusMessage *pop_message;
03090
03091 _dbus_return_if_fail (connection != NULL);
03092 _dbus_return_if_fail (message != NULL);
03093 _dbus_return_if_fail (message == connection->message_borrowed);
03094 _dbus_return_if_fail (connection->dispatch_acquired);
03095
03096 CONNECTION_LOCK (connection);
03097
03098 _dbus_assert (message == connection->message_borrowed);
03099
03100 pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03101 _dbus_assert (message == pop_message);
03102
03103 connection->n_incoming -= 1;
03104
03105 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03106 message, connection->n_incoming);
03107
03108 connection->message_borrowed = NULL;
03109
03110 _dbus_connection_release_dispatch (connection);
03111
03112 CONNECTION_UNLOCK (connection);
03113 }
03114
03115
03116
03117
03118 static DBusList*
03119 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03120 {
03121 HAVE_LOCK_CHECK (connection);
03122
03123 _dbus_assert (connection->message_borrowed == NULL);
03124
03125 if (connection->n_incoming > 0)
03126 {
03127 DBusList *link;
03128
03129 link = _dbus_list_pop_first_link (&connection->incoming_messages);
03130 connection->n_incoming -= 1;
03131
03132 _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03133 link->data,
03134 dbus_message_get_type (link->data),
03135 dbus_message_get_path (link->data) ?
03136 dbus_message_get_path (link->data) :
03137 "no path",
03138 dbus_message_get_interface (link->data) ?
03139 dbus_message_get_interface (link->data) :
03140 "no interface",
03141 dbus_message_get_member (link->data) ?
03142 dbus_message_get_member (link->data) :
03143 "no member",
03144 dbus_message_get_signature (link->data),
03145 connection, connection->n_incoming);
03146
03147 return link;
03148 }
03149 else
03150 return NULL;
03151 }
03152
03153
03154
03155
03156 static DBusMessage*
03157 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03158 {
03159 DBusList *link;
03160
03161 HAVE_LOCK_CHECK (connection);
03162
03163 link = _dbus_connection_pop_message_link_unlocked (connection);
03164
03165 if (link != NULL)
03166 {
03167 DBusMessage *message;
03168
03169 message = link->data;
03170
03171 _dbus_list_free_link (link);
03172
03173 return message;
03174 }
03175 else
03176 return NULL;
03177 }
03178
03179 static void
03180 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03181 DBusList *message_link)
03182 {
03183 HAVE_LOCK_CHECK (connection);
03184
03185 _dbus_assert (message_link != NULL);
03186
03187 _dbus_assert (connection->message_borrowed == NULL);
03188
03189 _dbus_assert (connection->dispatch_acquired);
03190
03191 _dbus_list_prepend_link (&connection->incoming_messages,
03192 message_link);
03193 connection->n_incoming += 1;
03194
03195 _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
03196 message_link->data,
03197 dbus_message_get_type (message_link->data),
03198 dbus_message_get_interface (message_link->data) ?
03199 dbus_message_get_interface (message_link->data) :
03200 "no interface",
03201 dbus_message_get_member (message_link->data) ?
03202 dbus_message_get_member (message_link->data) :
03203 "no member",
03204 dbus_message_get_signature (message_link->data),
03205 connection, connection->n_incoming);
03206 }
03207
03227 DBusMessage*
03228 dbus_connection_pop_message (DBusConnection *connection)
03229 {
03230 DBusMessage *message;
03231 DBusDispatchStatus status;
03232
03233 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03234
03235
03236
03237
03238 status = dbus_connection_get_dispatch_status (connection);
03239 if (status != DBUS_DISPATCH_DATA_REMAINS)
03240 return NULL;
03241
03242 CONNECTION_LOCK (connection);
03243 _dbus_connection_acquire_dispatch (connection);
03244 HAVE_LOCK_CHECK (connection);
03245
03246 message = _dbus_connection_pop_message_unlocked (connection);
03247
03248 _dbus_verbose ("Returning popped message %p\n", message);
03249
03250 _dbus_connection_release_dispatch (connection);
03251 CONNECTION_UNLOCK (connection);
03252
03253 return message;
03254 }
03255
03263 static void
03264 _dbus_connection_acquire_dispatch (DBusConnection *connection)
03265 {
03266 HAVE_LOCK_CHECK (connection);
03267
03268 _dbus_connection_ref_unlocked (connection);
03269 CONNECTION_UNLOCK (connection);
03270
03271 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03272 _dbus_mutex_lock (connection->dispatch_mutex);
03273
03274 while (connection->dispatch_acquired)
03275 {
03276 _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
03277 _dbus_condvar_wait (connection->dispatch_cond, connection->dispatch_mutex);
03278 }
03279
03280 _dbus_assert (!connection->dispatch_acquired);
03281
03282 connection->dispatch_acquired = TRUE;
03283
03284 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03285 _dbus_mutex_unlock (connection->dispatch_mutex);
03286
03287 CONNECTION_LOCK (connection);
03288 _dbus_connection_unref_unlocked (connection);
03289 }
03290
03298 static void
03299 _dbus_connection_release_dispatch (DBusConnection *connection)
03300 {
03301 HAVE_LOCK_CHECK (connection);
03302
03303 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03304 _dbus_mutex_lock (connection->dispatch_mutex);
03305
03306 _dbus_assert (connection->dispatch_acquired);
03307
03308 connection->dispatch_acquired = FALSE;
03309 _dbus_condvar_wake_one (connection->dispatch_cond);
03310
03311 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03312 _dbus_mutex_unlock (connection->dispatch_mutex);
03313 }
03314
03315 static void
03316 _dbus_connection_failed_pop (DBusConnection *connection,
03317 DBusList *message_link)
03318 {
03319 _dbus_list_prepend_link (&connection->incoming_messages,
03320 message_link);
03321 connection->n_incoming += 1;
03322 }
03323
03324 static DBusDispatchStatus
03325 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
03326 {
03327 HAVE_LOCK_CHECK (connection);
03328
03329 if (connection->n_incoming > 0)
03330 return DBUS_DISPATCH_DATA_REMAINS;
03331 else if (!_dbus_transport_queue_messages (connection->transport))
03332 return DBUS_DISPATCH_NEED_MEMORY;
03333 else
03334 {
03335 DBusDispatchStatus status;
03336 dbus_bool_t is_connected;
03337
03338 status = _dbus_transport_get_dispatch_status (connection->transport);
03339 is_connected = _dbus_transport_get_is_connected (connection->transport);
03340
03341 _dbus_verbose ("dispatch status = %s is_connected = %d\n",
03342 DISPATCH_STATUS_NAME (status), is_connected);
03343
03344 if (!is_connected)
03345 {
03346 if (status == DBUS_DISPATCH_COMPLETE &&
03347 connection->disconnect_message_link)
03348 {
03349 _dbus_verbose ("Sending disconnect message from %s\n",
03350 _DBUS_FUNCTION_NAME);
03351
03352 connection_forget_shared_unlocked (connection);
03353
03354
03355
03356
03357 _dbus_connection_queue_synthesized_message_link (connection,
03358 connection->disconnect_message_link);
03359 connection->disconnect_message_link = NULL;
03360
03361 status = DBUS_DISPATCH_DATA_REMAINS;
03362 }
03363
03364
03365
03366
03367
03368 if (connection->n_outgoing > 0)
03369 {
03370 DBusList *link;
03371
03372 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
03373 connection->n_outgoing);
03374
03375 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
03376 {
03377 _dbus_connection_message_sent (connection, link->data);
03378 }
03379 }
03380 }
03381
03382 if (status != DBUS_DISPATCH_COMPLETE)
03383 return status;
03384 else if (connection->n_incoming > 0)
03385 return DBUS_DISPATCH_DATA_REMAINS;
03386 else
03387 return DBUS_DISPATCH_COMPLETE;
03388 }
03389 }
03390
03391 static void
03392 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
03393 DBusDispatchStatus new_status)
03394 {
03395 dbus_bool_t changed;
03396 DBusDispatchStatusFunction function;
03397 void *data;
03398
03399 HAVE_LOCK_CHECK (connection);
03400
03401 _dbus_connection_ref_unlocked (connection);
03402
03403 changed = new_status != connection->last_dispatch_status;
03404
03405 connection->last_dispatch_status = new_status;
03406
03407 function = connection->dispatch_status_function;
03408 data = connection->dispatch_status_data;
03409
03410
03411 CONNECTION_UNLOCK (connection);
03412
03413 if (changed && function)
03414 {
03415 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
03416 connection, new_status,
03417 DISPATCH_STATUS_NAME (new_status));
03418 (* function) (connection, new_status, data);
03419 }
03420
03421 dbus_connection_unref (connection);
03422 }
03423
03432 DBusDispatchStatus
03433 dbus_connection_get_dispatch_status (DBusConnection *connection)
03434 {
03435 DBusDispatchStatus status;
03436
03437 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
03438
03439 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03440
03441 CONNECTION_LOCK (connection);
03442
03443 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03444
03445 CONNECTION_UNLOCK (connection);
03446
03447 return status;
03448 }
03449
03453 static DBusHandlerResult
03454 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
03455 DBusMessage *message)
03456 {
03457 if (dbus_message_is_method_call (message,
03458 DBUS_INTERFACE_PEER,
03459 "Ping"))
03460 {
03461 DBusMessage *ret;
03462 dbus_bool_t sent;
03463
03464 ret = dbus_message_new_method_return (message);
03465 if (ret == NULL)
03466 return DBUS_HANDLER_RESULT_NEED_MEMORY;
03467
03468 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
03469
03470 dbus_message_unref (ret);
03471
03472 if (!sent)
03473 return DBUS_HANDLER_RESULT_NEED_MEMORY;
03474
03475 return DBUS_HANDLER_RESULT_HANDLED;
03476 }
03477
03478
03479 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03480 }
03481
03488 static DBusHandlerResult
03489 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
03490 DBusMessage *message)
03491 {
03492
03493
03494
03495 return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
03496 }
03497
03521 DBusDispatchStatus
03522 dbus_connection_dispatch (DBusConnection *connection)
03523 {
03524 DBusMessage *message;
03525 DBusList *link, *filter_list_copy, *message_link;
03526 DBusHandlerResult result;
03527 DBusPendingCall *pending;
03528 dbus_int32_t reply_serial;
03529 DBusDispatchStatus status;
03530
03531 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
03532
03533 _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
03534
03535 CONNECTION_LOCK (connection);
03536 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03537 if (status != DBUS_DISPATCH_DATA_REMAINS)
03538 {
03539
03540 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03541 return status;
03542 }
03543
03544
03545
03546
03547 _dbus_connection_ref_unlocked (connection);
03548
03549 _dbus_connection_acquire_dispatch (connection);
03550 HAVE_LOCK_CHECK (connection);
03551
03552 message_link = _dbus_connection_pop_message_link_unlocked (connection);
03553 if (message_link == NULL)
03554 {
03555
03556
03557 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
03558
03559 _dbus_connection_release_dispatch (connection);
03560
03561 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03562
03563 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03564
03565 dbus_connection_unref (connection);
03566
03567 return status;
03568 }
03569
03570 message = message_link->data;
03571
03572 _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
03573 message,
03574 dbus_message_get_type (message),
03575 dbus_message_get_interface (message) ?
03576 dbus_message_get_interface (message) :
03577 "no interface",
03578 dbus_message_get_member (message) ?
03579 dbus_message_get_member (message) :
03580 "no member",
03581 dbus_message_get_signature (message));
03582
03583 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03584
03585
03586
03587
03588
03589
03590
03591
03592 reply_serial = dbus_message_get_reply_serial (message);
03593 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
03594 reply_serial);
03595 if (pending)
03596 {
03597 _dbus_verbose ("Dispatching a pending reply\n");
03598 _dbus_pending_call_complete_and_unlock (pending, message);
03599 pending = NULL;
03600
03601 CONNECTION_LOCK (connection);
03602 _dbus_verbose ("pending call completed in dispatch\n");
03603 result = DBUS_HANDLER_RESULT_HANDLED;
03604 goto out;
03605 }
03606
03607 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
03608 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03609 goto out;
03610
03611 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
03612 {
03613 _dbus_connection_release_dispatch (connection);
03614 HAVE_LOCK_CHECK (connection);
03615
03616 _dbus_connection_failed_pop (connection, message_link);
03617
03618
03619 _dbus_connection_update_dispatch_status_and_unlock (connection,
03620 DBUS_DISPATCH_NEED_MEMORY);
03621
03622 if (pending)
03623 dbus_pending_call_unref (pending);
03624 dbus_connection_unref (connection);
03625
03626 return DBUS_DISPATCH_NEED_MEMORY;
03627 }
03628
03629 _dbus_list_foreach (&filter_list_copy,
03630 (DBusForeachFunction)_dbus_message_filter_ref,
03631 NULL);
03632
03633
03634
03635
03636 CONNECTION_UNLOCK (connection);
03637
03638 link = _dbus_list_get_first_link (&filter_list_copy);
03639 while (link != NULL)
03640 {
03641 DBusMessageFilter *filter = link->data;
03642 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
03643
03644 _dbus_verbose (" running filter on message %p\n", message);
03645 result = (* filter->function) (connection, message, filter->user_data);
03646
03647 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03648 break;
03649
03650 link = next;
03651 }
03652
03653 _dbus_list_foreach (&filter_list_copy,
03654 (DBusForeachFunction)_dbus_message_filter_unref,
03655 NULL);
03656 _dbus_list_clear (&filter_list_copy);
03657
03658 CONNECTION_LOCK (connection);
03659
03660 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
03661 {
03662 _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
03663 goto out;
03664 }
03665 else if (result == DBUS_HANDLER_RESULT_HANDLED)
03666 {
03667 _dbus_verbose ("filter handled message in dispatch\n");
03668 goto out;
03669 }
03670
03671
03672
03673
03674 _dbus_verbose (" running object path dispatch on message %p (%d %s %s '%s')\n",
03675 message,
03676 dbus_message_get_type (message),
03677 dbus_message_get_interface (message) ?
03678 dbus_message_get_interface (message) :
03679 "no interface",
03680 dbus_message_get_member (message) ?
03681 dbus_message_get_member (message) :
03682 "no member",
03683 dbus_message_get_signature (message));
03684
03685 HAVE_LOCK_CHECK (connection);
03686 result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
03687 message);
03688
03689 CONNECTION_LOCK (connection);
03690
03691 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03692 {
03693 _dbus_verbose ("object tree handled message in dispatch\n");
03694 goto out;
03695 }
03696
03697 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
03698 {
03699 DBusMessage *reply;
03700 DBusString str;
03701 DBusPreallocatedSend *preallocated;
03702
03703 _dbus_verbose (" sending error %s\n",
03704 DBUS_ERROR_UNKNOWN_METHOD);
03705
03706 if (!_dbus_string_init (&str))
03707 {
03708 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03709 _dbus_verbose ("no memory for error string in dispatch\n");
03710 goto out;
03711 }
03712
03713 if (!_dbus_string_append_printf (&str,
03714 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
03715 dbus_message_get_member (message),
03716 dbus_message_get_signature (message),
03717 dbus_message_get_interface (message)))
03718 {
03719 _dbus_string_free (&str);
03720 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03721 _dbus_verbose ("no memory for error string in dispatch\n");
03722 goto out;
03723 }
03724
03725 reply = dbus_message_new_error (message,
03726 DBUS_ERROR_UNKNOWN_METHOD,
03727 _dbus_string_get_const_data (&str));
03728 _dbus_string_free (&str);
03729
03730 if (reply == NULL)
03731 {
03732 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03733 _dbus_verbose ("no memory for error reply in dispatch\n");
03734 goto out;
03735 }
03736
03737 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03738
03739 if (preallocated == NULL)
03740 {
03741 dbus_message_unref (reply);
03742 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03743 _dbus_verbose ("no memory for error send in dispatch\n");
03744 goto out;
03745 }
03746
03747 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
03748 reply, NULL);
03749
03750 dbus_message_unref (reply);
03751
03752 result = DBUS_HANDLER_RESULT_HANDLED;
03753 }
03754
03755 _dbus_verbose (" done dispatching %p (%d %s %s '%s') on connection %p\n", message,
03756 dbus_message_get_type (message),
03757 dbus_message_get_interface (message) ?
03758 dbus_message_get_interface (message) :
03759 "no interface",
03760 dbus_message_get_member (message) ?
03761 dbus_message_get_member (message) :
03762 "no member",
03763 dbus_message_get_signature (message),
03764 connection);
03765
03766 out:
03767 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
03768 {
03769 _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
03770
03771
03772
03773
03774
03775 _dbus_connection_putback_message_link_unlocked (connection,
03776 message_link);
03777 }
03778 else
03779 {
03780 _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
03781
03782 if (connection->exit_on_disconnect &&
03783 dbus_message_is_signal (message,
03784 DBUS_INTERFACE_LOCAL,
03785 "Disconnected"))
03786 {
03787 _dbus_verbose ("Exiting on Disconnected signal\n");
03788 CONNECTION_UNLOCK (connection);
03789 _dbus_exit (1);
03790 _dbus_assert_not_reached ("Call to exit() returned");
03791 }
03792
03793 _dbus_list_free_link (message_link);
03794 dbus_message_unref (message);
03795
03796
03797 }
03798
03799 _dbus_connection_release_dispatch (connection);
03800 HAVE_LOCK_CHECK (connection);
03801
03802 _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
03803 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03804
03805
03806 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03807
03808 dbus_connection_unref (connection);
03809
03810 return status;
03811 }
03812
03871 dbus_bool_t
03872 dbus_connection_set_watch_functions (DBusConnection *connection,
03873 DBusAddWatchFunction add_function,
03874 DBusRemoveWatchFunction remove_function,
03875 DBusWatchToggledFunction toggled_function,
03876 void *data,
03877 DBusFreeFunction free_data_function)
03878 {
03879 dbus_bool_t retval;
03880 DBusWatchList *watches;
03881
03882 _dbus_return_val_if_fail (connection != NULL, FALSE);
03883
03884 CONNECTION_LOCK (connection);
03885
03886 #ifndef DBUS_DISABLE_CHECKS
03887 if (connection->watches == NULL)
03888 {
03889 _dbus_warn ("Re-entrant call to %s is not allowed\n",
03890 _DBUS_FUNCTION_NAME);
03891 return FALSE;
03892 }
03893 #endif
03894
03895
03896 _dbus_connection_ref_unlocked (connection);
03897
03898
03899
03900
03901
03902 watches = connection->watches;
03903 connection->watches = NULL;
03904 CONNECTION_UNLOCK (connection);
03905
03906 retval = _dbus_watch_list_set_functions (watches,
03907 add_function, remove_function,
03908 toggled_function,
03909 data, free_data_function);
03910 CONNECTION_LOCK (connection);
03911 connection->watches = watches;
03912
03913 CONNECTION_UNLOCK (connection);
03914
03915 dbus_connection_unref (connection);
03916
03917 return retval;
03918 }
03919
03953 dbus_bool_t
03954 dbus_connection_set_timeout_functions (DBusConnection *connection,
03955 DBusAddTimeoutFunction add_function,
03956 DBusRemoveTimeoutFunction remove_function,
03957 DBusTimeoutToggledFunction toggled_function,
03958 void *data,
03959 DBusFreeFunction free_data_function)
03960 {
03961 dbus_bool_t retval;
03962 DBusTimeoutList *timeouts;
03963
03964 _dbus_return_val_if_fail (connection != NULL, FALSE);
03965
03966 CONNECTION_LOCK (connection);
03967
03968 #ifndef DBUS_DISABLE_CHECKS
03969 if (connection->timeouts == NULL)
03970 {
03971 _dbus_warn ("Re-entrant call to %s is not allowed\n",
03972 _DBUS_FUNCTION_NAME);
03973 return FALSE;
03974 }
03975 #endif
03976
03977
03978 _dbus_connection_ref_unlocked (connection);
03979
03980 timeouts = connection->timeouts;
03981 connection->timeouts = NULL;
03982 CONNECTION_UNLOCK (connection);
03983
03984 retval = _dbus_timeout_list_set_functions (timeouts,
03985 add_function, remove_function,
03986 toggled_function,
03987 data, free_data_function);
03988 CONNECTION_LOCK (connection);
03989 connection->timeouts = timeouts;
03990
03991 CONNECTION_UNLOCK (connection);
03992
03993 dbus_connection_unref (connection);
03994
03995 return retval;
03996 }
03997
04012 void
04013 dbus_connection_set_wakeup_main_function (DBusConnection *connection,
04014 DBusWakeupMainFunction wakeup_main_function,
04015 void *data,
04016 DBusFreeFunction free_data_function)
04017 {
04018 void *old_data;
04019 DBusFreeFunction old_free_data;
04020
04021 _dbus_return_if_fail (connection != NULL);
04022
04023 CONNECTION_LOCK (connection);
04024 old_data = connection->wakeup_main_data;
04025 old_free_data = connection->free_wakeup_main_data;
04026
04027 connection->wakeup_main_function = wakeup_main_function;
04028 connection->wakeup_main_data = data;
04029 connection->free_wakeup_main_data = free_data_function;
04030
04031 CONNECTION_UNLOCK (connection);
04032
04033
04034 if (old_free_data)
04035 (*old_free_data) (old_data);
04036 }
04037
04054 void
04055 dbus_connection_set_dispatch_status_function (DBusConnection *connection,
04056 DBusDispatchStatusFunction function,
04057 void *data,
04058 DBusFreeFunction free_data_function)
04059 {
04060 void *old_data;
04061 DBusFreeFunction old_free_data;
04062
04063 _dbus_return_if_fail (connection != NULL);
04064
04065 CONNECTION_LOCK (connection);
04066 old_data = connection->dispatch_status_data;
04067 old_free_data = connection->free_dispatch_status_data;
04068
04069 connection->dispatch_status_function = function;
04070 connection->dispatch_status_data = data;
04071 connection->free_dispatch_status_data = free_data_function;
04072
04073 CONNECTION_UNLOCK (connection);
04074
04075
04076 if (old_free_data)
04077 (*old_free_data) (old_data);
04078 }
04079
04092 dbus_bool_t
04093 dbus_connection_get_unix_fd (DBusConnection *connection,
04094 int *fd)
04095 {
04096 dbus_bool_t retval;
04097
04098 _dbus_return_val_if_fail (connection != NULL, FALSE);
04099 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04100
04101 CONNECTION_LOCK (connection);
04102
04103 retval = _dbus_transport_get_unix_fd (connection->transport,
04104 fd);
04105
04106 CONNECTION_UNLOCK (connection);
04107
04108 return retval;
04109 }
04110
04122 dbus_bool_t
04123 dbus_connection_get_unix_user (DBusConnection *connection,
04124 unsigned long *uid)
04125 {
04126 dbus_bool_t result;
04127
04128 _dbus_return_val_if_fail (connection != NULL, FALSE);
04129 _dbus_return_val_if_fail (uid != NULL, FALSE);
04130
04131 CONNECTION_LOCK (connection);
04132
04133 if (!_dbus_transport_get_is_authenticated (connection->transport))
04134 result = FALSE;
04135 else
04136 result = _dbus_transport_get_unix_user (connection->transport,
04137 uid);
04138 CONNECTION_UNLOCK (connection);
04139
04140 return result;
04141 }
04142
04153 dbus_bool_t
04154 dbus_connection_get_unix_process_id (DBusConnection *connection,
04155 unsigned long *pid)
04156 {
04157 dbus_bool_t result;
04158
04159 _dbus_return_val_if_fail (connection != NULL, FALSE);
04160 _dbus_return_val_if_fail (pid != NULL, FALSE);
04161
04162 CONNECTION_LOCK (connection);
04163
04164 if (!_dbus_transport_get_is_authenticated (connection->transport))
04165 result = FALSE;
04166 else
04167 result = _dbus_transport_get_unix_process_id (connection->transport,
04168 pid);
04169 CONNECTION_UNLOCK (connection);
04170
04171 return result;
04172 }
04173
04190 void
04191 dbus_connection_set_unix_user_function (DBusConnection *connection,
04192 DBusAllowUnixUserFunction function,
04193 void *data,
04194 DBusFreeFunction free_data_function)
04195 {
04196 void *old_data = NULL;
04197 DBusFreeFunction old_free_function = NULL;
04198
04199 _dbus_return_if_fail (connection != NULL);
04200
04201 CONNECTION_LOCK (connection);
04202 _dbus_transport_set_unix_user_function (connection->transport,
04203 function, data, free_data_function,
04204 &old_data, &old_free_function);
04205 CONNECTION_UNLOCK (connection);
04206
04207 if (old_free_function != NULL)
04208 (* old_free_function) (old_data);
04209 }
04210
04232 dbus_bool_t
04233 dbus_connection_add_filter (DBusConnection *connection,
04234 DBusHandleMessageFunction function,
04235 void *user_data,
04236 DBusFreeFunction free_data_function)
04237 {
04238 DBusMessageFilter *filter;
04239
04240 _dbus_return_val_if_fail (connection != NULL, FALSE);
04241 _dbus_return_val_if_fail (function != NULL, FALSE);
04242
04243 filter = dbus_new0 (DBusMessageFilter, 1);
04244 if (filter == NULL)
04245 return FALSE;
04246
04247 filter->refcount.value = 1;
04248
04249 CONNECTION_LOCK (connection);
04250
04251 if (!_dbus_list_append (&connection->filter_list,
04252 filter))
04253 {
04254 _dbus_message_filter_unref (filter);
04255 CONNECTION_UNLOCK (connection);
04256 return FALSE;
04257 }
04258
04259
04260
04261
04262
04263
04264 filter->function = function;
04265 filter->user_data = user_data;
04266 filter->free_user_data_function = free_data_function;
04267
04268 CONNECTION_UNLOCK (connection);
04269 return TRUE;
04270 }
04271
04284 void
04285 dbus_connection_remove_filter (DBusConnection *connection,
04286 DBusHandleMessageFunction function,
04287 void *user_data)
04288 {
04289 DBusList *link;
04290 DBusMessageFilter *filter;
04291
04292 _dbus_return_if_fail (connection != NULL);
04293 _dbus_return_if_fail (function != NULL);
04294
04295 CONNECTION_LOCK (connection);
04296
04297 filter = NULL;
04298
04299 link = _dbus_list_get_last_link (&connection->filter_list);
04300 while (link != NULL)
04301 {
04302 filter = link->data;
04303
04304 if (filter->function == function &&
04305 filter->user_data == user_data)
04306 {
04307 _dbus_list_remove_link (&connection->filter_list, link);
04308 filter->function = NULL;
04309
04310 break;
04311 }
04312
04313 link = _dbus_list_get_prev_link (&connection->filter_list, link);
04314 }
04315
04316 CONNECTION_UNLOCK (connection);
04317
04318 #ifndef DBUS_DISABLE_CHECKS
04319 if (filter == NULL)
04320 {
04321 _dbus_warn ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
04322 function, user_data);
04323 return;
04324 }
04325 #endif
04326
04327
04328 if (filter->free_user_data_function)
04329 (* filter->free_user_data_function) (filter->user_data);
04330
04331 filter->free_user_data_function = NULL;
04332 filter->user_data = NULL;
04333
04334 _dbus_message_filter_unref (filter);
04335 }
04336
04348 dbus_bool_t
04349 dbus_connection_register_object_path (DBusConnection *connection,
04350 const char *path,
04351 const DBusObjectPathVTable *vtable,
04352 void *user_data)
04353 {
04354 char **decomposed_path;
04355 dbus_bool_t retval;
04356
04357 _dbus_return_val_if_fail (connection != NULL, FALSE);
04358 _dbus_return_val_if_fail (path != NULL, FALSE);
04359 _dbus_return_val_if_fail (path[0] == '/', FALSE);
04360 _dbus_return_val_if_fail (vtable != NULL, FALSE);
04361
04362 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04363 return FALSE;
04364
04365 CONNECTION_LOCK (connection);
04366
04367 retval = _dbus_object_tree_register (connection->objects,
04368 FALSE,
04369 (const char **) decomposed_path, vtable,
04370 user_data);
04371
04372 CONNECTION_UNLOCK (connection);
04373
04374 dbus_free_string_array (decomposed_path);
04375
04376 return retval;
04377 }
04378
04391 dbus_bool_t
04392 dbus_connection_register_fallback (DBusConnection *connection,
04393 const char *path,
04394 const DBusObjectPathVTable *vtable,
04395 void *user_data)
04396 {
04397 char **decomposed_path;
04398 dbus_bool_t retval;
04399
04400 _dbus_return_val_if_fail (connection != NULL, FALSE);
04401 _dbus_return_val_if_fail (path != NULL, FALSE);
04402 _dbus_return_val_if_fail (path[0] == '/', FALSE);
04403 _dbus_return_val_if_fail (vtable != NULL, FALSE);
04404
04405 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04406 return FALSE;
04407
04408 CONNECTION_LOCK (connection);
04409
04410 retval = _dbus_object_tree_register (connection->objects,
04411 TRUE,
04412 (const char **) decomposed_path, vtable,
04413 user_data);
04414
04415 CONNECTION_UNLOCK (connection);
04416
04417 dbus_free_string_array (decomposed_path);
04418
04419 return retval;
04420 }
04421
04431 dbus_bool_t
04432 dbus_connection_unregister_object_path (DBusConnection *connection,
04433 const char *path)
04434 {
04435 char **decomposed_path;
04436
04437 _dbus_return_val_if_fail (connection != NULL, FALSE);
04438 _dbus_return_val_if_fail (path != NULL, FALSE);
04439 _dbus_return_val_if_fail (path[0] == '/', FALSE);
04440
04441 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04442 return FALSE;
04443
04444 CONNECTION_LOCK (connection);
04445
04446 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
04447
04448 dbus_free_string_array (decomposed_path);
04449
04450 return TRUE;
04451 }
04452
04463 dbus_bool_t
04464 dbus_connection_get_object_path_data (DBusConnection *connection,
04465 const char *path,
04466 void **data_p)
04467 {
04468 char **decomposed_path;
04469
04470 _dbus_return_val_if_fail (connection != NULL, FALSE);
04471 _dbus_return_val_if_fail (path != NULL, FALSE);
04472 _dbus_return_val_if_fail (data_p != NULL, FALSE);
04473
04474 *data_p = NULL;
04475
04476 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04477 return FALSE;
04478
04479 CONNECTION_LOCK (connection);
04480
04481 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
04482
04483 CONNECTION_UNLOCK (connection);
04484
04485 dbus_free_string_array (decomposed_path);
04486
04487 return TRUE;
04488 }
04489
04500 dbus_bool_t
04501 dbus_connection_list_registered (DBusConnection *connection,
04502 const char *parent_path,
04503 char ***child_entries)
04504 {
04505 char **decomposed_path;
04506 dbus_bool_t retval;
04507 _dbus_return_val_if_fail (connection != NULL, FALSE);
04508 _dbus_return_val_if_fail (parent_path != NULL, FALSE);
04509 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
04510 _dbus_return_val_if_fail (child_entries != NULL, FALSE);
04511
04512 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
04513 return FALSE;
04514
04515 CONNECTION_LOCK (connection);
04516
04517 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
04518 (const char **) decomposed_path,
04519 child_entries);
04520 dbus_free_string_array (decomposed_path);
04521
04522 return retval;
04523 }
04524
04525 static DBusDataSlotAllocator slot_allocator;
04526 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
04527
04542 dbus_bool_t
04543 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
04544 {
04545 return _dbus_data_slot_allocator_alloc (&slot_allocator,
04546 _DBUS_LOCK_NAME (connection_slots),
04547 slot_p);
04548 }
04549
04561 void
04562 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
04563 {
04564 _dbus_return_if_fail (*slot_p >= 0);
04565
04566 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
04567 }
04568
04582 dbus_bool_t
04583 dbus_connection_set_data (DBusConnection *connection,
04584 dbus_int32_t slot,
04585 void *data,
04586 DBusFreeFunction free_data_func)
04587 {
04588 DBusFreeFunction old_free_func;
04589 void *old_data;
04590 dbus_bool_t retval;
04591
04592 _dbus_return_val_if_fail (connection != NULL, FALSE);
04593 _dbus_return_val_if_fail (slot >= 0, FALSE);
04594
04595 CONNECTION_LOCK (connection);
04596
04597 retval = _dbus_data_slot_list_set (&slot_allocator,
04598 &connection->slot_list,
04599 slot, data, free_data_func,
04600 &old_free_func, &old_data);
04601
04602 CONNECTION_UNLOCK (connection);
04603
04604 if (retval)
04605 {
04606
04607 if (old_free_func)
04608 (* old_free_func) (old_data);
04609 }
04610
04611 return retval;
04612 }
04613
04622 void*
04623 dbus_connection_get_data (DBusConnection *connection,
04624 dbus_int32_t slot)
04625 {
04626 void *res;
04627
04628 _dbus_return_val_if_fail (connection != NULL, NULL);
04629
04630 CONNECTION_LOCK (connection);
04631
04632 res = _dbus_data_slot_list_get (&slot_allocator,
04633 &connection->slot_list,
04634 slot);
04635
04636 CONNECTION_UNLOCK (connection);
04637
04638 return res;
04639 }
04640
04647 void
04648 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
04649 {
04650 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
04651 }
04652
04661 void
04662 dbus_connection_set_max_message_size (DBusConnection *connection,
04663 long size)
04664 {
04665 _dbus_return_if_fail (connection != NULL);
04666
04667 CONNECTION_LOCK (connection);
04668 _dbus_transport_set_max_message_size (connection->transport,
04669 size);
04670 CONNECTION_UNLOCK (connection);
04671 }
04672
04679 long
04680 dbus_connection_get_max_message_size (DBusConnection *connection)
04681 {
04682 long res;
04683
04684 _dbus_return_val_if_fail (connection != NULL, 0);
04685
04686 CONNECTION_LOCK (connection);
04687 res = _dbus_transport_get_max_message_size (connection->transport);
04688 CONNECTION_UNLOCK (connection);
04689 return res;
04690 }
04691
04717 void
04718 dbus_connection_set_max_received_size (DBusConnection *connection,
04719 long size)
04720 {
04721 _dbus_return_if_fail (connection != NULL);
04722
04723 CONNECTION_LOCK (connection);
04724 _dbus_transport_set_max_received_size (connection->transport,
04725 size);
04726 CONNECTION_UNLOCK (connection);
04727 }
04728
04735 long
04736 dbus_connection_get_max_received_size (DBusConnection *connection)
04737 {
04738 long res;
04739
04740 _dbus_return_val_if_fail (connection != NULL, 0);
04741
04742 CONNECTION_LOCK (connection);
04743 res = _dbus_transport_get_max_received_size (connection->transport);
04744 CONNECTION_UNLOCK (connection);
04745 return res;
04746 }
04747
04758 long
04759 dbus_connection_get_outgoing_size (DBusConnection *connection)
04760 {
04761 long res;
04762
04763 _dbus_return_val_if_fail (connection != NULL, 0);
04764
04765 CONNECTION_LOCK (connection);
04766 res = _dbus_counter_get_value (connection->outgoing_counter);
04767 CONNECTION_UNLOCK (connection);
04768 return res;
04769 }
04770