D-Bus
1.4.18
|
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-pending-call.h" 00042 #include "dbus-object-tree.h" 00043 #include "dbus-threads-internal.h" 00044 #include "dbus-bus.h" 00045 #include "dbus-marshal-basic.h" 00046 00047 #ifdef DBUS_DISABLE_CHECKS 00048 #define TOOK_LOCK_CHECK(connection) 00049 #define RELEASING_LOCK_CHECK(connection) 00050 #define HAVE_LOCK_CHECK(connection) 00051 #else 00052 #define TOOK_LOCK_CHECK(connection) do { \ 00053 _dbus_assert (!(connection)->have_connection_lock); \ 00054 (connection)->have_connection_lock = TRUE; \ 00055 } while (0) 00056 #define RELEASING_LOCK_CHECK(connection) do { \ 00057 _dbus_assert ((connection)->have_connection_lock); \ 00058 (connection)->have_connection_lock = FALSE; \ 00059 } while (0) 00060 #define HAVE_LOCK_CHECK(connection) _dbus_assert ((connection)->have_connection_lock) 00061 /* A "DO_NOT_HAVE_LOCK_CHECK" is impossible since we need the lock to check the flag */ 00062 #endif 00063 00064 #define TRACE_LOCKS 1 00065 00066 #define CONNECTION_LOCK(connection) do { \ 00067 if (TRACE_LOCKS) { _dbus_verbose ("LOCK\n"); } \ 00068 _dbus_mutex_lock ((connection)->mutex); \ 00069 TOOK_LOCK_CHECK (connection); \ 00070 } while (0) 00071 00072 #define CONNECTION_UNLOCK(connection) do { \ 00073 if (TRACE_LOCKS) { _dbus_verbose ("UNLOCK\n"); } \ 00074 RELEASING_LOCK_CHECK (connection); \ 00075 _dbus_mutex_unlock ((connection)->mutex); \ 00076 } while (0) 00077 00078 #define SLOTS_LOCK(connection) do { \ 00079 _dbus_mutex_lock ((connection)->slot_mutex); \ 00080 } while (0) 00081 00082 #define SLOTS_UNLOCK(connection) do { \ 00083 _dbus_mutex_unlock ((connection)->slot_mutex); \ 00084 } while (0) 00085 00086 #define DISPATCH_STATUS_NAME(s) \ 00087 ((s) == DBUS_DISPATCH_COMPLETE ? "complete" : \ 00088 (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \ 00089 (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" : \ 00090 "???") 00091 00212 typedef struct DBusMessageFilter DBusMessageFilter; 00213 00217 struct DBusMessageFilter 00218 { 00219 DBusAtomic refcount; 00220 DBusHandleMessageFunction function; 00221 void *user_data; 00222 DBusFreeFunction free_user_data_function; 00223 }; 00224 00225 00229 struct DBusPreallocatedSend 00230 { 00231 DBusConnection *connection; 00232 DBusList *queue_link; 00233 DBusList *counter_link; 00234 }; 00235 00236 #if HAVE_DECL_MSG_NOSIGNAL 00237 static dbus_bool_t _dbus_modify_sigpipe = FALSE; 00238 #else 00239 static dbus_bool_t _dbus_modify_sigpipe = TRUE; 00240 #endif 00241 00245 struct DBusConnection 00246 { 00247 DBusAtomic refcount; 00249 DBusMutex *mutex; 00251 DBusMutex *dispatch_mutex; 00252 DBusCondVar *dispatch_cond; 00253 DBusMutex *io_path_mutex; 00254 DBusCondVar *io_path_cond; 00256 DBusList *outgoing_messages; 00257 DBusList *incoming_messages; 00259 DBusMessage *message_borrowed; 00263 int n_outgoing; 00264 int n_incoming; 00266 DBusCounter *outgoing_counter; 00268 DBusTransport *transport; 00269 DBusWatchList *watches; 00270 DBusTimeoutList *timeouts; 00272 DBusList *filter_list; 00274 DBusMutex *slot_mutex; 00275 DBusDataSlotList slot_list; 00277 DBusHashTable *pending_replies; 00279 dbus_uint32_t client_serial; 00280 DBusList *disconnect_message_link; 00282 DBusWakeupMainFunction wakeup_main_function; 00283 void *wakeup_main_data; 00284 DBusFreeFunction free_wakeup_main_data; 00286 DBusDispatchStatusFunction dispatch_status_function; 00287 void *dispatch_status_data; 00288 DBusFreeFunction free_dispatch_status_data; 00290 DBusDispatchStatus last_dispatch_status; 00292 DBusList *link_cache; 00295 DBusObjectTree *objects; 00297 char *server_guid; 00299 /* These two MUST be bools and not bitfields, because they are protected by a separate lock 00300 * from connection->mutex and all bitfields in a word have to be read/written together. 00301 * So you can't have a different lock for different bitfields in the same word. 00302 */ 00303 dbus_bool_t dispatch_acquired; 00304 dbus_bool_t io_path_acquired; 00306 unsigned int shareable : 1; 00308 unsigned int exit_on_disconnect : 1; 00310 unsigned int route_peer_messages : 1; 00312 unsigned int disconnected_message_arrived : 1; 00316 unsigned int disconnected_message_processed : 1; 00320 #ifndef DBUS_DISABLE_CHECKS 00321 unsigned int have_connection_lock : 1; 00322 #endif 00323 00324 #ifndef DBUS_DISABLE_CHECKS 00325 int generation; 00326 #endif 00327 }; 00328 00329 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection); 00330 static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection, 00331 DBusDispatchStatus new_status); 00332 static void _dbus_connection_last_unref (DBusConnection *connection); 00333 static void _dbus_connection_acquire_dispatch (DBusConnection *connection); 00334 static void _dbus_connection_release_dispatch (DBusConnection *connection); 00335 static DBusDispatchStatus _dbus_connection_flush_unlocked (DBusConnection *connection); 00336 static void _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection); 00337 static dbus_bool_t _dbus_connection_get_is_connected_unlocked (DBusConnection *connection); 00338 static dbus_bool_t _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection, 00339 dbus_uint32_t client_serial); 00340 00341 static DBusMessageFilter * 00342 _dbus_message_filter_ref (DBusMessageFilter *filter) 00343 { 00344 #ifdef DBUS_DISABLE_ASSERT 00345 _dbus_atomic_inc (&filter->refcount); 00346 #else 00347 dbus_int32_t old_value; 00348 00349 old_value = _dbus_atomic_inc (&filter->refcount); 00350 _dbus_assert (old_value > 0); 00351 #endif 00352 00353 return filter; 00354 } 00355 00356 static void 00357 _dbus_message_filter_unref (DBusMessageFilter *filter) 00358 { 00359 dbus_int32_t old_value; 00360 00361 old_value = _dbus_atomic_dec (&filter->refcount); 00362 _dbus_assert (old_value > 0); 00363 00364 if (old_value == 1) 00365 { 00366 if (filter->free_user_data_function) 00367 (* filter->free_user_data_function) (filter->user_data); 00368 00369 dbus_free (filter); 00370 } 00371 } 00372 00378 void 00379 _dbus_connection_lock (DBusConnection *connection) 00380 { 00381 CONNECTION_LOCK (connection); 00382 } 00383 00389 void 00390 _dbus_connection_unlock (DBusConnection *connection) 00391 { 00392 CONNECTION_UNLOCK (connection); 00393 } 00394 00402 static void 00403 _dbus_connection_wakeup_mainloop (DBusConnection *connection) 00404 { 00405 if (connection->wakeup_main_function) 00406 (*connection->wakeup_main_function) (connection->wakeup_main_data); 00407 } 00408 00409 #ifdef DBUS_BUILD_TESTS 00410 /* For now this function isn't used */ 00420 dbus_bool_t 00421 _dbus_connection_queue_received_message (DBusConnection *connection, 00422 DBusMessage *message) 00423 { 00424 DBusList *link; 00425 00426 link = _dbus_list_alloc_link (message); 00427 if (link == NULL) 00428 return FALSE; 00429 00430 dbus_message_ref (message); 00431 _dbus_connection_queue_received_message_link (connection, link); 00432 00433 return TRUE; 00434 } 00435 00448 void 00449 _dbus_connection_test_get_locks (DBusConnection *connection, 00450 DBusMutex **mutex_loc, 00451 DBusMutex **dispatch_mutex_loc, 00452 DBusMutex **io_path_mutex_loc, 00453 DBusCondVar **dispatch_cond_loc, 00454 DBusCondVar **io_path_cond_loc) 00455 { 00456 *mutex_loc = connection->mutex; 00457 *dispatch_mutex_loc = connection->dispatch_mutex; 00458 *io_path_mutex_loc = connection->io_path_mutex; 00459 *dispatch_cond_loc = connection->dispatch_cond; 00460 *io_path_cond_loc = connection->io_path_cond; 00461 } 00462 #endif 00463 00472 void 00473 _dbus_connection_queue_received_message_link (DBusConnection *connection, 00474 DBusList *link) 00475 { 00476 DBusPendingCall *pending; 00477 dbus_uint32_t reply_serial; 00478 DBusMessage *message; 00479 00480 _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport)); 00481 00482 _dbus_list_append_link (&connection->incoming_messages, 00483 link); 00484 message = link->data; 00485 00486 /* If this is a reply we're waiting on, remove timeout for it */ 00487 reply_serial = dbus_message_get_reply_serial (message); 00488 if (reply_serial != 0) 00489 { 00490 pending = _dbus_hash_table_lookup_int (connection->pending_replies, 00491 reply_serial); 00492 if (pending != NULL) 00493 { 00494 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 00495 _dbus_connection_remove_timeout_unlocked (connection, 00496 _dbus_pending_call_get_timeout_unlocked (pending)); 00497 00498 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 00499 } 00500 } 00501 00502 00503 00504 connection->n_incoming += 1; 00505 00506 _dbus_connection_wakeup_mainloop (connection); 00507 00508 _dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n", 00509 message, 00510 dbus_message_type_to_string (dbus_message_get_type (message)), 00511 dbus_message_get_path (message) ? 00512 dbus_message_get_path (message) : 00513 "no path", 00514 dbus_message_get_interface (message) ? 00515 dbus_message_get_interface (message) : 00516 "no interface", 00517 dbus_message_get_member (message) ? 00518 dbus_message_get_member (message) : 00519 "no member", 00520 dbus_message_get_signature (message), 00521 dbus_message_get_reply_serial (message), 00522 connection, 00523 connection->n_incoming);} 00524 00533 void 00534 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection, 00535 DBusList *link) 00536 { 00537 HAVE_LOCK_CHECK (connection); 00538 00539 _dbus_list_append_link (&connection->incoming_messages, link); 00540 00541 connection->n_incoming += 1; 00542 00543 _dbus_connection_wakeup_mainloop (connection); 00544 00545 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n", 00546 link->data, connection, connection->n_incoming); 00547 } 00548 00549 00557 dbus_bool_t 00558 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection) 00559 { 00560 HAVE_LOCK_CHECK (connection); 00561 return connection->outgoing_messages != NULL; 00562 } 00563 00573 dbus_bool_t 00574 dbus_connection_has_messages_to_send (DBusConnection *connection) 00575 { 00576 dbus_bool_t v; 00577 00578 _dbus_return_val_if_fail (connection != NULL, FALSE); 00579 00580 CONNECTION_LOCK (connection); 00581 v = _dbus_connection_has_messages_to_send_unlocked (connection); 00582 CONNECTION_UNLOCK (connection); 00583 00584 return v; 00585 } 00586 00594 DBusMessage* 00595 _dbus_connection_get_message_to_send (DBusConnection *connection) 00596 { 00597 HAVE_LOCK_CHECK (connection); 00598 00599 return _dbus_list_get_last (&connection->outgoing_messages); 00600 } 00601 00610 void 00611 _dbus_connection_message_sent (DBusConnection *connection, 00612 DBusMessage *message) 00613 { 00614 DBusList *link; 00615 00616 HAVE_LOCK_CHECK (connection); 00617 00618 /* This can be called before we even complete authentication, since 00619 * it's called on disconnect to clean up the outgoing queue. 00620 * It's also called as we successfully send each message. 00621 */ 00622 00623 link = _dbus_list_get_last_link (&connection->outgoing_messages); 00624 _dbus_assert (link != NULL); 00625 _dbus_assert (link->data == message); 00626 00627 /* Save this link in the link cache */ 00628 _dbus_list_unlink (&connection->outgoing_messages, 00629 link); 00630 _dbus_list_prepend_link (&connection->link_cache, link); 00631 00632 connection->n_outgoing -= 1; 00633 00634 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n", 00635 message, 00636 dbus_message_type_to_string (dbus_message_get_type (message)), 00637 dbus_message_get_path (message) ? 00638 dbus_message_get_path (message) : 00639 "no path", 00640 dbus_message_get_interface (message) ? 00641 dbus_message_get_interface (message) : 00642 "no interface", 00643 dbus_message_get_member (message) ? 00644 dbus_message_get_member (message) : 00645 "no member", 00646 dbus_message_get_signature (message), 00647 connection, connection->n_outgoing); 00648 00649 /* Save this link in the link cache also */ 00650 _dbus_message_remove_counter (message, connection->outgoing_counter, 00651 &link); 00652 _dbus_list_prepend_link (&connection->link_cache, link); 00653 00654 dbus_message_unref (message); 00655 } 00656 00658 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list, 00659 DBusWatch *watch); 00661 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list, 00662 DBusWatch *watch); 00664 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list, 00665 DBusWatch *watch, 00666 dbus_bool_t enabled); 00667 00668 static dbus_bool_t 00669 protected_change_watch (DBusConnection *connection, 00670 DBusWatch *watch, 00671 DBusWatchAddFunction add_function, 00672 DBusWatchRemoveFunction remove_function, 00673 DBusWatchToggleFunction toggle_function, 00674 dbus_bool_t enabled) 00675 { 00676 dbus_bool_t retval; 00677 00678 HAVE_LOCK_CHECK (connection); 00679 00680 /* The original purpose of protected_change_watch() was to hold a 00681 * ref on the connection while dropping the connection lock, then 00682 * calling out to the app. This was a broken hack that did not 00683 * work, since the connection was in a hosed state (no WatchList 00684 * field) while calling out. 00685 * 00686 * So for now we'll just keep the lock while calling out. This means 00687 * apps are not allowed to call DBusConnection methods inside a 00688 * watch function or they will deadlock. 00689 * 00690 * The "real fix" is to use the _and_unlock() pattern found 00691 * elsewhere in the code, to defer calling out to the app until 00692 * we're about to drop locks and return flow of control to the app 00693 * anyway. 00694 * 00695 * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144 00696 */ 00697 00698 if (connection->watches) 00699 { 00700 if (add_function) 00701 retval = (* add_function) (connection->watches, watch); 00702 else if (remove_function) 00703 { 00704 retval = TRUE; 00705 (* remove_function) (connection->watches, watch); 00706 } 00707 else 00708 { 00709 retval = TRUE; 00710 (* toggle_function) (connection->watches, watch, enabled); 00711 } 00712 return retval; 00713 } 00714 else 00715 return FALSE; 00716 } 00717 00718 00730 dbus_bool_t 00731 _dbus_connection_add_watch_unlocked (DBusConnection *connection, 00732 DBusWatch *watch) 00733 { 00734 return protected_change_watch (connection, watch, 00735 _dbus_watch_list_add_watch, 00736 NULL, NULL, FALSE); 00737 } 00738 00748 void 00749 _dbus_connection_remove_watch_unlocked (DBusConnection *connection, 00750 DBusWatch *watch) 00751 { 00752 protected_change_watch (connection, watch, 00753 NULL, 00754 _dbus_watch_list_remove_watch, 00755 NULL, FALSE); 00756 } 00757 00768 void 00769 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection, 00770 DBusWatch *watch, 00771 dbus_bool_t enabled) 00772 { 00773 _dbus_assert (watch != NULL); 00774 00775 protected_change_watch (connection, watch, 00776 NULL, NULL, 00777 _dbus_watch_list_toggle_watch, 00778 enabled); 00779 } 00780 00782 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list, 00783 DBusTimeout *timeout); 00785 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list, 00786 DBusTimeout *timeout); 00788 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list, 00789 DBusTimeout *timeout, 00790 dbus_bool_t enabled); 00791 00792 static dbus_bool_t 00793 protected_change_timeout (DBusConnection *connection, 00794 DBusTimeout *timeout, 00795 DBusTimeoutAddFunction add_function, 00796 DBusTimeoutRemoveFunction remove_function, 00797 DBusTimeoutToggleFunction toggle_function, 00798 dbus_bool_t enabled) 00799 { 00800 dbus_bool_t retval; 00801 00802 HAVE_LOCK_CHECK (connection); 00803 00804 /* The original purpose of protected_change_timeout() was to hold a 00805 * ref on the connection while dropping the connection lock, then 00806 * calling out to the app. This was a broken hack that did not 00807 * work, since the connection was in a hosed state (no TimeoutList 00808 * field) while calling out. 00809 * 00810 * So for now we'll just keep the lock while calling out. This means 00811 * apps are not allowed to call DBusConnection methods inside a 00812 * timeout function or they will deadlock. 00813 * 00814 * The "real fix" is to use the _and_unlock() pattern found 00815 * elsewhere in the code, to defer calling out to the app until 00816 * we're about to drop locks and return flow of control to the app 00817 * anyway. 00818 * 00819 * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144 00820 */ 00821 00822 if (connection->timeouts) 00823 { 00824 if (add_function) 00825 retval = (* add_function) (connection->timeouts, timeout); 00826 else if (remove_function) 00827 { 00828 retval = TRUE; 00829 (* remove_function) (connection->timeouts, timeout); 00830 } 00831 else 00832 { 00833 retval = TRUE; 00834 (* toggle_function) (connection->timeouts, timeout, enabled); 00835 } 00836 return retval; 00837 } 00838 else 00839 return FALSE; 00840 } 00841 00854 dbus_bool_t 00855 _dbus_connection_add_timeout_unlocked (DBusConnection *connection, 00856 DBusTimeout *timeout) 00857 { 00858 return protected_change_timeout (connection, timeout, 00859 _dbus_timeout_list_add_timeout, 00860 NULL, NULL, FALSE); 00861 } 00862 00872 void 00873 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection, 00874 DBusTimeout *timeout) 00875 { 00876 protected_change_timeout (connection, timeout, 00877 NULL, 00878 _dbus_timeout_list_remove_timeout, 00879 NULL, FALSE); 00880 } 00881 00892 void 00893 _dbus_connection_toggle_timeout_unlocked (DBusConnection *connection, 00894 DBusTimeout *timeout, 00895 dbus_bool_t enabled) 00896 { 00897 protected_change_timeout (connection, timeout, 00898 NULL, NULL, 00899 _dbus_timeout_list_toggle_timeout, 00900 enabled); 00901 } 00902 00903 static dbus_bool_t 00904 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection, 00905 DBusPendingCall *pending) 00906 { 00907 dbus_uint32_t reply_serial; 00908 DBusTimeout *timeout; 00909 00910 HAVE_LOCK_CHECK (connection); 00911 00912 reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending); 00913 00914 _dbus_assert (reply_serial != 0); 00915 00916 timeout = _dbus_pending_call_get_timeout_unlocked (pending); 00917 00918 if (timeout) 00919 { 00920 if (!_dbus_connection_add_timeout_unlocked (connection, timeout)) 00921 return FALSE; 00922 00923 if (!_dbus_hash_table_insert_int (connection->pending_replies, 00924 reply_serial, 00925 pending)) 00926 { 00927 _dbus_connection_remove_timeout_unlocked (connection, timeout); 00928 00929 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 00930 HAVE_LOCK_CHECK (connection); 00931 return FALSE; 00932 } 00933 00934 _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE); 00935 } 00936 else 00937 { 00938 if (!_dbus_hash_table_insert_int (connection->pending_replies, 00939 reply_serial, 00940 pending)) 00941 { 00942 HAVE_LOCK_CHECK (connection); 00943 return FALSE; 00944 } 00945 } 00946 00947 _dbus_pending_call_ref_unlocked (pending); 00948 00949 HAVE_LOCK_CHECK (connection); 00950 00951 return TRUE; 00952 } 00953 00954 static void 00955 free_pending_call_on_hash_removal (void *data) 00956 { 00957 DBusPendingCall *pending; 00958 DBusConnection *connection; 00959 00960 if (data == NULL) 00961 return; 00962 00963 pending = data; 00964 00965 connection = _dbus_pending_call_get_connection_unlocked (pending); 00966 00967 HAVE_LOCK_CHECK (connection); 00968 00969 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 00970 { 00971 _dbus_connection_remove_timeout_unlocked (connection, 00972 _dbus_pending_call_get_timeout_unlocked (pending)); 00973 00974 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 00975 } 00976 00977 /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock 00978 * here, but the pending call finalizer could in principle call out to 00979 * application code so we pretty much have to... some larger code reorg 00980 * might be needed. 00981 */ 00982 _dbus_connection_ref_unlocked (connection); 00983 _dbus_pending_call_unref_and_unlock (pending); 00984 CONNECTION_LOCK (connection); 00985 _dbus_connection_unref_unlocked (connection); 00986 } 00987 00988 static void 00989 _dbus_connection_detach_pending_call_unlocked (DBusConnection *connection, 00990 DBusPendingCall *pending) 00991 { 00992 /* This ends up unlocking to call the pending call finalizer, which is unexpected to 00993 * say the least. 00994 */ 00995 _dbus_hash_table_remove_int (connection->pending_replies, 00996 _dbus_pending_call_get_reply_serial_unlocked (pending)); 00997 } 00998 00999 static void 01000 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection, 01001 DBusPendingCall *pending) 01002 { 01003 /* The idea here is to avoid finalizing the pending call 01004 * with the lock held, since there's a destroy notifier 01005 * in pending call that goes out to application code. 01006 * 01007 * There's an extra unlock inside the hash table 01008 * "free pending call" function FIXME... 01009 */ 01010 _dbus_pending_call_ref_unlocked (pending); 01011 _dbus_hash_table_remove_int (connection->pending_replies, 01012 _dbus_pending_call_get_reply_serial_unlocked (pending)); 01013 01014 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 01015 _dbus_connection_remove_timeout_unlocked (connection, 01016 _dbus_pending_call_get_timeout_unlocked (pending)); 01017 01018 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 01019 01020 _dbus_pending_call_unref_and_unlock (pending); 01021 } 01022 01031 void 01032 _dbus_connection_remove_pending_call (DBusConnection *connection, 01033 DBusPendingCall *pending) 01034 { 01035 CONNECTION_LOCK (connection); 01036 _dbus_connection_detach_pending_call_and_unlock (connection, pending); 01037 } 01038 01048 static dbus_bool_t 01049 _dbus_connection_acquire_io_path (DBusConnection *connection, 01050 int timeout_milliseconds) 01051 { 01052 dbus_bool_t we_acquired; 01053 01054 HAVE_LOCK_CHECK (connection); 01055 01056 /* We don't want the connection to vanish */ 01057 _dbus_connection_ref_unlocked (connection); 01058 01059 /* We will only touch io_path_acquired which is protected by our mutex */ 01060 CONNECTION_UNLOCK (connection); 01061 01062 _dbus_verbose ("locking io_path_mutex\n"); 01063 _dbus_mutex_lock (connection->io_path_mutex); 01064 01065 _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n", 01066 connection->io_path_acquired, timeout_milliseconds); 01067 01068 we_acquired = FALSE; 01069 01070 if (connection->io_path_acquired) 01071 { 01072 if (timeout_milliseconds != -1) 01073 { 01074 _dbus_verbose ("waiting %d for IO path to be acquirable\n", 01075 timeout_milliseconds); 01076 01077 if (!_dbus_condvar_wait_timeout (connection->io_path_cond, 01078 connection->io_path_mutex, 01079 timeout_milliseconds)) 01080 { 01081 /* We timed out before anyone signaled. */ 01082 /* (writing the loop to handle the !timedout case by 01083 * waiting longer if needed is a pain since dbus 01084 * wraps pthread_cond_timedwait to take a relative 01085 * time instead of absolute, something kind of stupid 01086 * on our part. for now it doesn't matter, we will just 01087 * end up back here eventually.) 01088 */ 01089 } 01090 } 01091 else 01092 { 01093 while (connection->io_path_acquired) 01094 { 01095 _dbus_verbose ("waiting for IO path to be acquirable\n"); 01096 _dbus_condvar_wait (connection->io_path_cond, 01097 connection->io_path_mutex); 01098 } 01099 } 01100 } 01101 01102 if (!connection->io_path_acquired) 01103 { 01104 we_acquired = TRUE; 01105 connection->io_path_acquired = TRUE; 01106 } 01107 01108 _dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n", 01109 connection->io_path_acquired, we_acquired); 01110 01111 _dbus_verbose ("unlocking io_path_mutex\n"); 01112 _dbus_mutex_unlock (connection->io_path_mutex); 01113 01114 CONNECTION_LOCK (connection); 01115 01116 HAVE_LOCK_CHECK (connection); 01117 01118 _dbus_connection_unref_unlocked (connection); 01119 01120 return we_acquired; 01121 } 01122 01130 static void 01131 _dbus_connection_release_io_path (DBusConnection *connection) 01132 { 01133 HAVE_LOCK_CHECK (connection); 01134 01135 _dbus_verbose ("locking io_path_mutex\n"); 01136 _dbus_mutex_lock (connection->io_path_mutex); 01137 01138 _dbus_assert (connection->io_path_acquired); 01139 01140 _dbus_verbose ("start connection->io_path_acquired = %d\n", 01141 connection->io_path_acquired); 01142 01143 connection->io_path_acquired = FALSE; 01144 _dbus_condvar_wake_one (connection->io_path_cond); 01145 01146 _dbus_verbose ("unlocking io_path_mutex\n"); 01147 _dbus_mutex_unlock (connection->io_path_mutex); 01148 } 01149 01185 void 01186 _dbus_connection_do_iteration_unlocked (DBusConnection *connection, 01187 DBusPendingCall *pending, 01188 unsigned int flags, 01189 int timeout_milliseconds) 01190 { 01191 _dbus_verbose ("start\n"); 01192 01193 HAVE_LOCK_CHECK (connection); 01194 01195 if (connection->n_outgoing == 0) 01196 flags &= ~DBUS_ITERATION_DO_WRITING; 01197 01198 if (_dbus_connection_acquire_io_path (connection, 01199 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0)) 01200 { 01201 HAVE_LOCK_CHECK (connection); 01202 01203 if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending)) 01204 { 01205 _dbus_verbose ("pending call completed while acquiring I/O path"); 01206 } 01207 else if ( (pending != NULL) && 01208 _dbus_connection_peek_for_reply_unlocked (connection, 01209 _dbus_pending_call_get_reply_serial_unlocked (pending))) 01210 { 01211 _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)"); 01212 } 01213 else 01214 { 01215 _dbus_transport_do_iteration (connection->transport, 01216 flags, timeout_milliseconds); 01217 } 01218 01219 _dbus_connection_release_io_path (connection); 01220 } 01221 01222 HAVE_LOCK_CHECK (connection); 01223 01224 _dbus_verbose ("end\n"); 01225 } 01226 01236 DBusConnection* 01237 _dbus_connection_new_for_transport (DBusTransport *transport) 01238 { 01239 DBusConnection *connection; 01240 DBusWatchList *watch_list; 01241 DBusTimeoutList *timeout_list; 01242 DBusHashTable *pending_replies; 01243 DBusList *disconnect_link; 01244 DBusMessage *disconnect_message; 01245 DBusCounter *outgoing_counter; 01246 DBusObjectTree *objects; 01247 01248 watch_list = NULL; 01249 connection = NULL; 01250 pending_replies = NULL; 01251 timeout_list = NULL; 01252 disconnect_link = NULL; 01253 disconnect_message = NULL; 01254 outgoing_counter = NULL; 01255 objects = NULL; 01256 01257 watch_list = _dbus_watch_list_new (); 01258 if (watch_list == NULL) 01259 goto error; 01260 01261 timeout_list = _dbus_timeout_list_new (); 01262 if (timeout_list == NULL) 01263 goto error; 01264 01265 pending_replies = 01266 _dbus_hash_table_new (DBUS_HASH_INT, 01267 NULL, 01268 (DBusFreeFunction)free_pending_call_on_hash_removal); 01269 if (pending_replies == NULL) 01270 goto error; 01271 01272 connection = dbus_new0 (DBusConnection, 1); 01273 if (connection == NULL) 01274 goto error; 01275 01276 _dbus_mutex_new_at_location (&connection->mutex); 01277 if (connection->mutex == NULL) 01278 goto error; 01279 01280 _dbus_mutex_new_at_location (&connection->io_path_mutex); 01281 if (connection->io_path_mutex == NULL) 01282 goto error; 01283 01284 _dbus_mutex_new_at_location (&connection->dispatch_mutex); 01285 if (connection->dispatch_mutex == NULL) 01286 goto error; 01287 01288 _dbus_condvar_new_at_location (&connection->dispatch_cond); 01289 if (connection->dispatch_cond == NULL) 01290 goto error; 01291 01292 _dbus_condvar_new_at_location (&connection->io_path_cond); 01293 if (connection->io_path_cond == NULL) 01294 goto error; 01295 01296 _dbus_mutex_new_at_location (&connection->slot_mutex); 01297 if (connection->slot_mutex == NULL) 01298 goto error; 01299 01300 disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL, 01301 DBUS_INTERFACE_LOCAL, 01302 "Disconnected"); 01303 01304 if (disconnect_message == NULL) 01305 goto error; 01306 01307 disconnect_link = _dbus_list_alloc_link (disconnect_message); 01308 if (disconnect_link == NULL) 01309 goto error; 01310 01311 outgoing_counter = _dbus_counter_new (); 01312 if (outgoing_counter == NULL) 01313 goto error; 01314 01315 objects = _dbus_object_tree_new (connection); 01316 if (objects == NULL) 01317 goto error; 01318 01319 if (_dbus_modify_sigpipe) 01320 _dbus_disable_sigpipe (); 01321 01322 /* initialized to 0: use atomic op to avoid mixing atomic and non-atomic */ 01323 _dbus_atomic_inc (&connection->refcount); 01324 connection->transport = transport; 01325 connection->watches = watch_list; 01326 connection->timeouts = timeout_list; 01327 connection->pending_replies = pending_replies; 01328 connection->outgoing_counter = outgoing_counter; 01329 connection->filter_list = NULL; 01330 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */ 01331 connection->objects = objects; 01332 connection->exit_on_disconnect = FALSE; 01333 connection->shareable = FALSE; 01334 connection->route_peer_messages = FALSE; 01335 connection->disconnected_message_arrived = FALSE; 01336 connection->disconnected_message_processed = FALSE; 01337 01338 #ifndef DBUS_DISABLE_CHECKS 01339 connection->generation = _dbus_current_generation; 01340 #endif 01341 01342 _dbus_data_slot_list_init (&connection->slot_list); 01343 01344 connection->client_serial = 1; 01345 01346 connection->disconnect_message_link = disconnect_link; 01347 01348 CONNECTION_LOCK (connection); 01349 01350 if (!_dbus_transport_set_connection (transport, connection)) 01351 { 01352 CONNECTION_UNLOCK (connection); 01353 01354 goto error; 01355 } 01356 01357 _dbus_transport_ref (transport); 01358 01359 CONNECTION_UNLOCK (connection); 01360 01361 return connection; 01362 01363 error: 01364 if (disconnect_message != NULL) 01365 dbus_message_unref (disconnect_message); 01366 01367 if (disconnect_link != NULL) 01368 _dbus_list_free_link (disconnect_link); 01369 01370 if (connection != NULL) 01371 { 01372 _dbus_condvar_free_at_location (&connection->io_path_cond); 01373 _dbus_condvar_free_at_location (&connection->dispatch_cond); 01374 _dbus_mutex_free_at_location (&connection->mutex); 01375 _dbus_mutex_free_at_location (&connection->io_path_mutex); 01376 _dbus_mutex_free_at_location (&connection->dispatch_mutex); 01377 _dbus_mutex_free_at_location (&connection->slot_mutex); 01378 dbus_free (connection); 01379 } 01380 if (pending_replies) 01381 _dbus_hash_table_unref (pending_replies); 01382 01383 if (watch_list) 01384 _dbus_watch_list_free (watch_list); 01385 01386 if (timeout_list) 01387 _dbus_timeout_list_free (timeout_list); 01388 01389 if (outgoing_counter) 01390 _dbus_counter_unref (outgoing_counter); 01391 01392 if (objects) 01393 _dbus_object_tree_unref (objects); 01394 01395 return NULL; 01396 } 01397 01405 DBusConnection * 01406 _dbus_connection_ref_unlocked (DBusConnection *connection) 01407 { 01408 _dbus_assert (connection != NULL); 01409 _dbus_assert (connection->generation == _dbus_current_generation); 01410 01411 HAVE_LOCK_CHECK (connection); 01412 01413 _dbus_atomic_inc (&connection->refcount); 01414 01415 return connection; 01416 } 01417 01424 void 01425 _dbus_connection_unref_unlocked (DBusConnection *connection) 01426 { 01427 dbus_bool_t last_unref; 01428 01429 HAVE_LOCK_CHECK (connection); 01430 01431 _dbus_assert (connection != NULL); 01432 01433 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1); 01434 01435 if (last_unref) 01436 _dbus_connection_last_unref (connection); 01437 } 01438 01439 static dbus_uint32_t 01440 _dbus_connection_get_next_client_serial (DBusConnection *connection) 01441 { 01442 dbus_uint32_t serial; 01443 01444 serial = connection->client_serial++; 01445 01446 if (connection->client_serial == 0) 01447 connection->client_serial = 1; 01448 01449 return serial; 01450 } 01451 01465 dbus_bool_t 01466 _dbus_connection_handle_watch (DBusWatch *watch, 01467 unsigned int condition, 01468 void *data) 01469 { 01470 DBusConnection *connection; 01471 dbus_bool_t retval; 01472 DBusDispatchStatus status; 01473 01474 connection = data; 01475 01476 _dbus_verbose ("start\n"); 01477 01478 CONNECTION_LOCK (connection); 01479 01480 if (!_dbus_connection_acquire_io_path (connection, 1)) 01481 { 01482 /* another thread is handling the message */ 01483 CONNECTION_UNLOCK (connection); 01484 return TRUE; 01485 } 01486 01487 HAVE_LOCK_CHECK (connection); 01488 retval = _dbus_transport_handle_watch (connection->transport, 01489 watch, condition); 01490 01491 _dbus_connection_release_io_path (connection); 01492 01493 HAVE_LOCK_CHECK (connection); 01494 01495 _dbus_verbose ("middle\n"); 01496 01497 status = _dbus_connection_get_dispatch_status_unlocked (connection); 01498 01499 /* this calls out to user code */ 01500 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 01501 01502 _dbus_verbose ("end\n"); 01503 01504 return retval; 01505 } 01506 01507 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections); 01508 static DBusHashTable *shared_connections = NULL; 01509 static DBusList *shared_connections_no_guid = NULL; 01510 01511 static void 01512 close_connection_on_shutdown (DBusConnection *connection) 01513 { 01514 DBusMessage *message; 01515 01516 dbus_connection_ref (connection); 01517 _dbus_connection_close_possibly_shared (connection); 01518 01519 /* Churn through to the Disconnected message */ 01520 while ((message = dbus_connection_pop_message (connection))) 01521 { 01522 dbus_message_unref (message); 01523 } 01524 dbus_connection_unref (connection); 01525 } 01526 01527 static void 01528 shared_connections_shutdown (void *data) 01529 { 01530 int n_entries; 01531 01532 _DBUS_LOCK (shared_connections); 01533 01534 /* This is a little bit unpleasant... better ideas? */ 01535 while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0) 01536 { 01537 DBusConnection *connection; 01538 DBusHashIter iter; 01539 01540 _dbus_hash_iter_init (shared_connections, &iter); 01541 _dbus_hash_iter_next (&iter); 01542 01543 connection = _dbus_hash_iter_get_value (&iter); 01544 01545 _DBUS_UNLOCK (shared_connections); 01546 close_connection_on_shutdown (connection); 01547 _DBUS_LOCK (shared_connections); 01548 01549 /* The connection should now be dead and not in our hash ... */ 01550 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries); 01551 } 01552 01553 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0); 01554 01555 _dbus_hash_table_unref (shared_connections); 01556 shared_connections = NULL; 01557 01558 if (shared_connections_no_guid != NULL) 01559 { 01560 DBusConnection *connection; 01561 connection = _dbus_list_pop_first (&shared_connections_no_guid); 01562 while (connection != NULL) 01563 { 01564 _DBUS_UNLOCK (shared_connections); 01565 close_connection_on_shutdown (connection); 01566 _DBUS_LOCK (shared_connections); 01567 connection = _dbus_list_pop_first (&shared_connections_no_guid); 01568 } 01569 } 01570 01571 shared_connections_no_guid = NULL; 01572 01573 _DBUS_UNLOCK (shared_connections); 01574 } 01575 01576 static dbus_bool_t 01577 connection_lookup_shared (DBusAddressEntry *entry, 01578 DBusConnection **result) 01579 { 01580 _dbus_verbose ("checking for existing connection\n"); 01581 01582 *result = NULL; 01583 01584 _DBUS_LOCK (shared_connections); 01585 01586 if (shared_connections == NULL) 01587 { 01588 _dbus_verbose ("creating shared_connections hash table\n"); 01589 01590 shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING, 01591 dbus_free, 01592 NULL); 01593 if (shared_connections == NULL) 01594 { 01595 _DBUS_UNLOCK (shared_connections); 01596 return FALSE; 01597 } 01598 01599 if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL)) 01600 { 01601 _dbus_hash_table_unref (shared_connections); 01602 shared_connections = NULL; 01603 _DBUS_UNLOCK (shared_connections); 01604 return FALSE; 01605 } 01606 01607 _dbus_verbose (" successfully created shared_connections\n"); 01608 01609 _DBUS_UNLOCK (shared_connections); 01610 return TRUE; /* no point looking up in the hash we just made */ 01611 } 01612 else 01613 { 01614 const char *guid; 01615 01616 guid = dbus_address_entry_get_value (entry, "guid"); 01617 01618 if (guid != NULL) 01619 { 01620 DBusConnection *connection; 01621 01622 connection = _dbus_hash_table_lookup_string (shared_connections, 01623 guid); 01624 01625 if (connection) 01626 { 01627 /* The DBusConnection can't be finalized without taking 01628 * the shared_connections lock to remove it from the 01629 * hash. So it's safe to ref the connection here. 01630 * However, it may be disconnected if the Disconnected 01631 * message hasn't been processed yet, in which case we 01632 * want to pretend it isn't in the hash and avoid 01633 * returning it. 01634 * 01635 * The idea is to avoid ever returning a disconnected connection 01636 * from dbus_connection_open(). We could just synchronously 01637 * drop our shared ref to the connection on connection disconnect, 01638 * and then assert here that the connection is connected, but 01639 * that causes reentrancy headaches. 01640 */ 01641 CONNECTION_LOCK (connection); 01642 if (_dbus_connection_get_is_connected_unlocked (connection)) 01643 { 01644 _dbus_connection_ref_unlocked (connection); 01645 *result = connection; 01646 _dbus_verbose ("looked up existing connection to server guid %s\n", 01647 guid); 01648 } 01649 else 01650 { 01651 _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n", 01652 guid); 01653 } 01654 CONNECTION_UNLOCK (connection); 01655 } 01656 } 01657 01658 _DBUS_UNLOCK (shared_connections); 01659 return TRUE; 01660 } 01661 } 01662 01663 static dbus_bool_t 01664 connection_record_shared_unlocked (DBusConnection *connection, 01665 const char *guid) 01666 { 01667 char *guid_key; 01668 char *guid_in_connection; 01669 01670 HAVE_LOCK_CHECK (connection); 01671 _dbus_assert (connection->server_guid == NULL); 01672 _dbus_assert (connection->shareable); 01673 01674 /* get a hard ref on this connection, even if 01675 * we won't in fact store it in the hash, we still 01676 * need to hold a ref on it until it's disconnected. 01677 */ 01678 _dbus_connection_ref_unlocked (connection); 01679 01680 if (guid == NULL) 01681 { 01682 _DBUS_LOCK (shared_connections); 01683 01684 if (!_dbus_list_prepend (&shared_connections_no_guid, connection)) 01685 { 01686 _DBUS_UNLOCK (shared_connections); 01687 return FALSE; 01688 } 01689 01690 _DBUS_UNLOCK (shared_connections); 01691 return TRUE; /* don't store in the hash */ 01692 } 01693 01694 /* A separate copy of the key is required in the hash table, because 01695 * we don't have a lock on the connection when we are doing a hash 01696 * lookup. 01697 */ 01698 01699 guid_key = _dbus_strdup (guid); 01700 if (guid_key == NULL) 01701 return FALSE; 01702 01703 guid_in_connection = _dbus_strdup (guid); 01704 if (guid_in_connection == NULL) 01705 { 01706 dbus_free (guid_key); 01707 return FALSE; 01708 } 01709 01710 _DBUS_LOCK (shared_connections); 01711 _dbus_assert (shared_connections != NULL); 01712 01713 if (!_dbus_hash_table_insert_string (shared_connections, 01714 guid_key, connection)) 01715 { 01716 dbus_free (guid_key); 01717 dbus_free (guid_in_connection); 01718 _DBUS_UNLOCK (shared_connections); 01719 return FALSE; 01720 } 01721 01722 connection->server_guid = guid_in_connection; 01723 01724 _dbus_verbose ("stored connection to %s to be shared\n", 01725 connection->server_guid); 01726 01727 _DBUS_UNLOCK (shared_connections); 01728 01729 _dbus_assert (connection->server_guid != NULL); 01730 01731 return TRUE; 01732 } 01733 01734 static void 01735 connection_forget_shared_unlocked (DBusConnection *connection) 01736 { 01737 HAVE_LOCK_CHECK (connection); 01738 01739 if (!connection->shareable) 01740 return; 01741 01742 _DBUS_LOCK (shared_connections); 01743 01744 if (connection->server_guid != NULL) 01745 { 01746 _dbus_verbose ("dropping connection to %s out of the shared table\n", 01747 connection->server_guid); 01748 01749 if (!_dbus_hash_table_remove_string (shared_connections, 01750 connection->server_guid)) 01751 _dbus_assert_not_reached ("connection was not in the shared table"); 01752 01753 dbus_free (connection->server_guid); 01754 connection->server_guid = NULL; 01755 } 01756 else 01757 { 01758 _dbus_list_remove (&shared_connections_no_guid, connection); 01759 } 01760 01761 _DBUS_UNLOCK (shared_connections); 01762 01763 /* remove our reference held on all shareable connections */ 01764 _dbus_connection_unref_unlocked (connection); 01765 } 01766 01767 static DBusConnection* 01768 connection_try_from_address_entry (DBusAddressEntry *entry, 01769 DBusError *error) 01770 { 01771 DBusTransport *transport; 01772 DBusConnection *connection; 01773 01774 transport = _dbus_transport_open (entry, error); 01775 01776 if (transport == NULL) 01777 { 01778 _DBUS_ASSERT_ERROR_IS_SET (error); 01779 return NULL; 01780 } 01781 01782 connection = _dbus_connection_new_for_transport (transport); 01783 01784 _dbus_transport_unref (transport); 01785 01786 if (connection == NULL) 01787 { 01788 _DBUS_SET_OOM (error); 01789 return NULL; 01790 } 01791 01792 #ifndef DBUS_DISABLE_CHECKS 01793 _dbus_assert (!connection->have_connection_lock); 01794 #endif 01795 return connection; 01796 } 01797 01798 /* 01799 * If the shared parameter is true, then any existing connection will 01800 * be used (and if a new connection is created, it will be available 01801 * for use by others). If the shared parameter is false, a new 01802 * connection will always be created, and the new connection will 01803 * never be returned to other callers. 01804 * 01805 * @param address the address 01806 * @param shared whether the connection is shared or private 01807 * @param error error return 01808 * @returns the connection or #NULL on error 01809 */ 01810 static DBusConnection* 01811 _dbus_connection_open_internal (const char *address, 01812 dbus_bool_t shared, 01813 DBusError *error) 01814 { 01815 DBusConnection *connection; 01816 DBusAddressEntry **entries; 01817 DBusError tmp_error = DBUS_ERROR_INIT; 01818 DBusError first_error = DBUS_ERROR_INIT; 01819 int len, i; 01820 01821 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01822 01823 _dbus_verbose ("opening %s connection to: %s\n", 01824 shared ? "shared" : "private", address); 01825 01826 if (!dbus_parse_address (address, &entries, &len, error)) 01827 return NULL; 01828 01829 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01830 01831 connection = NULL; 01832 01833 for (i = 0; i < len; i++) 01834 { 01835 if (shared) 01836 { 01837 if (!connection_lookup_shared (entries[i], &connection)) 01838 _DBUS_SET_OOM (&tmp_error); 01839 } 01840 01841 if (connection == NULL) 01842 { 01843 connection = connection_try_from_address_entry (entries[i], 01844 &tmp_error); 01845 01846 if (connection != NULL && shared) 01847 { 01848 const char *guid; 01849 01850 connection->shareable = TRUE; 01851 01852 /* guid may be NULL */ 01853 guid = dbus_address_entry_get_value (entries[i], "guid"); 01854 01855 CONNECTION_LOCK (connection); 01856 01857 if (!connection_record_shared_unlocked (connection, guid)) 01858 { 01859 _DBUS_SET_OOM (&tmp_error); 01860 _dbus_connection_close_possibly_shared_and_unlock (connection); 01861 dbus_connection_unref (connection); 01862 connection = NULL; 01863 } 01864 else 01865 CONNECTION_UNLOCK (connection); 01866 } 01867 } 01868 01869 if (connection) 01870 break; 01871 01872 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 01873 01874 if (i == 0) 01875 dbus_move_error (&tmp_error, &first_error); 01876 else 01877 dbus_error_free (&tmp_error); 01878 } 01879 01880 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01881 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 01882 01883 if (connection == NULL) 01884 { 01885 _DBUS_ASSERT_ERROR_IS_SET (&first_error); 01886 dbus_move_error (&first_error, error); 01887 } 01888 else 01889 dbus_error_free (&first_error); 01890 01891 dbus_address_entries_free (entries); 01892 return connection; 01893 } 01894 01903 void 01904 _dbus_connection_close_possibly_shared (DBusConnection *connection) 01905 { 01906 _dbus_assert (connection != NULL); 01907 _dbus_assert (connection->generation == _dbus_current_generation); 01908 01909 CONNECTION_LOCK (connection); 01910 _dbus_connection_close_possibly_shared_and_unlock (connection); 01911 } 01912 01913 static DBusPreallocatedSend* 01914 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection) 01915 { 01916 DBusPreallocatedSend *preallocated; 01917 01918 HAVE_LOCK_CHECK (connection); 01919 01920 _dbus_assert (connection != NULL); 01921 01922 preallocated = dbus_new (DBusPreallocatedSend, 1); 01923 if (preallocated == NULL) 01924 return NULL; 01925 01926 if (connection->link_cache != NULL) 01927 { 01928 preallocated->queue_link = 01929 _dbus_list_pop_first_link (&connection->link_cache); 01930 preallocated->queue_link->data = NULL; 01931 } 01932 else 01933 { 01934 preallocated->queue_link = _dbus_list_alloc_link (NULL); 01935 if (preallocated->queue_link == NULL) 01936 goto failed_0; 01937 } 01938 01939 if (connection->link_cache != NULL) 01940 { 01941 preallocated->counter_link = 01942 _dbus_list_pop_first_link (&connection->link_cache); 01943 preallocated->counter_link->data = connection->outgoing_counter; 01944 } 01945 else 01946 { 01947 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter); 01948 if (preallocated->counter_link == NULL) 01949 goto failed_1; 01950 } 01951 01952 _dbus_counter_ref (preallocated->counter_link->data); 01953 01954 preallocated->connection = connection; 01955 01956 return preallocated; 01957 01958 failed_1: 01959 _dbus_list_free_link (preallocated->queue_link); 01960 failed_0: 01961 dbus_free (preallocated); 01962 01963 return NULL; 01964 } 01965 01966 /* Called with lock held, does not update dispatch status */ 01967 static void 01968 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection, 01969 DBusPreallocatedSend *preallocated, 01970 DBusMessage *message, 01971 dbus_uint32_t *client_serial) 01972 { 01973 dbus_uint32_t serial; 01974 01975 preallocated->queue_link->data = message; 01976 _dbus_list_prepend_link (&connection->outgoing_messages, 01977 preallocated->queue_link); 01978 01979 _dbus_message_add_counter_link (message, 01980 preallocated->counter_link); 01981 01982 dbus_free (preallocated); 01983 preallocated = NULL; 01984 01985 dbus_message_ref (message); 01986 01987 connection->n_outgoing += 1; 01988 01989 _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n", 01990 message, 01991 dbus_message_type_to_string (dbus_message_get_type (message)), 01992 dbus_message_get_path (message) ? 01993 dbus_message_get_path (message) : 01994 "no path", 01995 dbus_message_get_interface (message) ? 01996 dbus_message_get_interface (message) : 01997 "no interface", 01998 dbus_message_get_member (message) ? 01999 dbus_message_get_member (message) : 02000 "no member", 02001 dbus_message_get_signature (message), 02002 dbus_message_get_destination (message) ? 02003 dbus_message_get_destination (message) : 02004 "null", 02005 connection, 02006 connection->n_outgoing); 02007 02008 if (dbus_message_get_serial (message) == 0) 02009 { 02010 serial = _dbus_connection_get_next_client_serial (connection); 02011 dbus_message_set_serial (message, serial); 02012 if (client_serial) 02013 *client_serial = serial; 02014 } 02015 else 02016 { 02017 if (client_serial) 02018 *client_serial = dbus_message_get_serial (message); 02019 } 02020 02021 _dbus_verbose ("Message %p serial is %u\n", 02022 message, dbus_message_get_serial (message)); 02023 02024 dbus_message_lock (message); 02025 02026 /* Now we need to run an iteration to hopefully just write the messages 02027 * out immediately, and otherwise get them queued up 02028 */ 02029 _dbus_connection_do_iteration_unlocked (connection, 02030 NULL, 02031 DBUS_ITERATION_DO_WRITING, 02032 -1); 02033 02034 /* If stuff is still queued up, be sure we wake up the main loop */ 02035 if (connection->n_outgoing > 0) 02036 _dbus_connection_wakeup_mainloop (connection); 02037 } 02038 02039 static void 02040 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection, 02041 DBusPreallocatedSend *preallocated, 02042 DBusMessage *message, 02043 dbus_uint32_t *client_serial) 02044 { 02045 DBusDispatchStatus status; 02046 02047 HAVE_LOCK_CHECK (connection); 02048 02049 _dbus_connection_send_preallocated_unlocked_no_update (connection, 02050 preallocated, 02051 message, client_serial); 02052 02053 _dbus_verbose ("middle\n"); 02054 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02055 02056 /* this calls out to user code */ 02057 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02058 } 02059 02069 dbus_bool_t 02070 _dbus_connection_send_and_unlock (DBusConnection *connection, 02071 DBusMessage *message, 02072 dbus_uint32_t *client_serial) 02073 { 02074 DBusPreallocatedSend *preallocated; 02075 02076 _dbus_assert (connection != NULL); 02077 _dbus_assert (message != NULL); 02078 02079 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 02080 if (preallocated == NULL) 02081 { 02082 CONNECTION_UNLOCK (connection); 02083 return FALSE; 02084 } 02085 02086 _dbus_connection_send_preallocated_and_unlock (connection, 02087 preallocated, 02088 message, 02089 client_serial); 02090 return TRUE; 02091 } 02092 02117 void 02118 _dbus_connection_close_if_only_one_ref (DBusConnection *connection) 02119 { 02120 dbus_int32_t refcount; 02121 02122 CONNECTION_LOCK (connection); 02123 02124 refcount = _dbus_atomic_get (&connection->refcount); 02125 /* The caller should have at least one ref */ 02126 _dbus_assert (refcount >= 1); 02127 02128 if (refcount == 1) 02129 _dbus_connection_close_possibly_shared_and_unlock (connection); 02130 else 02131 CONNECTION_UNLOCK (connection); 02132 } 02133 02134 02144 static void 02145 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds) 02146 { 02147 if (timeout_milliseconds == -1) 02148 _dbus_sleep_milliseconds (1000); 02149 else if (timeout_milliseconds < 100) 02150 ; /* just busy loop */ 02151 else if (timeout_milliseconds <= 1000) 02152 _dbus_sleep_milliseconds (timeout_milliseconds / 3); 02153 else 02154 _dbus_sleep_milliseconds (1000); 02155 } 02156 02157 static DBusMessage * 02158 generate_local_error_message (dbus_uint32_t serial, 02159 char *error_name, 02160 char *error_msg) 02161 { 02162 DBusMessage *message; 02163 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR); 02164 if (!message) 02165 goto out; 02166 02167 if (!dbus_message_set_error_name (message, error_name)) 02168 { 02169 dbus_message_unref (message); 02170 message = NULL; 02171 goto out; 02172 } 02173 02174 dbus_message_set_no_reply (message, TRUE); 02175 02176 if (!dbus_message_set_reply_serial (message, 02177 serial)) 02178 { 02179 dbus_message_unref (message); 02180 message = NULL; 02181 goto out; 02182 } 02183 02184 if (error_msg != NULL) 02185 { 02186 DBusMessageIter iter; 02187 02188 dbus_message_iter_init_append (message, &iter); 02189 if (!dbus_message_iter_append_basic (&iter, 02190 DBUS_TYPE_STRING, 02191 &error_msg)) 02192 { 02193 dbus_message_unref (message); 02194 message = NULL; 02195 goto out; 02196 } 02197 } 02198 02199 out: 02200 return message; 02201 } 02202 02203 /* 02204 * Peek the incoming queue to see if we got reply for a specific serial 02205 */ 02206 static dbus_bool_t 02207 _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection, 02208 dbus_uint32_t client_serial) 02209 { 02210 DBusList *link; 02211 HAVE_LOCK_CHECK (connection); 02212 02213 link = _dbus_list_get_first_link (&connection->incoming_messages); 02214 02215 while (link != NULL) 02216 { 02217 DBusMessage *reply = link->data; 02218 02219 if (dbus_message_get_reply_serial (reply) == client_serial) 02220 { 02221 _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial); 02222 return TRUE; 02223 } 02224 link = _dbus_list_get_next_link (&connection->incoming_messages, link); 02225 } 02226 02227 return FALSE; 02228 } 02229 02230 /* This is slightly strange since we can pop a message here without 02231 * the dispatch lock. 02232 */ 02233 static DBusMessage* 02234 check_for_reply_unlocked (DBusConnection *connection, 02235 dbus_uint32_t client_serial) 02236 { 02237 DBusList *link; 02238 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_list_remove_link (&connection->incoming_messages, link); 02250 connection->n_incoming -= 1; 02251 return reply; 02252 } 02253 link = _dbus_list_get_next_link (&connection->incoming_messages, link); 02254 } 02255 02256 return NULL; 02257 } 02258 02259 static void 02260 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection) 02261 { 02262 /* We can't iterate over the hash in the normal way since we'll be 02263 * dropping the lock for each item. So we restart the 02264 * iter each time as we drain the hash table. 02265 */ 02266 02267 while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0) 02268 { 02269 DBusPendingCall *pending; 02270 DBusHashIter iter; 02271 02272 _dbus_hash_iter_init (connection->pending_replies, &iter); 02273 _dbus_hash_iter_next (&iter); 02274 02275 pending = _dbus_hash_iter_get_value (&iter); 02276 _dbus_pending_call_ref_unlocked (pending); 02277 02278 _dbus_pending_call_queue_timeout_error_unlocked (pending, 02279 connection); 02280 02281 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 02282 _dbus_connection_remove_timeout_unlocked (connection, 02283 _dbus_pending_call_get_timeout_unlocked (pending)); 02284 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 02285 _dbus_hash_iter_remove_entry (&iter); 02286 02287 _dbus_pending_call_unref_and_unlock (pending); 02288 CONNECTION_LOCK (connection); 02289 } 02290 HAVE_LOCK_CHECK (connection); 02291 } 02292 02293 static void 02294 complete_pending_call_and_unlock (DBusConnection *connection, 02295 DBusPendingCall *pending, 02296 DBusMessage *message) 02297 { 02298 _dbus_pending_call_set_reply_unlocked (pending, message); 02299 _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */ 02300 _dbus_connection_detach_pending_call_and_unlock (connection, pending); 02301 02302 /* Must be called unlocked since it invokes app callback */ 02303 _dbus_pending_call_complete (pending); 02304 dbus_pending_call_unref (pending); 02305 } 02306 02307 static dbus_bool_t 02308 check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection, 02309 DBusPendingCall *pending) 02310 { 02311 DBusMessage *reply; 02312 DBusDispatchStatus status; 02313 02314 reply = check_for_reply_unlocked (connection, 02315 _dbus_pending_call_get_reply_serial_unlocked (pending)); 02316 if (reply != NULL) 02317 { 02318 _dbus_verbose ("checked for reply\n"); 02319 02320 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n"); 02321 02322 complete_pending_call_and_unlock (connection, pending, reply); 02323 dbus_message_unref (reply); 02324 02325 CONNECTION_LOCK (connection); 02326 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02327 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02328 dbus_pending_call_unref (pending); 02329 02330 return TRUE; 02331 } 02332 02333 return FALSE; 02334 } 02335 02350 void 02351 _dbus_connection_block_pending_call (DBusPendingCall *pending) 02352 { 02353 long start_tv_sec, start_tv_usec; 02354 long tv_sec, tv_usec; 02355 DBusDispatchStatus status; 02356 DBusConnection *connection; 02357 dbus_uint32_t client_serial; 02358 DBusTimeout *timeout; 02359 int timeout_milliseconds, elapsed_milliseconds; 02360 02361 _dbus_assert (pending != NULL); 02362 02363 if (dbus_pending_call_get_completed (pending)) 02364 return; 02365 02366 dbus_pending_call_ref (pending); /* necessary because the call could be canceled */ 02367 02368 connection = _dbus_pending_call_get_connection_and_lock (pending); 02369 02370 /* Flush message queue - note, can affect dispatch status */ 02371 _dbus_connection_flush_unlocked (connection); 02372 02373 client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending); 02374 02375 /* note that timeout_milliseconds is limited to a smallish value 02376 * in _dbus_pending_call_new() so overflows aren't possible 02377 * below 02378 */ 02379 timeout = _dbus_pending_call_get_timeout_unlocked (pending); 02380 _dbus_get_current_time (&start_tv_sec, &start_tv_usec); 02381 if (timeout) 02382 { 02383 timeout_milliseconds = dbus_timeout_get_interval (timeout); 02384 02385 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n", 02386 timeout_milliseconds, 02387 client_serial, 02388 start_tv_sec, start_tv_usec); 02389 } 02390 else 02391 { 02392 timeout_milliseconds = -1; 02393 02394 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial); 02395 } 02396 02397 /* check to see if we already got the data off the socket */ 02398 /* from another blocked pending call */ 02399 if (check_for_reply_and_update_dispatch_unlocked (connection, pending)) 02400 return; 02401 02402 /* Now we wait... */ 02403 /* always block at least once as we know we don't have the reply yet */ 02404 _dbus_connection_do_iteration_unlocked (connection, 02405 pending, 02406 DBUS_ITERATION_DO_READING | 02407 DBUS_ITERATION_BLOCK, 02408 timeout_milliseconds); 02409 02410 recheck_status: 02411 02412 _dbus_verbose ("top of recheck\n"); 02413 02414 HAVE_LOCK_CHECK (connection); 02415 02416 /* queue messages and get status */ 02417 02418 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02419 02420 /* the get_completed() is in case a dispatch() while we were blocking 02421 * got the reply instead of us. 02422 */ 02423 if (_dbus_pending_call_get_completed_unlocked (pending)) 02424 { 02425 _dbus_verbose ("Pending call completed by dispatch\n"); 02426 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02427 dbus_pending_call_unref (pending); 02428 return; 02429 } 02430 02431 if (status == DBUS_DISPATCH_DATA_REMAINS) 02432 { 02433 if (check_for_reply_and_update_dispatch_unlocked (connection, pending)) 02434 return; 02435 } 02436 02437 _dbus_get_current_time (&tv_sec, &tv_usec); 02438 elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 + 02439 (tv_usec - start_tv_usec) / 1000; 02440 02441 if (!_dbus_connection_get_is_connected_unlocked (connection)) 02442 { 02443 DBusMessage *error_msg; 02444 02445 error_msg = generate_local_error_message (client_serial, 02446 DBUS_ERROR_DISCONNECTED, 02447 "Connection was disconnected before a reply was received"); 02448 02449 /* on OOM error_msg is set to NULL */ 02450 complete_pending_call_and_unlock (connection, pending, error_msg); 02451 dbus_pending_call_unref (pending); 02452 return; 02453 } 02454 else if (connection->disconnect_message_link == NULL) 02455 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n"); 02456 else if (timeout == NULL) 02457 { 02458 if (status == DBUS_DISPATCH_NEED_MEMORY) 02459 { 02460 /* Try sleeping a bit, as we aren't sure we need to block for reading, 02461 * we may already have a reply in the buffer and just can't process 02462 * it. 02463 */ 02464 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n"); 02465 02466 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds); 02467 } 02468 else 02469 { 02470 /* block again, we don't have the reply buffered yet. */ 02471 _dbus_connection_do_iteration_unlocked (connection, 02472 pending, 02473 DBUS_ITERATION_DO_READING | 02474 DBUS_ITERATION_BLOCK, 02475 timeout_milliseconds - elapsed_milliseconds); 02476 } 02477 02478 goto recheck_status; 02479 } 02480 else if (tv_sec < start_tv_sec) 02481 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n"); 02482 else if (elapsed_milliseconds < timeout_milliseconds) 02483 { 02484 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds); 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 NULL, 02501 DBUS_ITERATION_DO_READING | 02502 DBUS_ITERATION_BLOCK, 02503 timeout_milliseconds - elapsed_milliseconds); 02504 } 02505 02506 goto recheck_status; 02507 } 02508 02509 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n", 02510 elapsed_milliseconds); 02511 02512 _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending)); 02513 02514 /* unlock and call user code */ 02515 complete_pending_call_and_unlock (connection, pending, NULL); 02516 02517 /* update user code on dispatch status */ 02518 CONNECTION_LOCK (connection); 02519 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02520 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02521 dbus_pending_call_unref (pending); 02522 } 02523 02529 int 02530 _dbus_connection_get_pending_fds_count (DBusConnection *connection) 02531 { 02532 return _dbus_transport_get_pending_fds_count (connection->transport); 02533 } 02534 02542 void 02543 _dbus_connection_set_pending_fds_function (DBusConnection *connection, 02544 DBusPendingFdsChangeFunction callback, 02545 void *data) 02546 { 02547 _dbus_transport_set_pending_fds_function (connection->transport, 02548 callback, data); 02549 } 02550 02587 DBusConnection* 02588 dbus_connection_open (const char *address, 02589 DBusError *error) 02590 { 02591 DBusConnection *connection; 02592 02593 _dbus_return_val_if_fail (address != NULL, NULL); 02594 _dbus_return_val_if_error_is_set (error, NULL); 02595 02596 connection = _dbus_connection_open_internal (address, 02597 TRUE, 02598 error); 02599 02600 return connection; 02601 } 02602 02630 DBusConnection* 02631 dbus_connection_open_private (const char *address, 02632 DBusError *error) 02633 { 02634 DBusConnection *connection; 02635 02636 _dbus_return_val_if_fail (address != NULL, NULL); 02637 _dbus_return_val_if_error_is_set (error, NULL); 02638 02639 connection = _dbus_connection_open_internal (address, 02640 FALSE, 02641 error); 02642 02643 return connection; 02644 } 02645 02652 DBusConnection * 02653 dbus_connection_ref (DBusConnection *connection) 02654 { 02655 _dbus_return_val_if_fail (connection != NULL, NULL); 02656 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL); 02657 02658 _dbus_atomic_inc (&connection->refcount); 02659 02660 return connection; 02661 } 02662 02663 static void 02664 free_outgoing_message (void *element, 02665 void *data) 02666 { 02667 DBusMessage *message = element; 02668 DBusConnection *connection = data; 02669 02670 _dbus_message_remove_counter (message, 02671 connection->outgoing_counter, 02672 NULL); 02673 dbus_message_unref (message); 02674 } 02675 02676 /* This is run without the mutex held, but after the last reference 02677 * to the connection has been dropped we should have no thread-related 02678 * problems 02679 */ 02680 static void 02681 _dbus_connection_last_unref (DBusConnection *connection) 02682 { 02683 DBusList *link; 02684 02685 _dbus_verbose ("Finalizing connection %p\n", connection); 02686 02687 _dbus_assert (_dbus_atomic_get (&connection->refcount) == 0); 02688 02689 /* You have to disconnect the connection before unref:ing it. Otherwise 02690 * you won't get the disconnected message. 02691 */ 02692 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport)); 02693 _dbus_assert (connection->server_guid == NULL); 02694 02695 /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */ 02696 _dbus_object_tree_free_all_unlocked (connection->objects); 02697 02698 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL); 02699 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL); 02700 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL); 02701 02702 _dbus_watch_list_free (connection->watches); 02703 connection->watches = NULL; 02704 02705 _dbus_timeout_list_free (connection->timeouts); 02706 connection->timeouts = NULL; 02707 02708 _dbus_data_slot_list_free (&connection->slot_list); 02709 02710 link = _dbus_list_get_first_link (&connection->filter_list); 02711 while (link != NULL) 02712 { 02713 DBusMessageFilter *filter = link->data; 02714 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link); 02715 02716 filter->function = NULL; 02717 _dbus_message_filter_unref (filter); /* calls app callback */ 02718 link->data = NULL; 02719 02720 link = next; 02721 } 02722 _dbus_list_clear (&connection->filter_list); 02723 02724 /* ---- Done with stuff that invokes application callbacks */ 02725 02726 _dbus_object_tree_unref (connection->objects); 02727 02728 _dbus_hash_table_unref (connection->pending_replies); 02729 connection->pending_replies = NULL; 02730 02731 _dbus_list_clear (&connection->filter_list); 02732 02733 _dbus_list_foreach (&connection->outgoing_messages, 02734 free_outgoing_message, 02735 connection); 02736 _dbus_list_clear (&connection->outgoing_messages); 02737 02738 _dbus_list_foreach (&connection->incoming_messages, 02739 (DBusForeachFunction) dbus_message_unref, 02740 NULL); 02741 _dbus_list_clear (&connection->incoming_messages); 02742 02743 _dbus_counter_unref (connection->outgoing_counter); 02744 02745 _dbus_transport_unref (connection->transport); 02746 02747 if (connection->disconnect_message_link) 02748 { 02749 DBusMessage *message = connection->disconnect_message_link->data; 02750 dbus_message_unref (message); 02751 _dbus_list_free_link (connection->disconnect_message_link); 02752 } 02753 02754 _dbus_list_clear (&connection->link_cache); 02755 02756 _dbus_condvar_free_at_location (&connection->dispatch_cond); 02757 _dbus_condvar_free_at_location (&connection->io_path_cond); 02758 02759 _dbus_mutex_free_at_location (&connection->io_path_mutex); 02760 _dbus_mutex_free_at_location (&connection->dispatch_mutex); 02761 02762 _dbus_mutex_free_at_location (&connection->slot_mutex); 02763 02764 _dbus_mutex_free_at_location (&connection->mutex); 02765 02766 dbus_free (connection); 02767 } 02768 02788 void 02789 dbus_connection_unref (DBusConnection *connection) 02790 { 02791 dbus_bool_t last_unref; 02792 02793 _dbus_return_if_fail (connection != NULL); 02794 _dbus_return_if_fail (connection->generation == _dbus_current_generation); 02795 02796 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1); 02797 02798 if (last_unref) 02799 { 02800 #ifndef DBUS_DISABLE_CHECKS 02801 if (_dbus_transport_get_is_connected (connection->transport)) 02802 { 02803 _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", 02804 connection->shareable ? 02805 "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" : 02806 "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n"); 02807 return; 02808 } 02809 #endif 02810 _dbus_connection_last_unref (connection); 02811 } 02812 } 02813 02814 /* 02815 * Note that the transport can disconnect itself (other end drops us) 02816 * and in that case this function never runs. So this function must 02817 * not do anything more than disconnect the transport and update the 02818 * dispatch status. 02819 * 02820 * If the transport self-disconnects, then we assume someone will 02821 * dispatch the connection to cause the dispatch status update. 02822 */ 02823 static void 02824 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection) 02825 { 02826 DBusDispatchStatus status; 02827 02828 HAVE_LOCK_CHECK (connection); 02829 02830 _dbus_verbose ("Disconnecting %p\n", connection); 02831 02832 /* We need to ref because update_dispatch_status_and_unlock will unref 02833 * the connection if it was shared and libdbus was the only remaining 02834 * refcount holder. 02835 */ 02836 _dbus_connection_ref_unlocked (connection); 02837 02838 _dbus_transport_disconnect (connection->transport); 02839 02840 /* This has the side effect of queuing the disconnect message link 02841 * (unless we don't have enough memory, possibly, so don't assert it). 02842 * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open 02843 * should never again return the newly-disconnected connection. 02844 * 02845 * However, we only unref the shared connection and exit_on_disconnect when 02846 * the disconnect message reaches the head of the message queue, 02847 * NOT when it's first queued. 02848 */ 02849 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02850 02851 /* This calls out to user code */ 02852 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02853 02854 /* Could also call out to user code */ 02855 dbus_connection_unref (connection); 02856 } 02857 02900 void 02901 dbus_connection_close (DBusConnection *connection) 02902 { 02903 _dbus_return_if_fail (connection != NULL); 02904 _dbus_return_if_fail (connection->generation == _dbus_current_generation); 02905 02906 CONNECTION_LOCK (connection); 02907 02908 #ifndef DBUS_DISABLE_CHECKS 02909 if (connection->shareable) 02910 { 02911 CONNECTION_UNLOCK (connection); 02912 02913 _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n"); 02914 return; 02915 } 02916 #endif 02917 02918 _dbus_connection_close_possibly_shared_and_unlock (connection); 02919 } 02920 02921 static dbus_bool_t 02922 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection) 02923 { 02924 HAVE_LOCK_CHECK (connection); 02925 return _dbus_transport_get_is_connected (connection->transport); 02926 } 02927 02941 dbus_bool_t 02942 dbus_connection_get_is_connected (DBusConnection *connection) 02943 { 02944 dbus_bool_t res; 02945 02946 _dbus_return_val_if_fail (connection != NULL, FALSE); 02947 02948 CONNECTION_LOCK (connection); 02949 res = _dbus_connection_get_is_connected_unlocked (connection); 02950 CONNECTION_UNLOCK (connection); 02951 02952 return res; 02953 } 02954 02963 dbus_bool_t 02964 dbus_connection_get_is_authenticated (DBusConnection *connection) 02965 { 02966 dbus_bool_t res; 02967 02968 _dbus_return_val_if_fail (connection != NULL, FALSE); 02969 02970 CONNECTION_LOCK (connection); 02971 res = _dbus_transport_get_is_authenticated (connection->transport); 02972 CONNECTION_UNLOCK (connection); 02973 02974 return res; 02975 } 02976 02997 dbus_bool_t 02998 dbus_connection_get_is_anonymous (DBusConnection *connection) 02999 { 03000 dbus_bool_t res; 03001 03002 _dbus_return_val_if_fail (connection != NULL, FALSE); 03003 03004 CONNECTION_LOCK (connection); 03005 res = _dbus_transport_get_is_anonymous (connection->transport); 03006 CONNECTION_UNLOCK (connection); 03007 03008 return res; 03009 } 03010 03042 char* 03043 dbus_connection_get_server_id (DBusConnection *connection) 03044 { 03045 char *id; 03046 03047 _dbus_return_val_if_fail (connection != NULL, NULL); 03048 03049 CONNECTION_LOCK (connection); 03050 id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport)); 03051 CONNECTION_UNLOCK (connection); 03052 03053 return id; 03054 } 03055 03073 dbus_bool_t 03074 dbus_connection_can_send_type(DBusConnection *connection, 03075 int type) 03076 { 03077 _dbus_return_val_if_fail (connection != NULL, FALSE); 03078 03079 if (!_dbus_type_is_valid(type)) 03080 return FALSE; 03081 03082 if (type != DBUS_TYPE_UNIX_FD) 03083 return TRUE; 03084 03085 #ifdef HAVE_UNIX_FD_PASSING 03086 { 03087 dbus_bool_t b; 03088 03089 CONNECTION_LOCK(connection); 03090 b = _dbus_transport_can_pass_unix_fd(connection->transport); 03091 CONNECTION_UNLOCK(connection); 03092 03093 return b; 03094 } 03095 #endif 03096 03097 return FALSE; 03098 } 03099 03113 void 03114 dbus_connection_set_exit_on_disconnect (DBusConnection *connection, 03115 dbus_bool_t exit_on_disconnect) 03116 { 03117 _dbus_return_if_fail (connection != NULL); 03118 03119 CONNECTION_LOCK (connection); 03120 connection->exit_on_disconnect = exit_on_disconnect != FALSE; 03121 CONNECTION_UNLOCK (connection); 03122 } 03123 03133 DBusPreallocatedSend* 03134 dbus_connection_preallocate_send (DBusConnection *connection) 03135 { 03136 DBusPreallocatedSend *preallocated; 03137 03138 _dbus_return_val_if_fail (connection != NULL, NULL); 03139 03140 CONNECTION_LOCK (connection); 03141 03142 preallocated = 03143 _dbus_connection_preallocate_send_unlocked (connection); 03144 03145 CONNECTION_UNLOCK (connection); 03146 03147 return preallocated; 03148 } 03149 03159 void 03160 dbus_connection_free_preallocated_send (DBusConnection *connection, 03161 DBusPreallocatedSend *preallocated) 03162 { 03163 _dbus_return_if_fail (connection != NULL); 03164 _dbus_return_if_fail (preallocated != NULL); 03165 _dbus_return_if_fail (connection == preallocated->connection); 03166 03167 _dbus_list_free_link (preallocated->queue_link); 03168 _dbus_counter_unref (preallocated->counter_link->data); 03169 _dbus_list_free_link (preallocated->counter_link); 03170 dbus_free (preallocated); 03171 } 03172 03185 void 03186 dbus_connection_send_preallocated (DBusConnection *connection, 03187 DBusPreallocatedSend *preallocated, 03188 DBusMessage *message, 03189 dbus_uint32_t *client_serial) 03190 { 03191 _dbus_return_if_fail (connection != NULL); 03192 _dbus_return_if_fail (preallocated != NULL); 03193 _dbus_return_if_fail (message != NULL); 03194 _dbus_return_if_fail (preallocated->connection == connection); 03195 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL || 03196 dbus_message_get_member (message) != NULL); 03197 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL || 03198 (dbus_message_get_interface (message) != NULL && 03199 dbus_message_get_member (message) != NULL)); 03200 03201 CONNECTION_LOCK (connection); 03202 03203 #ifdef HAVE_UNIX_FD_PASSING 03204 03205 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03206 message->n_unix_fds > 0) 03207 { 03208 /* Refuse to send fds on a connection that cannot handle 03209 them. Unfortunately we cannot return a proper error here, so 03210 the best we can is just return. */ 03211 CONNECTION_UNLOCK (connection); 03212 return; 03213 } 03214 03215 #endif 03216 03217 _dbus_connection_send_preallocated_and_unlock (connection, 03218 preallocated, 03219 message, client_serial); 03220 } 03221 03222 static dbus_bool_t 03223 _dbus_connection_send_unlocked_no_update (DBusConnection *connection, 03224 DBusMessage *message, 03225 dbus_uint32_t *client_serial) 03226 { 03227 DBusPreallocatedSend *preallocated; 03228 03229 _dbus_assert (connection != NULL); 03230 _dbus_assert (message != NULL); 03231 03232 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 03233 if (preallocated == NULL) 03234 return FALSE; 03235 03236 _dbus_connection_send_preallocated_unlocked_no_update (connection, 03237 preallocated, 03238 message, 03239 client_serial); 03240 return TRUE; 03241 } 03242 03270 dbus_bool_t 03271 dbus_connection_send (DBusConnection *connection, 03272 DBusMessage *message, 03273 dbus_uint32_t *serial) 03274 { 03275 _dbus_return_val_if_fail (connection != NULL, FALSE); 03276 _dbus_return_val_if_fail (message != NULL, FALSE); 03277 03278 CONNECTION_LOCK (connection); 03279 03280 #ifdef HAVE_UNIX_FD_PASSING 03281 03282 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03283 message->n_unix_fds > 0) 03284 { 03285 /* Refuse to send fds on a connection that cannot handle 03286 them. Unfortunately we cannot return a proper error here, so 03287 the best we can is just return. */ 03288 CONNECTION_UNLOCK (connection); 03289 return FALSE; 03290 } 03291 03292 #endif 03293 03294 return _dbus_connection_send_and_unlock (connection, 03295 message, 03296 serial); 03297 } 03298 03299 static dbus_bool_t 03300 reply_handler_timeout (void *data) 03301 { 03302 DBusConnection *connection; 03303 DBusDispatchStatus status; 03304 DBusPendingCall *pending = data; 03305 03306 connection = _dbus_pending_call_get_connection_and_lock (pending); 03307 03308 _dbus_pending_call_queue_timeout_error_unlocked (pending, 03309 connection); 03310 _dbus_connection_remove_timeout_unlocked (connection, 03311 _dbus_pending_call_get_timeout_unlocked (pending)); 03312 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 03313 03314 _dbus_verbose ("middle\n"); 03315 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03316 03317 /* Unlocks, and calls out to user code */ 03318 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03319 03320 return TRUE; 03321 } 03322 03365 dbus_bool_t 03366 dbus_connection_send_with_reply (DBusConnection *connection, 03367 DBusMessage *message, 03368 DBusPendingCall **pending_return, 03369 int timeout_milliseconds) 03370 { 03371 DBusPendingCall *pending; 03372 dbus_int32_t serial = -1; 03373 DBusDispatchStatus status; 03374 03375 _dbus_return_val_if_fail (connection != NULL, FALSE); 03376 _dbus_return_val_if_fail (message != NULL, FALSE); 03377 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03378 03379 if (pending_return) 03380 *pending_return = NULL; 03381 03382 CONNECTION_LOCK (connection); 03383 03384 #ifdef HAVE_UNIX_FD_PASSING 03385 03386 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03387 message->n_unix_fds > 0) 03388 { 03389 /* Refuse to send fds on a connection that cannot handle 03390 them. Unfortunately we cannot return a proper error here, so 03391 the best we can do is return TRUE but leave *pending_return 03392 as NULL. */ 03393 CONNECTION_UNLOCK (connection); 03394 return TRUE; 03395 } 03396 03397 #endif 03398 03399 if (!_dbus_connection_get_is_connected_unlocked (connection)) 03400 { 03401 CONNECTION_UNLOCK (connection); 03402 03403 return TRUE; 03404 } 03405 03406 pending = _dbus_pending_call_new_unlocked (connection, 03407 timeout_milliseconds, 03408 reply_handler_timeout); 03409 03410 if (pending == NULL) 03411 { 03412 CONNECTION_UNLOCK (connection); 03413 return FALSE; 03414 } 03415 03416 /* Assign a serial to the message */ 03417 serial = dbus_message_get_serial (message); 03418 if (serial == 0) 03419 { 03420 serial = _dbus_connection_get_next_client_serial (connection); 03421 dbus_message_set_serial (message, serial); 03422 } 03423 03424 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial)) 03425 goto error; 03426 03427 /* Insert the serial in the pending replies hash; 03428 * hash takes a refcount on DBusPendingCall. 03429 * Also, add the timeout. 03430 */ 03431 if (!_dbus_connection_attach_pending_call_unlocked (connection, 03432 pending)) 03433 goto error; 03434 03435 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL)) 03436 { 03437 _dbus_connection_detach_pending_call_and_unlock (connection, 03438 pending); 03439 goto error_unlocked; 03440 } 03441 03442 if (pending_return) 03443 *pending_return = pending; /* hand off refcount */ 03444 else 03445 { 03446 _dbus_connection_detach_pending_call_unlocked (connection, pending); 03447 /* we still have a ref to the pending call in this case, we unref 03448 * after unlocking, below 03449 */ 03450 } 03451 03452 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03453 03454 /* this calls out to user code */ 03455 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03456 03457 if (pending_return == NULL) 03458 dbus_pending_call_unref (pending); 03459 03460 return TRUE; 03461 03462 error: 03463 CONNECTION_UNLOCK (connection); 03464 error_unlocked: 03465 dbus_pending_call_unref (pending); 03466 return FALSE; 03467 } 03468 03501 DBusMessage* 03502 dbus_connection_send_with_reply_and_block (DBusConnection *connection, 03503 DBusMessage *message, 03504 int timeout_milliseconds, 03505 DBusError *error) 03506 { 03507 DBusMessage *reply; 03508 DBusPendingCall *pending; 03509 03510 _dbus_return_val_if_fail (connection != NULL, NULL); 03511 _dbus_return_val_if_fail (message != NULL, NULL); 03512 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL); 03513 _dbus_return_val_if_error_is_set (error, NULL); 03514 03515 #ifdef HAVE_UNIX_FD_PASSING 03516 03517 CONNECTION_LOCK (connection); 03518 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03519 message->n_unix_fds > 0) 03520 { 03521 CONNECTION_UNLOCK (connection); 03522 dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection."); 03523 return NULL; 03524 } 03525 CONNECTION_UNLOCK (connection); 03526 03527 #endif 03528 03529 if (!dbus_connection_send_with_reply (connection, message, 03530 &pending, timeout_milliseconds)) 03531 { 03532 _DBUS_SET_OOM (error); 03533 return NULL; 03534 } 03535 03536 if (pending == NULL) 03537 { 03538 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed"); 03539 return NULL; 03540 } 03541 03542 dbus_pending_call_block (pending); 03543 03544 reply = dbus_pending_call_steal_reply (pending); 03545 dbus_pending_call_unref (pending); 03546 03547 /* call_complete_and_unlock() called from pending_call_block() should 03548 * always fill this in. 03549 */ 03550 _dbus_assert (reply != NULL); 03551 03552 if (dbus_set_error_from_message (error, reply)) 03553 { 03554 dbus_message_unref (reply); 03555 return NULL; 03556 } 03557 else 03558 return reply; 03559 } 03560 03569 static DBusDispatchStatus 03570 _dbus_connection_flush_unlocked (DBusConnection *connection) 03571 { 03572 /* We have to specify DBUS_ITERATION_DO_READING here because 03573 * otherwise we could have two apps deadlock if they are both doing 03574 * a flush(), and the kernel buffers fill up. This could change the 03575 * dispatch status. 03576 */ 03577 DBusDispatchStatus status; 03578 03579 HAVE_LOCK_CHECK (connection); 03580 03581 while (connection->n_outgoing > 0 && 03582 _dbus_connection_get_is_connected_unlocked (connection)) 03583 { 03584 _dbus_verbose ("doing iteration in\n"); 03585 HAVE_LOCK_CHECK (connection); 03586 _dbus_connection_do_iteration_unlocked (connection, 03587 NULL, 03588 DBUS_ITERATION_DO_READING | 03589 DBUS_ITERATION_DO_WRITING | 03590 DBUS_ITERATION_BLOCK, 03591 -1); 03592 } 03593 03594 HAVE_LOCK_CHECK (connection); 03595 _dbus_verbose ("middle\n"); 03596 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03597 03598 HAVE_LOCK_CHECK (connection); 03599 return status; 03600 } 03601 03607 void 03608 dbus_connection_flush (DBusConnection *connection) 03609 { 03610 /* We have to specify DBUS_ITERATION_DO_READING here because 03611 * otherwise we could have two apps deadlock if they are both doing 03612 * a flush(), and the kernel buffers fill up. This could change the 03613 * dispatch status. 03614 */ 03615 DBusDispatchStatus status; 03616 03617 _dbus_return_if_fail (connection != NULL); 03618 03619 CONNECTION_LOCK (connection); 03620 03621 status = _dbus_connection_flush_unlocked (connection); 03622 03623 HAVE_LOCK_CHECK (connection); 03624 /* Unlocks and calls out to user code */ 03625 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03626 03627 _dbus_verbose ("end\n"); 03628 } 03629 03640 static dbus_bool_t 03641 _dbus_connection_read_write_dispatch (DBusConnection *connection, 03642 int timeout_milliseconds, 03643 dbus_bool_t dispatch) 03644 { 03645 DBusDispatchStatus dstatus; 03646 dbus_bool_t progress_possible; 03647 03648 /* Need to grab a ref here in case we're a private connection and 03649 * the user drops the last ref in a handler we call; see bug 03650 * https://bugs.freedesktop.org/show_bug.cgi?id=15635 03651 */ 03652 dbus_connection_ref (connection); 03653 dstatus = dbus_connection_get_dispatch_status (connection); 03654 03655 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS) 03656 { 03657 _dbus_verbose ("doing dispatch\n"); 03658 dbus_connection_dispatch (connection); 03659 CONNECTION_LOCK (connection); 03660 } 03661 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY) 03662 { 03663 _dbus_verbose ("pausing for memory\n"); 03664 _dbus_memory_pause_based_on_timeout (timeout_milliseconds); 03665 CONNECTION_LOCK (connection); 03666 } 03667 else 03668 { 03669 CONNECTION_LOCK (connection); 03670 if (_dbus_connection_get_is_connected_unlocked (connection)) 03671 { 03672 _dbus_verbose ("doing iteration\n"); 03673 _dbus_connection_do_iteration_unlocked (connection, 03674 NULL, 03675 DBUS_ITERATION_DO_READING | 03676 DBUS_ITERATION_DO_WRITING | 03677 DBUS_ITERATION_BLOCK, 03678 timeout_milliseconds); 03679 } 03680 } 03681 03682 HAVE_LOCK_CHECK (connection); 03683 /* If we can dispatch, we can make progress until the Disconnected message 03684 * has been processed; if we can only read/write, we can make progress 03685 * as long as the transport is open. 03686 */ 03687 if (dispatch) 03688 progress_possible = connection->n_incoming != 0 || 03689 connection->disconnect_message_link != NULL; 03690 else 03691 progress_possible = _dbus_connection_get_is_connected_unlocked (connection); 03692 03693 CONNECTION_UNLOCK (connection); 03694 03695 dbus_connection_unref (connection); 03696 03697 return progress_possible; /* TRUE if we can make more progress */ 03698 } 03699 03700 03735 dbus_bool_t 03736 dbus_connection_read_write_dispatch (DBusConnection *connection, 03737 int timeout_milliseconds) 03738 { 03739 _dbus_return_val_if_fail (connection != NULL, FALSE); 03740 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03741 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE); 03742 } 03743 03767 dbus_bool_t 03768 dbus_connection_read_write (DBusConnection *connection, 03769 int timeout_milliseconds) 03770 { 03771 _dbus_return_val_if_fail (connection != NULL, FALSE); 03772 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03773 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE); 03774 } 03775 03776 /* We need to call this anytime we pop the head of the queue, and then 03777 * update_dispatch_status_and_unlock needs to be called afterward 03778 * which will "process" the disconnected message and set 03779 * disconnected_message_processed. 03780 */ 03781 static void 03782 check_disconnected_message_arrived_unlocked (DBusConnection *connection, 03783 DBusMessage *head_of_queue) 03784 { 03785 HAVE_LOCK_CHECK (connection); 03786 03787 /* checking that the link is NULL is an optimization to avoid the is_signal call */ 03788 if (connection->disconnect_message_link == NULL && 03789 dbus_message_is_signal (head_of_queue, 03790 DBUS_INTERFACE_LOCAL, 03791 "Disconnected")) 03792 { 03793 connection->disconnected_message_arrived = TRUE; 03794 } 03795 } 03796 03816 DBusMessage* 03817 dbus_connection_borrow_message (DBusConnection *connection) 03818 { 03819 DBusDispatchStatus status; 03820 DBusMessage *message; 03821 03822 _dbus_return_val_if_fail (connection != NULL, NULL); 03823 03824 _dbus_verbose ("start\n"); 03825 03826 /* this is called for the side effect that it queues 03827 * up any messages from the transport 03828 */ 03829 status = dbus_connection_get_dispatch_status (connection); 03830 if (status != DBUS_DISPATCH_DATA_REMAINS) 03831 return NULL; 03832 03833 CONNECTION_LOCK (connection); 03834 03835 _dbus_connection_acquire_dispatch (connection); 03836 03837 /* While a message is outstanding, the dispatch lock is held */ 03838 _dbus_assert (connection->message_borrowed == NULL); 03839 03840 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages); 03841 03842 message = connection->message_borrowed; 03843 03844 check_disconnected_message_arrived_unlocked (connection, message); 03845 03846 /* Note that we KEEP the dispatch lock until the message is returned */ 03847 if (message == NULL) 03848 _dbus_connection_release_dispatch (connection); 03849 03850 CONNECTION_UNLOCK (connection); 03851 03852 /* We don't update dispatch status until it's returned or stolen */ 03853 03854 return message; 03855 } 03856 03865 void 03866 dbus_connection_return_message (DBusConnection *connection, 03867 DBusMessage *message) 03868 { 03869 DBusDispatchStatus status; 03870 03871 _dbus_return_if_fail (connection != NULL); 03872 _dbus_return_if_fail (message != NULL); 03873 _dbus_return_if_fail (message == connection->message_borrowed); 03874 _dbus_return_if_fail (connection->dispatch_acquired); 03875 03876 CONNECTION_LOCK (connection); 03877 03878 _dbus_assert (message == connection->message_borrowed); 03879 03880 connection->message_borrowed = NULL; 03881 03882 _dbus_connection_release_dispatch (connection); 03883 03884 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03885 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03886 } 03887 03897 void 03898 dbus_connection_steal_borrowed_message (DBusConnection *connection, 03899 DBusMessage *message) 03900 { 03901 DBusMessage *pop_message; 03902 DBusDispatchStatus status; 03903 03904 _dbus_return_if_fail (connection != NULL); 03905 _dbus_return_if_fail (message != NULL); 03906 _dbus_return_if_fail (message == connection->message_borrowed); 03907 _dbus_return_if_fail (connection->dispatch_acquired); 03908 03909 CONNECTION_LOCK (connection); 03910 03911 _dbus_assert (message == connection->message_borrowed); 03912 03913 pop_message = _dbus_list_pop_first (&connection->incoming_messages); 03914 _dbus_assert (message == pop_message); 03915 03916 connection->n_incoming -= 1; 03917 03918 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n", 03919 message, connection->n_incoming); 03920 03921 connection->message_borrowed = NULL; 03922 03923 _dbus_connection_release_dispatch (connection); 03924 03925 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03926 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03927 } 03928 03929 /* See dbus_connection_pop_message, but requires the caller to own 03930 * the lock before calling. May drop the lock while running. 03931 */ 03932 static DBusList* 03933 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection) 03934 { 03935 HAVE_LOCK_CHECK (connection); 03936 03937 _dbus_assert (connection->message_borrowed == NULL); 03938 03939 if (connection->n_incoming > 0) 03940 { 03941 DBusList *link; 03942 03943 link = _dbus_list_pop_first_link (&connection->incoming_messages); 03944 connection->n_incoming -= 1; 03945 03946 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from incoming queue %p, %d incoming\n", 03947 link->data, 03948 dbus_message_type_to_string (dbus_message_get_type (link->data)), 03949 dbus_message_get_path (link->data) ? 03950 dbus_message_get_path (link->data) : 03951 "no path", 03952 dbus_message_get_interface (link->data) ? 03953 dbus_message_get_interface (link->data) : 03954 "no interface", 03955 dbus_message_get_member (link->data) ? 03956 dbus_message_get_member (link->data) : 03957 "no member", 03958 dbus_message_get_signature (link->data), 03959 connection, connection->n_incoming); 03960 03961 check_disconnected_message_arrived_unlocked (connection, link->data); 03962 03963 return link; 03964 } 03965 else 03966 return NULL; 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 DBusMessage* 03973 _dbus_connection_pop_message_unlocked (DBusConnection *connection) 03974 { 03975 DBusList *link; 03976 03977 HAVE_LOCK_CHECK (connection); 03978 03979 link = _dbus_connection_pop_message_link_unlocked (connection); 03980 03981 if (link != NULL) 03982 { 03983 DBusMessage *message; 03984 03985 message = link->data; 03986 03987 _dbus_list_free_link (link); 03988 03989 return message; 03990 } 03991 else 03992 return NULL; 03993 } 03994 03995 static void 03996 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection, 03997 DBusList *message_link) 03998 { 03999 HAVE_LOCK_CHECK (connection); 04000 04001 _dbus_assert (message_link != NULL); 04002 /* You can't borrow a message while a link is outstanding */ 04003 _dbus_assert (connection->message_borrowed == NULL); 04004 /* We had to have the dispatch lock across the pop/putback */ 04005 _dbus_assert (connection->dispatch_acquired); 04006 04007 _dbus_list_prepend_link (&connection->incoming_messages, 04008 message_link); 04009 connection->n_incoming += 1; 04010 04011 _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n", 04012 message_link->data, 04013 dbus_message_type_to_string (dbus_message_get_type (message_link->data)), 04014 dbus_message_get_interface (message_link->data) ? 04015 dbus_message_get_interface (message_link->data) : 04016 "no interface", 04017 dbus_message_get_member (message_link->data) ? 04018 dbus_message_get_member (message_link->data) : 04019 "no member", 04020 dbus_message_get_signature (message_link->data), 04021 connection, connection->n_incoming); 04022 } 04023 04043 DBusMessage* 04044 dbus_connection_pop_message (DBusConnection *connection) 04045 { 04046 DBusMessage *message; 04047 DBusDispatchStatus status; 04048 04049 _dbus_verbose ("start\n"); 04050 04051 /* this is called for the side effect that it queues 04052 * up any messages from the transport 04053 */ 04054 status = dbus_connection_get_dispatch_status (connection); 04055 if (status != DBUS_DISPATCH_DATA_REMAINS) 04056 return NULL; 04057 04058 CONNECTION_LOCK (connection); 04059 _dbus_connection_acquire_dispatch (connection); 04060 HAVE_LOCK_CHECK (connection); 04061 04062 message = _dbus_connection_pop_message_unlocked (connection); 04063 04064 _dbus_verbose ("Returning popped message %p\n", message); 04065 04066 _dbus_connection_release_dispatch (connection); 04067 04068 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04069 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04070 04071 return message; 04072 } 04073 04081 static void 04082 _dbus_connection_acquire_dispatch (DBusConnection *connection) 04083 { 04084 HAVE_LOCK_CHECK (connection); 04085 04086 _dbus_connection_ref_unlocked (connection); 04087 CONNECTION_UNLOCK (connection); 04088 04089 _dbus_verbose ("locking dispatch_mutex\n"); 04090 _dbus_mutex_lock (connection->dispatch_mutex); 04091 04092 while (connection->dispatch_acquired) 04093 { 04094 _dbus_verbose ("waiting for dispatch to be acquirable\n"); 04095 _dbus_condvar_wait (connection->dispatch_cond, 04096 connection->dispatch_mutex); 04097 } 04098 04099 _dbus_assert (!connection->dispatch_acquired); 04100 04101 connection->dispatch_acquired = TRUE; 04102 04103 _dbus_verbose ("unlocking dispatch_mutex\n"); 04104 _dbus_mutex_unlock (connection->dispatch_mutex); 04105 04106 CONNECTION_LOCK (connection); 04107 _dbus_connection_unref_unlocked (connection); 04108 } 04109 04117 static void 04118 _dbus_connection_release_dispatch (DBusConnection *connection) 04119 { 04120 HAVE_LOCK_CHECK (connection); 04121 04122 _dbus_verbose ("locking dispatch_mutex\n"); 04123 _dbus_mutex_lock (connection->dispatch_mutex); 04124 04125 _dbus_assert (connection->dispatch_acquired); 04126 04127 connection->dispatch_acquired = FALSE; 04128 _dbus_condvar_wake_one (connection->dispatch_cond); 04129 04130 _dbus_verbose ("unlocking dispatch_mutex\n"); 04131 _dbus_mutex_unlock (connection->dispatch_mutex); 04132 } 04133 04134 static void 04135 _dbus_connection_failed_pop (DBusConnection *connection, 04136 DBusList *message_link) 04137 { 04138 _dbus_list_prepend_link (&connection->incoming_messages, 04139 message_link); 04140 connection->n_incoming += 1; 04141 } 04142 04143 /* Note this may be called multiple times since we don't track whether we already did it */ 04144 static void 04145 notify_disconnected_unlocked (DBusConnection *connection) 04146 { 04147 HAVE_LOCK_CHECK (connection); 04148 04149 /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected 04150 * connection from dbus_bus_get(). We make the same guarantee for 04151 * dbus_connection_open() but in a different way since we don't want to 04152 * unref right here; we instead check for connectedness before returning 04153 * the connection from the hash. 04154 */ 04155 _dbus_bus_notify_shared_connection_disconnected_unlocked (connection); 04156 04157 /* Dump the outgoing queue, we aren't going to be able to 04158 * send it now, and we'd like accessors like 04159 * dbus_connection_get_outgoing_size() to be accurate. 04160 */ 04161 if (connection->n_outgoing > 0) 04162 { 04163 DBusList *link; 04164 04165 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n", 04166 connection->n_outgoing); 04167 04168 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages))) 04169 { 04170 _dbus_connection_message_sent (connection, link->data); 04171 } 04172 } 04173 } 04174 04175 /* Note this may be called multiple times since we don't track whether we already did it */ 04176 static DBusDispatchStatus 04177 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection) 04178 { 04179 HAVE_LOCK_CHECK (connection); 04180 04181 if (connection->disconnect_message_link != NULL) 04182 { 04183 _dbus_verbose ("Sending disconnect message\n"); 04184 04185 /* If we have pending calls, queue their timeouts - we want the Disconnected 04186 * to be the last message, after these timeouts. 04187 */ 04188 connection_timeout_and_complete_all_pending_calls_unlocked (connection); 04189 04190 /* We haven't sent the disconnect message already, 04191 * and all real messages have been queued up. 04192 */ 04193 _dbus_connection_queue_synthesized_message_link (connection, 04194 connection->disconnect_message_link); 04195 connection->disconnect_message_link = NULL; 04196 04197 return DBUS_DISPATCH_DATA_REMAINS; 04198 } 04199 04200 return DBUS_DISPATCH_COMPLETE; 04201 } 04202 04203 static DBusDispatchStatus 04204 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection) 04205 { 04206 HAVE_LOCK_CHECK (connection); 04207 04208 if (connection->n_incoming > 0) 04209 return DBUS_DISPATCH_DATA_REMAINS; 04210 else if (!_dbus_transport_queue_messages (connection->transport)) 04211 return DBUS_DISPATCH_NEED_MEMORY; 04212 else 04213 { 04214 DBusDispatchStatus status; 04215 dbus_bool_t is_connected; 04216 04217 status = _dbus_transport_get_dispatch_status (connection->transport); 04218 is_connected = _dbus_transport_get_is_connected (connection->transport); 04219 04220 _dbus_verbose ("dispatch status = %s is_connected = %d\n", 04221 DISPATCH_STATUS_NAME (status), is_connected); 04222 04223 if (!is_connected) 04224 { 04225 /* It's possible this would be better done by having an explicit 04226 * notification from _dbus_transport_disconnect() that would 04227 * synchronously do this, instead of waiting for the next dispatch 04228 * status check. However, probably not good to change until it causes 04229 * a problem. 04230 */ 04231 notify_disconnected_unlocked (connection); 04232 04233 /* I'm not sure this is needed; the idea is that we want to 04234 * queue the Disconnected only after we've read all the 04235 * messages, but if we're disconnected maybe we are guaranteed 04236 * to have read them all ? 04237 */ 04238 if (status == DBUS_DISPATCH_COMPLETE) 04239 status = notify_disconnected_and_dispatch_complete_unlocked (connection); 04240 } 04241 04242 if (status != DBUS_DISPATCH_COMPLETE) 04243 return status; 04244 else if (connection->n_incoming > 0) 04245 return DBUS_DISPATCH_DATA_REMAINS; 04246 else 04247 return DBUS_DISPATCH_COMPLETE; 04248 } 04249 } 04250 04251 static void 04252 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection, 04253 DBusDispatchStatus new_status) 04254 { 04255 dbus_bool_t changed; 04256 DBusDispatchStatusFunction function; 04257 void *data; 04258 04259 HAVE_LOCK_CHECK (connection); 04260 04261 _dbus_connection_ref_unlocked (connection); 04262 04263 changed = new_status != connection->last_dispatch_status; 04264 04265 connection->last_dispatch_status = new_status; 04266 04267 function = connection->dispatch_status_function; 04268 data = connection->dispatch_status_data; 04269 04270 if (connection->disconnected_message_arrived && 04271 !connection->disconnected_message_processed) 04272 { 04273 connection->disconnected_message_processed = TRUE; 04274 04275 /* this does an unref, but we have a ref 04276 * so we should not run the finalizer here 04277 * inside the lock. 04278 */ 04279 connection_forget_shared_unlocked (connection); 04280 04281 if (connection->exit_on_disconnect) 04282 { 04283 CONNECTION_UNLOCK (connection); 04284 04285 _dbus_verbose ("Exiting on Disconnected signal\n"); 04286 _dbus_exit (1); 04287 _dbus_assert_not_reached ("Call to exit() returned"); 04288 } 04289 } 04290 04291 /* We drop the lock */ 04292 CONNECTION_UNLOCK (connection); 04293 04294 if (changed && function) 04295 { 04296 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n", 04297 connection, new_status, 04298 DISPATCH_STATUS_NAME (new_status)); 04299 (* function) (connection, new_status, data); 04300 } 04301 04302 dbus_connection_unref (connection); 04303 } 04304 04330 DBusDispatchStatus 04331 dbus_connection_get_dispatch_status (DBusConnection *connection) 04332 { 04333 DBusDispatchStatus status; 04334 04335 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE); 04336 04337 _dbus_verbose ("start\n"); 04338 04339 CONNECTION_LOCK (connection); 04340 04341 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04342 04343 CONNECTION_UNLOCK (connection); 04344 04345 return status; 04346 } 04347 04351 static DBusHandlerResult 04352 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection, 04353 DBusMessage *message) 04354 { 04355 if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL) 04356 { 04357 /* This means we're letting the bus route this message */ 04358 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04359 } 04360 else if (dbus_message_is_method_call (message, 04361 DBUS_INTERFACE_PEER, 04362 "Ping")) 04363 { 04364 DBusMessage *ret; 04365 dbus_bool_t sent; 04366 04367 ret = dbus_message_new_method_return (message); 04368 if (ret == NULL) 04369 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04370 04371 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04372 04373 dbus_message_unref (ret); 04374 04375 if (!sent) 04376 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04377 04378 return DBUS_HANDLER_RESULT_HANDLED; 04379 } 04380 else if (dbus_message_is_method_call (message, 04381 DBUS_INTERFACE_PEER, 04382 "GetMachineId")) 04383 { 04384 DBusMessage *ret; 04385 dbus_bool_t sent; 04386 DBusString uuid; 04387 04388 ret = dbus_message_new_method_return (message); 04389 if (ret == NULL) 04390 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04391 04392 sent = FALSE; 04393 _dbus_string_init (&uuid); 04394 if (_dbus_get_local_machine_uuid_encoded (&uuid)) 04395 { 04396 const char *v_STRING = _dbus_string_get_const_data (&uuid); 04397 if (dbus_message_append_args (ret, 04398 DBUS_TYPE_STRING, &v_STRING, 04399 DBUS_TYPE_INVALID)) 04400 { 04401 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04402 } 04403 } 04404 _dbus_string_free (&uuid); 04405 04406 dbus_message_unref (ret); 04407 04408 if (!sent) 04409 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04410 04411 return DBUS_HANDLER_RESULT_HANDLED; 04412 } 04413 else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER)) 04414 { 04415 /* We need to bounce anything else with this interface, otherwise apps 04416 * could start extending the interface and when we added extensions 04417 * here to DBusConnection we'd break those apps. 04418 */ 04419 04420 DBusMessage *ret; 04421 dbus_bool_t sent; 04422 04423 ret = dbus_message_new_error (message, 04424 DBUS_ERROR_UNKNOWN_METHOD, 04425 "Unknown method invoked on org.freedesktop.DBus.Peer interface"); 04426 if (ret == NULL) 04427 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04428 04429 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04430 04431 dbus_message_unref (ret); 04432 04433 if (!sent) 04434 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04435 04436 return DBUS_HANDLER_RESULT_HANDLED; 04437 } 04438 else 04439 { 04440 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04441 } 04442 } 04443 04450 static DBusHandlerResult 04451 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection, 04452 DBusMessage *message) 04453 { 04454 /* We just run one filter for now but have the option to run more 04455 if the spec calls for it in the future */ 04456 04457 return _dbus_connection_peer_filter_unlocked_no_update (connection, message); 04458 } 04459 04502 DBusDispatchStatus 04503 dbus_connection_dispatch (DBusConnection *connection) 04504 { 04505 DBusMessage *message; 04506 DBusList *link, *filter_list_copy, *message_link; 04507 DBusHandlerResult result; 04508 DBusPendingCall *pending; 04509 dbus_int32_t reply_serial; 04510 DBusDispatchStatus status; 04511 04512 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE); 04513 04514 _dbus_verbose ("\n"); 04515 04516 CONNECTION_LOCK (connection); 04517 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04518 if (status != DBUS_DISPATCH_DATA_REMAINS) 04519 { 04520 /* unlocks and calls out to user code */ 04521 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04522 return status; 04523 } 04524 04525 /* We need to ref the connection since the callback could potentially 04526 * drop the last ref to it 04527 */ 04528 _dbus_connection_ref_unlocked (connection); 04529 04530 _dbus_connection_acquire_dispatch (connection); 04531 HAVE_LOCK_CHECK (connection); 04532 04533 message_link = _dbus_connection_pop_message_link_unlocked (connection); 04534 if (message_link == NULL) 04535 { 04536 /* another thread dispatched our stuff */ 04537 04538 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n"); 04539 04540 _dbus_connection_release_dispatch (connection); 04541 04542 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04543 04544 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04545 04546 dbus_connection_unref (connection); 04547 04548 return status; 04549 } 04550 04551 message = message_link->data; 04552 04553 _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n", 04554 message, 04555 dbus_message_type_to_string (dbus_message_get_type (message)), 04556 dbus_message_get_interface (message) ? 04557 dbus_message_get_interface (message) : 04558 "no interface", 04559 dbus_message_get_member (message) ? 04560 dbus_message_get_member (message) : 04561 "no member", 04562 dbus_message_get_signature (message)); 04563 04564 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04565 04566 /* Pending call handling must be first, because if you do 04567 * dbus_connection_send_with_reply_and_block() or 04568 * dbus_pending_call_block() then no handlers/filters will be run on 04569 * the reply. We want consistent semantics in the case where we 04570 * dbus_connection_dispatch() the reply. 04571 */ 04572 04573 reply_serial = dbus_message_get_reply_serial (message); 04574 pending = _dbus_hash_table_lookup_int (connection->pending_replies, 04575 reply_serial); 04576 if (pending) 04577 { 04578 _dbus_verbose ("Dispatching a pending reply\n"); 04579 complete_pending_call_and_unlock (connection, pending, message); 04580 pending = NULL; /* it's probably unref'd */ 04581 04582 CONNECTION_LOCK (connection); 04583 _dbus_verbose ("pending call completed in dispatch\n"); 04584 result = DBUS_HANDLER_RESULT_HANDLED; 04585 goto out; 04586 } 04587 04588 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message); 04589 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04590 goto out; 04591 04592 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy)) 04593 { 04594 _dbus_connection_release_dispatch (connection); 04595 HAVE_LOCK_CHECK (connection); 04596 04597 _dbus_connection_failed_pop (connection, message_link); 04598 04599 /* unlocks and calls user code */ 04600 _dbus_connection_update_dispatch_status_and_unlock (connection, 04601 DBUS_DISPATCH_NEED_MEMORY); 04602 dbus_connection_unref (connection); 04603 04604 return DBUS_DISPATCH_NEED_MEMORY; 04605 } 04606 04607 _dbus_list_foreach (&filter_list_copy, 04608 (DBusForeachFunction)_dbus_message_filter_ref, 04609 NULL); 04610 04611 /* We're still protected from dispatch() reentrancy here 04612 * since we acquired the dispatcher 04613 */ 04614 CONNECTION_UNLOCK (connection); 04615 04616 link = _dbus_list_get_first_link (&filter_list_copy); 04617 while (link != NULL) 04618 { 04619 DBusMessageFilter *filter = link->data; 04620 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link); 04621 04622 if (filter->function == NULL) 04623 { 04624 _dbus_verbose (" filter was removed in a callback function\n"); 04625 link = next; 04626 continue; 04627 } 04628 04629 _dbus_verbose (" running filter on message %p\n", message); 04630 result = (* filter->function) (connection, message, filter->user_data); 04631 04632 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04633 break; 04634 04635 link = next; 04636 } 04637 04638 _dbus_list_foreach (&filter_list_copy, 04639 (DBusForeachFunction)_dbus_message_filter_unref, 04640 NULL); 04641 _dbus_list_clear (&filter_list_copy); 04642 04643 CONNECTION_LOCK (connection); 04644 04645 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) 04646 { 04647 _dbus_verbose ("No memory\n"); 04648 goto out; 04649 } 04650 else if (result == DBUS_HANDLER_RESULT_HANDLED) 04651 { 04652 _dbus_verbose ("filter handled message in dispatch\n"); 04653 goto out; 04654 } 04655 04656 /* We're still protected from dispatch() reentrancy here 04657 * since we acquired the dispatcher 04658 */ 04659 _dbus_verbose (" running object path dispatch on message %p (%s %s %s '%s')\n", 04660 message, 04661 dbus_message_type_to_string (dbus_message_get_type (message)), 04662 dbus_message_get_interface (message) ? 04663 dbus_message_get_interface (message) : 04664 "no interface", 04665 dbus_message_get_member (message) ? 04666 dbus_message_get_member (message) : 04667 "no member", 04668 dbus_message_get_signature (message)); 04669 04670 HAVE_LOCK_CHECK (connection); 04671 result = _dbus_object_tree_dispatch_and_unlock (connection->objects, 04672 message); 04673 04674 CONNECTION_LOCK (connection); 04675 04676 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04677 { 04678 _dbus_verbose ("object tree handled message in dispatch\n"); 04679 goto out; 04680 } 04681 04682 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL) 04683 { 04684 DBusMessage *reply; 04685 DBusString str; 04686 DBusPreallocatedSend *preallocated; 04687 04688 _dbus_verbose (" sending error %s\n", 04689 DBUS_ERROR_UNKNOWN_METHOD); 04690 04691 if (!_dbus_string_init (&str)) 04692 { 04693 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04694 _dbus_verbose ("no memory for error string in dispatch\n"); 04695 goto out; 04696 } 04697 04698 if (!_dbus_string_append_printf (&str, 04699 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n", 04700 dbus_message_get_member (message), 04701 dbus_message_get_signature (message), 04702 dbus_message_get_interface (message))) 04703 { 04704 _dbus_string_free (&str); 04705 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04706 _dbus_verbose ("no memory for error string in dispatch\n"); 04707 goto out; 04708 } 04709 04710 reply = dbus_message_new_error (message, 04711 DBUS_ERROR_UNKNOWN_METHOD, 04712 _dbus_string_get_const_data (&str)); 04713 _dbus_string_free (&str); 04714 04715 if (reply == NULL) 04716 { 04717 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04718 _dbus_verbose ("no memory for error reply in dispatch\n"); 04719 goto out; 04720 } 04721 04722 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 04723 04724 if (preallocated == NULL) 04725 { 04726 dbus_message_unref (reply); 04727 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04728 _dbus_verbose ("no memory for error send in dispatch\n"); 04729 goto out; 04730 } 04731 04732 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated, 04733 reply, NULL); 04734 04735 dbus_message_unref (reply); 04736 04737 result = DBUS_HANDLER_RESULT_HANDLED; 04738 } 04739 04740 _dbus_verbose (" done dispatching %p (%s %s %s '%s') on connection %p\n", message, 04741 dbus_message_type_to_string (dbus_message_get_type (message)), 04742 dbus_message_get_interface (message) ? 04743 dbus_message_get_interface (message) : 04744 "no interface", 04745 dbus_message_get_member (message) ? 04746 dbus_message_get_member (message) : 04747 "no member", 04748 dbus_message_get_signature (message), 04749 connection); 04750 04751 out: 04752 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) 04753 { 04754 _dbus_verbose ("out of memory\n"); 04755 04756 /* Put message back, and we'll start over. 04757 * Yes this means handlers must be idempotent if they 04758 * don't return HANDLED; c'est la vie. 04759 */ 04760 _dbus_connection_putback_message_link_unlocked (connection, 04761 message_link); 04762 } 04763 else 04764 { 04765 _dbus_verbose (" ... done dispatching\n"); 04766 04767 _dbus_list_free_link (message_link); 04768 dbus_message_unref (message); /* don't want the message to count in max message limits 04769 * in computing dispatch status below 04770 */ 04771 } 04772 04773 _dbus_connection_release_dispatch (connection); 04774 HAVE_LOCK_CHECK (connection); 04775 04776 _dbus_verbose ("before final status update\n"); 04777 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04778 04779 /* unlocks and calls user code */ 04780 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04781 04782 dbus_connection_unref (connection); 04783 04784 return status; 04785 } 04786 04848 dbus_bool_t 04849 dbus_connection_set_watch_functions (DBusConnection *connection, 04850 DBusAddWatchFunction add_function, 04851 DBusRemoveWatchFunction remove_function, 04852 DBusWatchToggledFunction toggled_function, 04853 void *data, 04854 DBusFreeFunction free_data_function) 04855 { 04856 dbus_bool_t retval; 04857 04858 _dbus_return_val_if_fail (connection != NULL, FALSE); 04859 04860 CONNECTION_LOCK (connection); 04861 04862 retval = _dbus_watch_list_set_functions (connection->watches, 04863 add_function, remove_function, 04864 toggled_function, 04865 data, free_data_function); 04866 04867 CONNECTION_UNLOCK (connection); 04868 04869 return retval; 04870 } 04871 04911 dbus_bool_t 04912 dbus_connection_set_timeout_functions (DBusConnection *connection, 04913 DBusAddTimeoutFunction add_function, 04914 DBusRemoveTimeoutFunction remove_function, 04915 DBusTimeoutToggledFunction toggled_function, 04916 void *data, 04917 DBusFreeFunction free_data_function) 04918 { 04919 dbus_bool_t retval; 04920 04921 _dbus_return_val_if_fail (connection != NULL, FALSE); 04922 04923 CONNECTION_LOCK (connection); 04924 04925 retval = _dbus_timeout_list_set_functions (connection->timeouts, 04926 add_function, remove_function, 04927 toggled_function, 04928 data, free_data_function); 04929 04930 CONNECTION_UNLOCK (connection); 04931 04932 return retval; 04933 } 04934 04949 void 04950 dbus_connection_set_wakeup_main_function (DBusConnection *connection, 04951 DBusWakeupMainFunction wakeup_main_function, 04952 void *data, 04953 DBusFreeFunction free_data_function) 04954 { 04955 void *old_data; 04956 DBusFreeFunction old_free_data; 04957 04958 _dbus_return_if_fail (connection != NULL); 04959 04960 CONNECTION_LOCK (connection); 04961 old_data = connection->wakeup_main_data; 04962 old_free_data = connection->free_wakeup_main_data; 04963 04964 connection->wakeup_main_function = wakeup_main_function; 04965 connection->wakeup_main_data = data; 04966 connection->free_wakeup_main_data = free_data_function; 04967 04968 CONNECTION_UNLOCK (connection); 04969 04970 /* Callback outside the lock */ 04971 if (old_free_data) 04972 (*old_free_data) (old_data); 04973 } 04974 04995 void 04996 dbus_connection_set_dispatch_status_function (DBusConnection *connection, 04997 DBusDispatchStatusFunction function, 04998 void *data, 04999 DBusFreeFunction free_data_function) 05000 { 05001 void *old_data; 05002 DBusFreeFunction old_free_data; 05003 05004 _dbus_return_if_fail (connection != NULL); 05005 05006 CONNECTION_LOCK (connection); 05007 old_data = connection->dispatch_status_data; 05008 old_free_data = connection->free_dispatch_status_data; 05009 05010 connection->dispatch_status_function = function; 05011 connection->dispatch_status_data = data; 05012 connection->free_dispatch_status_data = free_data_function; 05013 05014 CONNECTION_UNLOCK (connection); 05015 05016 /* Callback outside the lock */ 05017 if (old_free_data) 05018 (*old_free_data) (old_data); 05019 } 05020 05040 dbus_bool_t 05041 dbus_connection_get_unix_fd (DBusConnection *connection, 05042 int *fd) 05043 { 05044 _dbus_return_val_if_fail (connection != NULL, FALSE); 05045 _dbus_return_val_if_fail (connection->transport != NULL, FALSE); 05046 05047 #ifdef DBUS_WIN 05048 /* FIXME do this on a lower level */ 05049 return FALSE; 05050 #endif 05051 05052 return dbus_connection_get_socket(connection, fd); 05053 } 05054 05070 dbus_bool_t 05071 dbus_connection_get_socket(DBusConnection *connection, 05072 int *fd) 05073 { 05074 dbus_bool_t retval; 05075 05076 _dbus_return_val_if_fail (connection != NULL, FALSE); 05077 _dbus_return_val_if_fail (connection->transport != NULL, FALSE); 05078 05079 CONNECTION_LOCK (connection); 05080 05081 retval = _dbus_transport_get_socket_fd (connection->transport, 05082 fd); 05083 05084 CONNECTION_UNLOCK (connection); 05085 05086 return retval; 05087 } 05088 05089 05112 dbus_bool_t 05113 dbus_connection_get_unix_user (DBusConnection *connection, 05114 unsigned long *uid) 05115 { 05116 dbus_bool_t result; 05117 05118 _dbus_return_val_if_fail (connection != NULL, FALSE); 05119 _dbus_return_val_if_fail (uid != NULL, FALSE); 05120 05121 CONNECTION_LOCK (connection); 05122 05123 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05124 result = FALSE; 05125 else 05126 result = _dbus_transport_get_unix_user (connection->transport, 05127 uid); 05128 05129 #ifdef DBUS_WIN 05130 _dbus_assert (!result); 05131 #endif 05132 05133 CONNECTION_UNLOCK (connection); 05134 05135 return result; 05136 } 05137 05148 dbus_bool_t 05149 dbus_connection_get_unix_process_id (DBusConnection *connection, 05150 unsigned long *pid) 05151 { 05152 dbus_bool_t result; 05153 05154 _dbus_return_val_if_fail (connection != NULL, FALSE); 05155 _dbus_return_val_if_fail (pid != NULL, FALSE); 05156 05157 CONNECTION_LOCK (connection); 05158 05159 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05160 result = FALSE; 05161 else 05162 result = _dbus_transport_get_unix_process_id (connection->transport, 05163 pid); 05164 05165 CONNECTION_UNLOCK (connection); 05166 05167 return result; 05168 } 05169 05180 dbus_bool_t 05181 dbus_connection_get_adt_audit_session_data (DBusConnection *connection, 05182 void **data, 05183 dbus_int32_t *data_size) 05184 { 05185 dbus_bool_t result; 05186 05187 _dbus_return_val_if_fail (connection != NULL, FALSE); 05188 _dbus_return_val_if_fail (data != NULL, FALSE); 05189 _dbus_return_val_if_fail (data_size != NULL, FALSE); 05190 05191 CONNECTION_LOCK (connection); 05192 05193 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05194 result = FALSE; 05195 else 05196 result = _dbus_transport_get_adt_audit_session_data (connection->transport, 05197 data, 05198 data_size); 05199 CONNECTION_UNLOCK (connection); 05200 05201 return result; 05202 } 05203 05226 void 05227 dbus_connection_set_unix_user_function (DBusConnection *connection, 05228 DBusAllowUnixUserFunction function, 05229 void *data, 05230 DBusFreeFunction free_data_function) 05231 { 05232 void *old_data = NULL; 05233 DBusFreeFunction old_free_function = NULL; 05234 05235 _dbus_return_if_fail (connection != NULL); 05236 05237 CONNECTION_LOCK (connection); 05238 _dbus_transport_set_unix_user_function (connection->transport, 05239 function, data, free_data_function, 05240 &old_data, &old_free_function); 05241 CONNECTION_UNLOCK (connection); 05242 05243 if (old_free_function != NULL) 05244 (* old_free_function) (old_data); 05245 } 05246 05278 dbus_bool_t 05279 dbus_connection_get_windows_user (DBusConnection *connection, 05280 char **windows_sid_p) 05281 { 05282 dbus_bool_t result; 05283 05284 _dbus_return_val_if_fail (connection != NULL, FALSE); 05285 _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE); 05286 05287 CONNECTION_LOCK (connection); 05288 05289 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05290 result = FALSE; 05291 else 05292 result = _dbus_transport_get_windows_user (connection->transport, 05293 windows_sid_p); 05294 05295 #ifdef DBUS_UNIX 05296 _dbus_assert (!result); 05297 #endif 05298 05299 CONNECTION_UNLOCK (connection); 05300 05301 return result; 05302 } 05303 05325 void 05326 dbus_connection_set_windows_user_function (DBusConnection *connection, 05327 DBusAllowWindowsUserFunction function, 05328 void *data, 05329 DBusFreeFunction free_data_function) 05330 { 05331 void *old_data = NULL; 05332 DBusFreeFunction old_free_function = NULL; 05333 05334 _dbus_return_if_fail (connection != NULL); 05335 05336 CONNECTION_LOCK (connection); 05337 _dbus_transport_set_windows_user_function (connection->transport, 05338 function, data, free_data_function, 05339 &old_data, &old_free_function); 05340 CONNECTION_UNLOCK (connection); 05341 05342 if (old_free_function != NULL) 05343 (* old_free_function) (old_data); 05344 } 05345 05372 void 05373 dbus_connection_set_allow_anonymous (DBusConnection *connection, 05374 dbus_bool_t value) 05375 { 05376 _dbus_return_if_fail (connection != NULL); 05377 05378 CONNECTION_LOCK (connection); 05379 _dbus_transport_set_allow_anonymous (connection->transport, value); 05380 CONNECTION_UNLOCK (connection); 05381 } 05382 05400 void 05401 dbus_connection_set_route_peer_messages (DBusConnection *connection, 05402 dbus_bool_t value) 05403 { 05404 _dbus_return_if_fail (connection != NULL); 05405 05406 CONNECTION_LOCK (connection); 05407 connection->route_peer_messages = TRUE; 05408 CONNECTION_UNLOCK (connection); 05409 } 05410 05432 dbus_bool_t 05433 dbus_connection_add_filter (DBusConnection *connection, 05434 DBusHandleMessageFunction function, 05435 void *user_data, 05436 DBusFreeFunction free_data_function) 05437 { 05438 DBusMessageFilter *filter; 05439 05440 _dbus_return_val_if_fail (connection != NULL, FALSE); 05441 _dbus_return_val_if_fail (function != NULL, FALSE); 05442 05443 filter = dbus_new0 (DBusMessageFilter, 1); 05444 if (filter == NULL) 05445 return FALSE; 05446 05447 _dbus_atomic_inc (&filter->refcount); 05448 05449 CONNECTION_LOCK (connection); 05450 05451 if (!_dbus_list_append (&connection->filter_list, 05452 filter)) 05453 { 05454 _dbus_message_filter_unref (filter); 05455 CONNECTION_UNLOCK (connection); 05456 return FALSE; 05457 } 05458 05459 /* Fill in filter after all memory allocated, 05460 * so we don't run the free_user_data_function 05461 * if the add_filter() fails 05462 */ 05463 05464 filter->function = function; 05465 filter->user_data = user_data; 05466 filter->free_user_data_function = free_data_function; 05467 05468 CONNECTION_UNLOCK (connection); 05469 return TRUE; 05470 } 05471 05484 void 05485 dbus_connection_remove_filter (DBusConnection *connection, 05486 DBusHandleMessageFunction function, 05487 void *user_data) 05488 { 05489 DBusList *link; 05490 DBusMessageFilter *filter; 05491 05492 _dbus_return_if_fail (connection != NULL); 05493 _dbus_return_if_fail (function != NULL); 05494 05495 CONNECTION_LOCK (connection); 05496 05497 filter = NULL; 05498 05499 link = _dbus_list_get_last_link (&connection->filter_list); 05500 while (link != NULL) 05501 { 05502 filter = link->data; 05503 05504 if (filter->function == function && 05505 filter->user_data == user_data) 05506 { 05507 _dbus_list_remove_link (&connection->filter_list, link); 05508 filter->function = NULL; 05509 05510 break; 05511 } 05512 05513 link = _dbus_list_get_prev_link (&connection->filter_list, link); 05514 filter = NULL; 05515 } 05516 05517 CONNECTION_UNLOCK (connection); 05518 05519 #ifndef DBUS_DISABLE_CHECKS 05520 if (filter == NULL) 05521 { 05522 _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n", 05523 function, user_data); 05524 return; 05525 } 05526 #endif 05527 05528 /* Call application code */ 05529 if (filter->free_user_data_function) 05530 (* filter->free_user_data_function) (filter->user_data); 05531 05532 filter->free_user_data_function = NULL; 05533 filter->user_data = NULL; 05534 05535 _dbus_message_filter_unref (filter); 05536 } 05537 05550 dbus_bool_t 05551 dbus_connection_try_register_object_path (DBusConnection *connection, 05552 const char *path, 05553 const DBusObjectPathVTable *vtable, 05554 void *user_data, 05555 DBusError *error) 05556 { 05557 char **decomposed_path; 05558 dbus_bool_t retval; 05559 05560 _dbus_return_val_if_fail (connection != NULL, FALSE); 05561 _dbus_return_val_if_fail (path != NULL, FALSE); 05562 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05563 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05564 05565 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05566 return FALSE; 05567 05568 CONNECTION_LOCK (connection); 05569 05570 retval = _dbus_object_tree_register (connection->objects, 05571 FALSE, 05572 (const char **) decomposed_path, vtable, 05573 user_data, error); 05574 05575 CONNECTION_UNLOCK (connection); 05576 05577 dbus_free_string_array (decomposed_path); 05578 05579 return retval; 05580 } 05581 05597 dbus_bool_t 05598 dbus_connection_register_object_path (DBusConnection *connection, 05599 const char *path, 05600 const DBusObjectPathVTable *vtable, 05601 void *user_data) 05602 { 05603 char **decomposed_path; 05604 dbus_bool_t retval; 05605 DBusError error = DBUS_ERROR_INIT; 05606 05607 _dbus_return_val_if_fail (connection != NULL, FALSE); 05608 _dbus_return_val_if_fail (path != NULL, FALSE); 05609 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05610 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05611 05612 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05613 return FALSE; 05614 05615 CONNECTION_LOCK (connection); 05616 05617 retval = _dbus_object_tree_register (connection->objects, 05618 FALSE, 05619 (const char **) decomposed_path, vtable, 05620 user_data, &error); 05621 05622 CONNECTION_UNLOCK (connection); 05623 05624 dbus_free_string_array (decomposed_path); 05625 05626 if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE)) 05627 { 05628 _dbus_warn ("%s\n", error.message); 05629 dbus_error_free (&error); 05630 return FALSE; 05631 } 05632 05633 return retval; 05634 } 05635 05650 dbus_bool_t 05651 dbus_connection_try_register_fallback (DBusConnection *connection, 05652 const char *path, 05653 const DBusObjectPathVTable *vtable, 05654 void *user_data, 05655 DBusError *error) 05656 { 05657 char **decomposed_path; 05658 dbus_bool_t retval; 05659 05660 _dbus_return_val_if_fail (connection != NULL, FALSE); 05661 _dbus_return_val_if_fail (path != NULL, FALSE); 05662 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05663 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05664 05665 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05666 return FALSE; 05667 05668 CONNECTION_LOCK (connection); 05669 05670 retval = _dbus_object_tree_register (connection->objects, 05671 TRUE, 05672 (const char **) decomposed_path, vtable, 05673 user_data, error); 05674 05675 CONNECTION_UNLOCK (connection); 05676 05677 dbus_free_string_array (decomposed_path); 05678 05679 return retval; 05680 } 05681 05699 dbus_bool_t 05700 dbus_connection_register_fallback (DBusConnection *connection, 05701 const char *path, 05702 const DBusObjectPathVTable *vtable, 05703 void *user_data) 05704 { 05705 char **decomposed_path; 05706 dbus_bool_t retval; 05707 DBusError error = DBUS_ERROR_INIT; 05708 05709 _dbus_return_val_if_fail (connection != NULL, FALSE); 05710 _dbus_return_val_if_fail (path != NULL, FALSE); 05711 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05712 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05713 05714 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05715 return FALSE; 05716 05717 CONNECTION_LOCK (connection); 05718 05719 retval = _dbus_object_tree_register (connection->objects, 05720 TRUE, 05721 (const char **) decomposed_path, vtable, 05722 user_data, &error); 05723 05724 CONNECTION_UNLOCK (connection); 05725 05726 dbus_free_string_array (decomposed_path); 05727 05728 if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE)) 05729 { 05730 _dbus_warn ("%s\n", error.message); 05731 dbus_error_free (&error); 05732 return FALSE; 05733 } 05734 05735 return retval; 05736 } 05737 05747 dbus_bool_t 05748 dbus_connection_unregister_object_path (DBusConnection *connection, 05749 const char *path) 05750 { 05751 char **decomposed_path; 05752 05753 _dbus_return_val_if_fail (connection != NULL, FALSE); 05754 _dbus_return_val_if_fail (path != NULL, FALSE); 05755 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05756 05757 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05758 return FALSE; 05759 05760 CONNECTION_LOCK (connection); 05761 05762 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path); 05763 05764 dbus_free_string_array (decomposed_path); 05765 05766 return TRUE; 05767 } 05768 05779 dbus_bool_t 05780 dbus_connection_get_object_path_data (DBusConnection *connection, 05781 const char *path, 05782 void **data_p) 05783 { 05784 char **decomposed_path; 05785 05786 _dbus_return_val_if_fail (connection != NULL, FALSE); 05787 _dbus_return_val_if_fail (path != NULL, FALSE); 05788 _dbus_return_val_if_fail (data_p != NULL, FALSE); 05789 05790 *data_p = NULL; 05791 05792 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05793 return FALSE; 05794 05795 CONNECTION_LOCK (connection); 05796 05797 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path); 05798 05799 CONNECTION_UNLOCK (connection); 05800 05801 dbus_free_string_array (decomposed_path); 05802 05803 return TRUE; 05804 } 05805 05816 dbus_bool_t 05817 dbus_connection_list_registered (DBusConnection *connection, 05818 const char *parent_path, 05819 char ***child_entries) 05820 { 05821 char **decomposed_path; 05822 dbus_bool_t retval; 05823 _dbus_return_val_if_fail (connection != NULL, FALSE); 05824 _dbus_return_val_if_fail (parent_path != NULL, FALSE); 05825 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE); 05826 _dbus_return_val_if_fail (child_entries != NULL, FALSE); 05827 05828 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL)) 05829 return FALSE; 05830 05831 CONNECTION_LOCK (connection); 05832 05833 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects, 05834 (const char **) decomposed_path, 05835 child_entries); 05836 dbus_free_string_array (decomposed_path); 05837 05838 return retval; 05839 } 05840 05841 static DBusDataSlotAllocator slot_allocator; 05842 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots); 05843 05858 dbus_bool_t 05859 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p) 05860 { 05861 return _dbus_data_slot_allocator_alloc (&slot_allocator, 05862 &_DBUS_LOCK_NAME (connection_slots), 05863 slot_p); 05864 } 05865 05877 void 05878 dbus_connection_free_data_slot (dbus_int32_t *slot_p) 05879 { 05880 _dbus_return_if_fail (*slot_p >= 0); 05881 05882 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 05883 } 05884 05907 dbus_bool_t 05908 dbus_connection_set_data (DBusConnection *connection, 05909 dbus_int32_t slot, 05910 void *data, 05911 DBusFreeFunction free_data_func) 05912 { 05913 DBusFreeFunction old_free_func; 05914 void *old_data; 05915 dbus_bool_t retval; 05916 05917 _dbus_return_val_if_fail (connection != NULL, FALSE); 05918 _dbus_return_val_if_fail (slot >= 0, FALSE); 05919 05920 SLOTS_LOCK (connection); 05921 05922 retval = _dbus_data_slot_list_set (&slot_allocator, 05923 &connection->slot_list, 05924 slot, data, free_data_func, 05925 &old_free_func, &old_data); 05926 05927 SLOTS_UNLOCK (connection); 05928 05929 if (retval) 05930 { 05931 /* Do the actual free outside the connection lock */ 05932 if (old_free_func) 05933 (* old_free_func) (old_data); 05934 } 05935 05936 return retval; 05937 } 05938 05956 void* 05957 dbus_connection_get_data (DBusConnection *connection, 05958 dbus_int32_t slot) 05959 { 05960 void *res; 05961 05962 _dbus_return_val_if_fail (connection != NULL, NULL); 05963 05964 SLOTS_LOCK (connection); 05965 05966 res = _dbus_data_slot_list_get (&slot_allocator, 05967 &connection->slot_list, 05968 slot); 05969 05970 SLOTS_UNLOCK (connection); 05971 05972 return res; 05973 } 05974 05981 void 05982 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe) 05983 { 05984 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE; 05985 } 05986 05995 void 05996 dbus_connection_set_max_message_size (DBusConnection *connection, 05997 long size) 05998 { 05999 _dbus_return_if_fail (connection != NULL); 06000 06001 CONNECTION_LOCK (connection); 06002 _dbus_transport_set_max_message_size (connection->transport, 06003 size); 06004 CONNECTION_UNLOCK (connection); 06005 } 06006 06013 long 06014 dbus_connection_get_max_message_size (DBusConnection *connection) 06015 { 06016 long res; 06017 06018 _dbus_return_val_if_fail (connection != NULL, 0); 06019 06020 CONNECTION_LOCK (connection); 06021 res = _dbus_transport_get_max_message_size (connection->transport); 06022 CONNECTION_UNLOCK (connection); 06023 return res; 06024 } 06025 06034 void 06035 dbus_connection_set_max_message_unix_fds (DBusConnection *connection, 06036 long n) 06037 { 06038 _dbus_return_if_fail (connection != NULL); 06039 06040 CONNECTION_LOCK (connection); 06041 _dbus_transport_set_max_message_unix_fds (connection->transport, 06042 n); 06043 CONNECTION_UNLOCK (connection); 06044 } 06045 06052 long 06053 dbus_connection_get_max_message_unix_fds (DBusConnection *connection) 06054 { 06055 long res; 06056 06057 _dbus_return_val_if_fail (connection != NULL, 0); 06058 06059 CONNECTION_LOCK (connection); 06060 res = _dbus_transport_get_max_message_unix_fds (connection->transport); 06061 CONNECTION_UNLOCK (connection); 06062 return res; 06063 } 06064 06090 void 06091 dbus_connection_set_max_received_size (DBusConnection *connection, 06092 long size) 06093 { 06094 _dbus_return_if_fail (connection != NULL); 06095 06096 CONNECTION_LOCK (connection); 06097 _dbus_transport_set_max_received_size (connection->transport, 06098 size); 06099 CONNECTION_UNLOCK (connection); 06100 } 06101 06108 long 06109 dbus_connection_get_max_received_size (DBusConnection *connection) 06110 { 06111 long res; 06112 06113 _dbus_return_val_if_fail (connection != NULL, 0); 06114 06115 CONNECTION_LOCK (connection); 06116 res = _dbus_transport_get_max_received_size (connection->transport); 06117 CONNECTION_UNLOCK (connection); 06118 return res; 06119 } 06120 06132 void 06133 dbus_connection_set_max_received_unix_fds (DBusConnection *connection, 06134 long n) 06135 { 06136 _dbus_return_if_fail (connection != NULL); 06137 06138 CONNECTION_LOCK (connection); 06139 _dbus_transport_set_max_received_unix_fds (connection->transport, 06140 n); 06141 CONNECTION_UNLOCK (connection); 06142 } 06143 06150 long 06151 dbus_connection_get_max_received_unix_fds (DBusConnection *connection) 06152 { 06153 long res; 06154 06155 _dbus_return_val_if_fail (connection != NULL, 0); 06156 06157 CONNECTION_LOCK (connection); 06158 res = _dbus_transport_get_max_received_unix_fds (connection->transport); 06159 CONNECTION_UNLOCK (connection); 06160 return res; 06161 } 06162 06173 long 06174 dbus_connection_get_outgoing_size (DBusConnection *connection) 06175 { 06176 long res; 06177 06178 _dbus_return_val_if_fail (connection != NULL, 0); 06179 06180 CONNECTION_LOCK (connection); 06181 res = _dbus_counter_get_size_value (connection->outgoing_counter); 06182 CONNECTION_UNLOCK (connection); 06183 return res; 06184 } 06185 06193 long 06194 dbus_connection_get_outgoing_unix_fds (DBusConnection *connection) 06195 { 06196 long res; 06197 06198 _dbus_return_val_if_fail (connection != NULL, 0); 06199 06200 CONNECTION_LOCK (connection); 06201 res = _dbus_counter_get_unix_fd_value (connection->outgoing_counter); 06202 CONNECTION_UNLOCK (connection); 06203 return res; 06204 } 06205