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