D-Bus
1.4.16
|
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 02560 DBusConnection* 02561 dbus_connection_open (const char *address, 02562 DBusError *error) 02563 { 02564 DBusConnection *connection; 02565 02566 _dbus_return_val_if_fail (address != NULL, NULL); 02567 _dbus_return_val_if_error_is_set (error, NULL); 02568 02569 connection = _dbus_connection_open_internal (address, 02570 TRUE, 02571 error); 02572 02573 return connection; 02574 } 02575 02603 DBusConnection* 02604 dbus_connection_open_private (const char *address, 02605 DBusError *error) 02606 { 02607 DBusConnection *connection; 02608 02609 _dbus_return_val_if_fail (address != NULL, NULL); 02610 _dbus_return_val_if_error_is_set (error, NULL); 02611 02612 connection = _dbus_connection_open_internal (address, 02613 FALSE, 02614 error); 02615 02616 return connection; 02617 } 02618 02625 DBusConnection * 02626 dbus_connection_ref (DBusConnection *connection) 02627 { 02628 _dbus_return_val_if_fail (connection != NULL, NULL); 02629 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL); 02630 02631 _dbus_atomic_inc (&connection->refcount); 02632 02633 return connection; 02634 } 02635 02636 static void 02637 free_outgoing_message (void *element, 02638 void *data) 02639 { 02640 DBusMessage *message = element; 02641 DBusConnection *connection = data; 02642 02643 _dbus_message_remove_counter (message, 02644 connection->outgoing_counter, 02645 NULL); 02646 dbus_message_unref (message); 02647 } 02648 02649 /* This is run without the mutex held, but after the last reference 02650 * to the connection has been dropped we should have no thread-related 02651 * problems 02652 */ 02653 static void 02654 _dbus_connection_last_unref (DBusConnection *connection) 02655 { 02656 DBusList *link; 02657 02658 _dbus_verbose ("Finalizing connection %p\n", connection); 02659 02660 _dbus_assert (_dbus_atomic_get (&connection->refcount) == 0); 02661 02662 /* You have to disconnect the connection before unref:ing it. Otherwise 02663 * you won't get the disconnected message. 02664 */ 02665 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport)); 02666 _dbus_assert (connection->server_guid == NULL); 02667 02668 /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */ 02669 _dbus_object_tree_free_all_unlocked (connection->objects); 02670 02671 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL); 02672 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL); 02673 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL); 02674 02675 _dbus_watch_list_free (connection->watches); 02676 connection->watches = NULL; 02677 02678 _dbus_timeout_list_free (connection->timeouts); 02679 connection->timeouts = NULL; 02680 02681 _dbus_data_slot_list_free (&connection->slot_list); 02682 02683 link = _dbus_list_get_first_link (&connection->filter_list); 02684 while (link != NULL) 02685 { 02686 DBusMessageFilter *filter = link->data; 02687 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link); 02688 02689 filter->function = NULL; 02690 _dbus_message_filter_unref (filter); /* calls app callback */ 02691 link->data = NULL; 02692 02693 link = next; 02694 } 02695 _dbus_list_clear (&connection->filter_list); 02696 02697 /* ---- Done with stuff that invokes application callbacks */ 02698 02699 _dbus_object_tree_unref (connection->objects); 02700 02701 _dbus_hash_table_unref (connection->pending_replies); 02702 connection->pending_replies = NULL; 02703 02704 _dbus_list_clear (&connection->filter_list); 02705 02706 _dbus_list_foreach (&connection->outgoing_messages, 02707 free_outgoing_message, 02708 connection); 02709 _dbus_list_clear (&connection->outgoing_messages); 02710 02711 _dbus_list_foreach (&connection->incoming_messages, 02712 (DBusForeachFunction) dbus_message_unref, 02713 NULL); 02714 _dbus_list_clear (&connection->incoming_messages); 02715 02716 _dbus_counter_unref (connection->outgoing_counter); 02717 02718 _dbus_transport_unref (connection->transport); 02719 02720 if (connection->disconnect_message_link) 02721 { 02722 DBusMessage *message = connection->disconnect_message_link->data; 02723 dbus_message_unref (message); 02724 _dbus_list_free_link (connection->disconnect_message_link); 02725 } 02726 02727 _dbus_list_clear (&connection->link_cache); 02728 02729 _dbus_condvar_free_at_location (&connection->dispatch_cond); 02730 _dbus_condvar_free_at_location (&connection->io_path_cond); 02731 02732 _dbus_mutex_free_at_location (&connection->io_path_mutex); 02733 _dbus_mutex_free_at_location (&connection->dispatch_mutex); 02734 02735 _dbus_mutex_free_at_location (&connection->slot_mutex); 02736 02737 _dbus_mutex_free_at_location (&connection->mutex); 02738 02739 dbus_free (connection); 02740 } 02741 02761 void 02762 dbus_connection_unref (DBusConnection *connection) 02763 { 02764 dbus_bool_t last_unref; 02765 02766 _dbus_return_if_fail (connection != NULL); 02767 _dbus_return_if_fail (connection->generation == _dbus_current_generation); 02768 02769 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1); 02770 02771 if (last_unref) 02772 { 02773 #ifndef DBUS_DISABLE_CHECKS 02774 if (_dbus_transport_get_is_connected (connection->transport)) 02775 { 02776 _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", 02777 connection->shareable ? 02778 "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" : 02779 "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n"); 02780 return; 02781 } 02782 #endif 02783 _dbus_connection_last_unref (connection); 02784 } 02785 } 02786 02787 /* 02788 * Note that the transport can disconnect itself (other end drops us) 02789 * and in that case this function never runs. So this function must 02790 * not do anything more than disconnect the transport and update the 02791 * dispatch status. 02792 * 02793 * If the transport self-disconnects, then we assume someone will 02794 * dispatch the connection to cause the dispatch status update. 02795 */ 02796 static void 02797 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection) 02798 { 02799 DBusDispatchStatus status; 02800 02801 HAVE_LOCK_CHECK (connection); 02802 02803 _dbus_verbose ("Disconnecting %p\n", connection); 02804 02805 /* We need to ref because update_dispatch_status_and_unlock will unref 02806 * the connection if it was shared and libdbus was the only remaining 02807 * refcount holder. 02808 */ 02809 _dbus_connection_ref_unlocked (connection); 02810 02811 _dbus_transport_disconnect (connection->transport); 02812 02813 /* This has the side effect of queuing the disconnect message link 02814 * (unless we don't have enough memory, possibly, so don't assert it). 02815 * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open 02816 * should never again return the newly-disconnected connection. 02817 * 02818 * However, we only unref the shared connection and exit_on_disconnect when 02819 * the disconnect message reaches the head of the message queue, 02820 * NOT when it's first queued. 02821 */ 02822 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02823 02824 /* This calls out to user code */ 02825 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02826 02827 /* Could also call out to user code */ 02828 dbus_connection_unref (connection); 02829 } 02830 02873 void 02874 dbus_connection_close (DBusConnection *connection) 02875 { 02876 _dbus_return_if_fail (connection != NULL); 02877 _dbus_return_if_fail (connection->generation == _dbus_current_generation); 02878 02879 CONNECTION_LOCK (connection); 02880 02881 #ifndef DBUS_DISABLE_CHECKS 02882 if (connection->shareable) 02883 { 02884 CONNECTION_UNLOCK (connection); 02885 02886 _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n"); 02887 return; 02888 } 02889 #endif 02890 02891 _dbus_connection_close_possibly_shared_and_unlock (connection); 02892 } 02893 02894 static dbus_bool_t 02895 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection) 02896 { 02897 HAVE_LOCK_CHECK (connection); 02898 return _dbus_transport_get_is_connected (connection->transport); 02899 } 02900 02914 dbus_bool_t 02915 dbus_connection_get_is_connected (DBusConnection *connection) 02916 { 02917 dbus_bool_t res; 02918 02919 _dbus_return_val_if_fail (connection != NULL, FALSE); 02920 02921 CONNECTION_LOCK (connection); 02922 res = _dbus_connection_get_is_connected_unlocked (connection); 02923 CONNECTION_UNLOCK (connection); 02924 02925 return res; 02926 } 02927 02936 dbus_bool_t 02937 dbus_connection_get_is_authenticated (DBusConnection *connection) 02938 { 02939 dbus_bool_t res; 02940 02941 _dbus_return_val_if_fail (connection != NULL, FALSE); 02942 02943 CONNECTION_LOCK (connection); 02944 res = _dbus_transport_get_is_authenticated (connection->transport); 02945 CONNECTION_UNLOCK (connection); 02946 02947 return res; 02948 } 02949 02970 dbus_bool_t 02971 dbus_connection_get_is_anonymous (DBusConnection *connection) 02972 { 02973 dbus_bool_t res; 02974 02975 _dbus_return_val_if_fail (connection != NULL, FALSE); 02976 02977 CONNECTION_LOCK (connection); 02978 res = _dbus_transport_get_is_anonymous (connection->transport); 02979 CONNECTION_UNLOCK (connection); 02980 02981 return res; 02982 } 02983 03015 char* 03016 dbus_connection_get_server_id (DBusConnection *connection) 03017 { 03018 char *id; 03019 03020 _dbus_return_val_if_fail (connection != NULL, NULL); 03021 03022 CONNECTION_LOCK (connection); 03023 id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport)); 03024 CONNECTION_UNLOCK (connection); 03025 03026 return id; 03027 } 03028 03046 dbus_bool_t 03047 dbus_connection_can_send_type(DBusConnection *connection, 03048 int type) 03049 { 03050 _dbus_return_val_if_fail (connection != NULL, FALSE); 03051 03052 if (!_dbus_type_is_valid(type)) 03053 return FALSE; 03054 03055 if (type != DBUS_TYPE_UNIX_FD) 03056 return TRUE; 03057 03058 #ifdef HAVE_UNIX_FD_PASSING 03059 { 03060 dbus_bool_t b; 03061 03062 CONNECTION_LOCK(connection); 03063 b = _dbus_transport_can_pass_unix_fd(connection->transport); 03064 CONNECTION_UNLOCK(connection); 03065 03066 return b; 03067 } 03068 #endif 03069 03070 return FALSE; 03071 } 03072 03086 void 03087 dbus_connection_set_exit_on_disconnect (DBusConnection *connection, 03088 dbus_bool_t exit_on_disconnect) 03089 { 03090 _dbus_return_if_fail (connection != NULL); 03091 03092 CONNECTION_LOCK (connection); 03093 connection->exit_on_disconnect = exit_on_disconnect != FALSE; 03094 CONNECTION_UNLOCK (connection); 03095 } 03096 03106 DBusPreallocatedSend* 03107 dbus_connection_preallocate_send (DBusConnection *connection) 03108 { 03109 DBusPreallocatedSend *preallocated; 03110 03111 _dbus_return_val_if_fail (connection != NULL, NULL); 03112 03113 CONNECTION_LOCK (connection); 03114 03115 preallocated = 03116 _dbus_connection_preallocate_send_unlocked (connection); 03117 03118 CONNECTION_UNLOCK (connection); 03119 03120 return preallocated; 03121 } 03122 03132 void 03133 dbus_connection_free_preallocated_send (DBusConnection *connection, 03134 DBusPreallocatedSend *preallocated) 03135 { 03136 _dbus_return_if_fail (connection != NULL); 03137 _dbus_return_if_fail (preallocated != NULL); 03138 _dbus_return_if_fail (connection == preallocated->connection); 03139 03140 _dbus_list_free_link (preallocated->queue_link); 03141 _dbus_counter_unref (preallocated->counter_link->data); 03142 _dbus_list_free_link (preallocated->counter_link); 03143 dbus_free (preallocated); 03144 } 03145 03158 void 03159 dbus_connection_send_preallocated (DBusConnection *connection, 03160 DBusPreallocatedSend *preallocated, 03161 DBusMessage *message, 03162 dbus_uint32_t *client_serial) 03163 { 03164 _dbus_return_if_fail (connection != NULL); 03165 _dbus_return_if_fail (preallocated != NULL); 03166 _dbus_return_if_fail (message != NULL); 03167 _dbus_return_if_fail (preallocated->connection == connection); 03168 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL || 03169 dbus_message_get_member (message) != NULL); 03170 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL || 03171 (dbus_message_get_interface (message) != NULL && 03172 dbus_message_get_member (message) != NULL)); 03173 03174 CONNECTION_LOCK (connection); 03175 03176 #ifdef HAVE_UNIX_FD_PASSING 03177 03178 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03179 message->n_unix_fds > 0) 03180 { 03181 /* Refuse to send fds on a connection that cannot handle 03182 them. Unfortunately we cannot return a proper error here, so 03183 the best we can is just return. */ 03184 CONNECTION_UNLOCK (connection); 03185 return; 03186 } 03187 03188 #endif 03189 03190 _dbus_connection_send_preallocated_and_unlock (connection, 03191 preallocated, 03192 message, client_serial); 03193 } 03194 03195 static dbus_bool_t 03196 _dbus_connection_send_unlocked_no_update (DBusConnection *connection, 03197 DBusMessage *message, 03198 dbus_uint32_t *client_serial) 03199 { 03200 DBusPreallocatedSend *preallocated; 03201 03202 _dbus_assert (connection != NULL); 03203 _dbus_assert (message != NULL); 03204 03205 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 03206 if (preallocated == NULL) 03207 return FALSE; 03208 03209 _dbus_connection_send_preallocated_unlocked_no_update (connection, 03210 preallocated, 03211 message, 03212 client_serial); 03213 return TRUE; 03214 } 03215 03243 dbus_bool_t 03244 dbus_connection_send (DBusConnection *connection, 03245 DBusMessage *message, 03246 dbus_uint32_t *serial) 03247 { 03248 _dbus_return_val_if_fail (connection != NULL, FALSE); 03249 _dbus_return_val_if_fail (message != NULL, FALSE); 03250 03251 CONNECTION_LOCK (connection); 03252 03253 #ifdef HAVE_UNIX_FD_PASSING 03254 03255 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03256 message->n_unix_fds > 0) 03257 { 03258 /* Refuse to send fds on a connection that cannot handle 03259 them. Unfortunately we cannot return a proper error here, so 03260 the best we can is just return. */ 03261 CONNECTION_UNLOCK (connection); 03262 return FALSE; 03263 } 03264 03265 #endif 03266 03267 return _dbus_connection_send_and_unlock (connection, 03268 message, 03269 serial); 03270 } 03271 03272 static dbus_bool_t 03273 reply_handler_timeout (void *data) 03274 { 03275 DBusConnection *connection; 03276 DBusDispatchStatus status; 03277 DBusPendingCall *pending = data; 03278 03279 connection = _dbus_pending_call_get_connection_and_lock (pending); 03280 03281 _dbus_pending_call_queue_timeout_error_unlocked (pending, 03282 connection); 03283 _dbus_connection_remove_timeout_unlocked (connection, 03284 _dbus_pending_call_get_timeout_unlocked (pending)); 03285 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 03286 03287 _dbus_verbose ("middle\n"); 03288 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03289 03290 /* Unlocks, and calls out to user code */ 03291 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03292 03293 return TRUE; 03294 } 03295 03338 dbus_bool_t 03339 dbus_connection_send_with_reply (DBusConnection *connection, 03340 DBusMessage *message, 03341 DBusPendingCall **pending_return, 03342 int timeout_milliseconds) 03343 { 03344 DBusPendingCall *pending; 03345 dbus_int32_t serial = -1; 03346 DBusDispatchStatus status; 03347 03348 _dbus_return_val_if_fail (connection != NULL, FALSE); 03349 _dbus_return_val_if_fail (message != NULL, FALSE); 03350 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03351 03352 if (pending_return) 03353 *pending_return = NULL; 03354 03355 CONNECTION_LOCK (connection); 03356 03357 #ifdef HAVE_UNIX_FD_PASSING 03358 03359 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03360 message->n_unix_fds > 0) 03361 { 03362 /* Refuse to send fds on a connection that cannot handle 03363 them. Unfortunately we cannot return a proper error here, so 03364 the best we can do is return TRUE but leave *pending_return 03365 as NULL. */ 03366 CONNECTION_UNLOCK (connection); 03367 return TRUE; 03368 } 03369 03370 #endif 03371 03372 if (!_dbus_connection_get_is_connected_unlocked (connection)) 03373 { 03374 CONNECTION_UNLOCK (connection); 03375 03376 return TRUE; 03377 } 03378 03379 pending = _dbus_pending_call_new_unlocked (connection, 03380 timeout_milliseconds, 03381 reply_handler_timeout); 03382 03383 if (pending == NULL) 03384 { 03385 CONNECTION_UNLOCK (connection); 03386 return FALSE; 03387 } 03388 03389 /* Assign a serial to the message */ 03390 serial = dbus_message_get_serial (message); 03391 if (serial == 0) 03392 { 03393 serial = _dbus_connection_get_next_client_serial (connection); 03394 dbus_message_set_serial (message, serial); 03395 } 03396 03397 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial)) 03398 goto error; 03399 03400 /* Insert the serial in the pending replies hash; 03401 * hash takes a refcount on DBusPendingCall. 03402 * Also, add the timeout. 03403 */ 03404 if (!_dbus_connection_attach_pending_call_unlocked (connection, 03405 pending)) 03406 goto error; 03407 03408 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL)) 03409 { 03410 _dbus_connection_detach_pending_call_and_unlock (connection, 03411 pending); 03412 goto error_unlocked; 03413 } 03414 03415 if (pending_return) 03416 *pending_return = pending; /* hand off refcount */ 03417 else 03418 { 03419 _dbus_connection_detach_pending_call_unlocked (connection, pending); 03420 /* we still have a ref to the pending call in this case, we unref 03421 * after unlocking, below 03422 */ 03423 } 03424 03425 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03426 03427 /* this calls out to user code */ 03428 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03429 03430 if (pending_return == NULL) 03431 dbus_pending_call_unref (pending); 03432 03433 return TRUE; 03434 03435 error: 03436 CONNECTION_UNLOCK (connection); 03437 error_unlocked: 03438 dbus_pending_call_unref (pending); 03439 return FALSE; 03440 } 03441 03474 DBusMessage* 03475 dbus_connection_send_with_reply_and_block (DBusConnection *connection, 03476 DBusMessage *message, 03477 int timeout_milliseconds, 03478 DBusError *error) 03479 { 03480 DBusMessage *reply; 03481 DBusPendingCall *pending; 03482 03483 _dbus_return_val_if_fail (connection != NULL, NULL); 03484 _dbus_return_val_if_fail (message != NULL, NULL); 03485 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL); 03486 _dbus_return_val_if_error_is_set (error, NULL); 03487 03488 #ifdef HAVE_UNIX_FD_PASSING 03489 03490 CONNECTION_LOCK (connection); 03491 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03492 message->n_unix_fds > 0) 03493 { 03494 CONNECTION_UNLOCK (connection); 03495 dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection."); 03496 return NULL; 03497 } 03498 CONNECTION_UNLOCK (connection); 03499 03500 #endif 03501 03502 if (!dbus_connection_send_with_reply (connection, message, 03503 &pending, timeout_milliseconds)) 03504 { 03505 _DBUS_SET_OOM (error); 03506 return NULL; 03507 } 03508 03509 if (pending == NULL) 03510 { 03511 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed"); 03512 return NULL; 03513 } 03514 03515 dbus_pending_call_block (pending); 03516 03517 reply = dbus_pending_call_steal_reply (pending); 03518 dbus_pending_call_unref (pending); 03519 03520 /* call_complete_and_unlock() called from pending_call_block() should 03521 * always fill this in. 03522 */ 03523 _dbus_assert (reply != NULL); 03524 03525 if (dbus_set_error_from_message (error, reply)) 03526 { 03527 dbus_message_unref (reply); 03528 return NULL; 03529 } 03530 else 03531 return reply; 03532 } 03533 03542 static DBusDispatchStatus 03543 _dbus_connection_flush_unlocked (DBusConnection *connection) 03544 { 03545 /* We have to specify DBUS_ITERATION_DO_READING here because 03546 * otherwise we could have two apps deadlock if they are both doing 03547 * a flush(), and the kernel buffers fill up. This could change the 03548 * dispatch status. 03549 */ 03550 DBusDispatchStatus status; 03551 03552 HAVE_LOCK_CHECK (connection); 03553 03554 while (connection->n_outgoing > 0 && 03555 _dbus_connection_get_is_connected_unlocked (connection)) 03556 { 03557 _dbus_verbose ("doing iteration in\n"); 03558 HAVE_LOCK_CHECK (connection); 03559 _dbus_connection_do_iteration_unlocked (connection, 03560 NULL, 03561 DBUS_ITERATION_DO_READING | 03562 DBUS_ITERATION_DO_WRITING | 03563 DBUS_ITERATION_BLOCK, 03564 -1); 03565 } 03566 03567 HAVE_LOCK_CHECK (connection); 03568 _dbus_verbose ("middle\n"); 03569 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03570 03571 HAVE_LOCK_CHECK (connection); 03572 return status; 03573 } 03574 03580 void 03581 dbus_connection_flush (DBusConnection *connection) 03582 { 03583 /* We have to specify DBUS_ITERATION_DO_READING here because 03584 * otherwise we could have two apps deadlock if they are both doing 03585 * a flush(), and the kernel buffers fill up. This could change the 03586 * dispatch status. 03587 */ 03588 DBusDispatchStatus status; 03589 03590 _dbus_return_if_fail (connection != NULL); 03591 03592 CONNECTION_LOCK (connection); 03593 03594 status = _dbus_connection_flush_unlocked (connection); 03595 03596 HAVE_LOCK_CHECK (connection); 03597 /* Unlocks and calls out to user code */ 03598 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03599 03600 _dbus_verbose ("end\n"); 03601 } 03602 03613 static dbus_bool_t 03614 _dbus_connection_read_write_dispatch (DBusConnection *connection, 03615 int timeout_milliseconds, 03616 dbus_bool_t dispatch) 03617 { 03618 DBusDispatchStatus dstatus; 03619 dbus_bool_t progress_possible; 03620 03621 /* Need to grab a ref here in case we're a private connection and 03622 * the user drops the last ref in a handler we call; see bug 03623 * https://bugs.freedesktop.org/show_bug.cgi?id=15635 03624 */ 03625 dbus_connection_ref (connection); 03626 dstatus = dbus_connection_get_dispatch_status (connection); 03627 03628 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS) 03629 { 03630 _dbus_verbose ("doing dispatch\n"); 03631 dbus_connection_dispatch (connection); 03632 CONNECTION_LOCK (connection); 03633 } 03634 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY) 03635 { 03636 _dbus_verbose ("pausing for memory\n"); 03637 _dbus_memory_pause_based_on_timeout (timeout_milliseconds); 03638 CONNECTION_LOCK (connection); 03639 } 03640 else 03641 { 03642 CONNECTION_LOCK (connection); 03643 if (_dbus_connection_get_is_connected_unlocked (connection)) 03644 { 03645 _dbus_verbose ("doing iteration\n"); 03646 _dbus_connection_do_iteration_unlocked (connection, 03647 NULL, 03648 DBUS_ITERATION_DO_READING | 03649 DBUS_ITERATION_DO_WRITING | 03650 DBUS_ITERATION_BLOCK, 03651 timeout_milliseconds); 03652 } 03653 } 03654 03655 HAVE_LOCK_CHECK (connection); 03656 /* If we can dispatch, we can make progress until the Disconnected message 03657 * has been processed; if we can only read/write, we can make progress 03658 * as long as the transport is open. 03659 */ 03660 if (dispatch) 03661 progress_possible = connection->n_incoming != 0 || 03662 connection->disconnect_message_link != NULL; 03663 else 03664 progress_possible = _dbus_connection_get_is_connected_unlocked (connection); 03665 03666 CONNECTION_UNLOCK (connection); 03667 03668 dbus_connection_unref (connection); 03669 03670 return progress_possible; /* TRUE if we can make more progress */ 03671 } 03672 03673 03708 dbus_bool_t 03709 dbus_connection_read_write_dispatch (DBusConnection *connection, 03710 int timeout_milliseconds) 03711 { 03712 _dbus_return_val_if_fail (connection != NULL, FALSE); 03713 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03714 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE); 03715 } 03716 03740 dbus_bool_t 03741 dbus_connection_read_write (DBusConnection *connection, 03742 int timeout_milliseconds) 03743 { 03744 _dbus_return_val_if_fail (connection != NULL, FALSE); 03745 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03746 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE); 03747 } 03748 03749 /* We need to call this anytime we pop the head of the queue, and then 03750 * update_dispatch_status_and_unlock needs to be called afterward 03751 * which will "process" the disconnected message and set 03752 * disconnected_message_processed. 03753 */ 03754 static void 03755 check_disconnected_message_arrived_unlocked (DBusConnection *connection, 03756 DBusMessage *head_of_queue) 03757 { 03758 HAVE_LOCK_CHECK (connection); 03759 03760 /* checking that the link is NULL is an optimization to avoid the is_signal call */ 03761 if (connection->disconnect_message_link == NULL && 03762 dbus_message_is_signal (head_of_queue, 03763 DBUS_INTERFACE_LOCAL, 03764 "Disconnected")) 03765 { 03766 connection->disconnected_message_arrived = TRUE; 03767 } 03768 } 03769 03789 DBusMessage* 03790 dbus_connection_borrow_message (DBusConnection *connection) 03791 { 03792 DBusDispatchStatus status; 03793 DBusMessage *message; 03794 03795 _dbus_return_val_if_fail (connection != NULL, NULL); 03796 03797 _dbus_verbose ("start\n"); 03798 03799 /* this is called for the side effect that it queues 03800 * up any messages from the transport 03801 */ 03802 status = dbus_connection_get_dispatch_status (connection); 03803 if (status != DBUS_DISPATCH_DATA_REMAINS) 03804 return NULL; 03805 03806 CONNECTION_LOCK (connection); 03807 03808 _dbus_connection_acquire_dispatch (connection); 03809 03810 /* While a message is outstanding, the dispatch lock is held */ 03811 _dbus_assert (connection->message_borrowed == NULL); 03812 03813 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages); 03814 03815 message = connection->message_borrowed; 03816 03817 check_disconnected_message_arrived_unlocked (connection, message); 03818 03819 /* Note that we KEEP the dispatch lock until the message is returned */ 03820 if (message == NULL) 03821 _dbus_connection_release_dispatch (connection); 03822 03823 CONNECTION_UNLOCK (connection); 03824 03825 /* We don't update dispatch status until it's returned or stolen */ 03826 03827 return message; 03828 } 03829 03838 void 03839 dbus_connection_return_message (DBusConnection *connection, 03840 DBusMessage *message) 03841 { 03842 DBusDispatchStatus status; 03843 03844 _dbus_return_if_fail (connection != NULL); 03845 _dbus_return_if_fail (message != NULL); 03846 _dbus_return_if_fail (message == connection->message_borrowed); 03847 _dbus_return_if_fail (connection->dispatch_acquired); 03848 03849 CONNECTION_LOCK (connection); 03850 03851 _dbus_assert (message == connection->message_borrowed); 03852 03853 connection->message_borrowed = NULL; 03854 03855 _dbus_connection_release_dispatch (connection); 03856 03857 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03858 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03859 } 03860 03870 void 03871 dbus_connection_steal_borrowed_message (DBusConnection *connection, 03872 DBusMessage *message) 03873 { 03874 DBusMessage *pop_message; 03875 DBusDispatchStatus status; 03876 03877 _dbus_return_if_fail (connection != NULL); 03878 _dbus_return_if_fail (message != NULL); 03879 _dbus_return_if_fail (message == connection->message_borrowed); 03880 _dbus_return_if_fail (connection->dispatch_acquired); 03881 03882 CONNECTION_LOCK (connection); 03883 03884 _dbus_assert (message == connection->message_borrowed); 03885 03886 pop_message = _dbus_list_pop_first (&connection->incoming_messages); 03887 _dbus_assert (message == pop_message); 03888 03889 connection->n_incoming -= 1; 03890 03891 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n", 03892 message, connection->n_incoming); 03893 03894 connection->message_borrowed = NULL; 03895 03896 _dbus_connection_release_dispatch (connection); 03897 03898 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03899 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03900 } 03901 03902 /* See dbus_connection_pop_message, but requires the caller to own 03903 * the lock before calling. May drop the lock while running. 03904 */ 03905 static DBusList* 03906 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection) 03907 { 03908 HAVE_LOCK_CHECK (connection); 03909 03910 _dbus_assert (connection->message_borrowed == NULL); 03911 03912 if (connection->n_incoming > 0) 03913 { 03914 DBusList *link; 03915 03916 link = _dbus_list_pop_first_link (&connection->incoming_messages); 03917 connection->n_incoming -= 1; 03918 03919 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from incoming queue %p, %d incoming\n", 03920 link->data, 03921 dbus_message_type_to_string (dbus_message_get_type (link->data)), 03922 dbus_message_get_path (link->data) ? 03923 dbus_message_get_path (link->data) : 03924 "no path", 03925 dbus_message_get_interface (link->data) ? 03926 dbus_message_get_interface (link->data) : 03927 "no interface", 03928 dbus_message_get_member (link->data) ? 03929 dbus_message_get_member (link->data) : 03930 "no member", 03931 dbus_message_get_signature (link->data), 03932 connection, connection->n_incoming); 03933 03934 check_disconnected_message_arrived_unlocked (connection, link->data); 03935 03936 return link; 03937 } 03938 else 03939 return NULL; 03940 } 03941 03942 /* See dbus_connection_pop_message, but requires the caller to own 03943 * the lock before calling. May drop the lock while running. 03944 */ 03945 static DBusMessage* 03946 _dbus_connection_pop_message_unlocked (DBusConnection *connection) 03947 { 03948 DBusList *link; 03949 03950 HAVE_LOCK_CHECK (connection); 03951 03952 link = _dbus_connection_pop_message_link_unlocked (connection); 03953 03954 if (link != NULL) 03955 { 03956 DBusMessage *message; 03957 03958 message = link->data; 03959 03960 _dbus_list_free_link (link); 03961 03962 return message; 03963 } 03964 else 03965 return NULL; 03966 } 03967 03968 static void 03969 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection, 03970 DBusList *message_link) 03971 { 03972 HAVE_LOCK_CHECK (connection); 03973 03974 _dbus_assert (message_link != NULL); 03975 /* You can't borrow a message while a link is outstanding */ 03976 _dbus_assert (connection->message_borrowed == NULL); 03977 /* We had to have the dispatch lock across the pop/putback */ 03978 _dbus_assert (connection->dispatch_acquired); 03979 03980 _dbus_list_prepend_link (&connection->incoming_messages, 03981 message_link); 03982 connection->n_incoming += 1; 03983 03984 _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n", 03985 message_link->data, 03986 dbus_message_type_to_string (dbus_message_get_type (message_link->data)), 03987 dbus_message_get_interface (message_link->data) ? 03988 dbus_message_get_interface (message_link->data) : 03989 "no interface", 03990 dbus_message_get_member (message_link->data) ? 03991 dbus_message_get_member (message_link->data) : 03992 "no member", 03993 dbus_message_get_signature (message_link->data), 03994 connection, connection->n_incoming); 03995 } 03996 04016 DBusMessage* 04017 dbus_connection_pop_message (DBusConnection *connection) 04018 { 04019 DBusMessage *message; 04020 DBusDispatchStatus status; 04021 04022 _dbus_verbose ("start\n"); 04023 04024 /* this is called for the side effect that it queues 04025 * up any messages from the transport 04026 */ 04027 status = dbus_connection_get_dispatch_status (connection); 04028 if (status != DBUS_DISPATCH_DATA_REMAINS) 04029 return NULL; 04030 04031 CONNECTION_LOCK (connection); 04032 _dbus_connection_acquire_dispatch (connection); 04033 HAVE_LOCK_CHECK (connection); 04034 04035 message = _dbus_connection_pop_message_unlocked (connection); 04036 04037 _dbus_verbose ("Returning popped message %p\n", message); 04038 04039 _dbus_connection_release_dispatch (connection); 04040 04041 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04042 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04043 04044 return message; 04045 } 04046 04054 static void 04055 _dbus_connection_acquire_dispatch (DBusConnection *connection) 04056 { 04057 HAVE_LOCK_CHECK (connection); 04058 04059 _dbus_connection_ref_unlocked (connection); 04060 CONNECTION_UNLOCK (connection); 04061 04062 _dbus_verbose ("locking dispatch_mutex\n"); 04063 _dbus_mutex_lock (connection->dispatch_mutex); 04064 04065 while (connection->dispatch_acquired) 04066 { 04067 _dbus_verbose ("waiting for dispatch to be acquirable\n"); 04068 _dbus_condvar_wait (connection->dispatch_cond, 04069 connection->dispatch_mutex); 04070 } 04071 04072 _dbus_assert (!connection->dispatch_acquired); 04073 04074 connection->dispatch_acquired = TRUE; 04075 04076 _dbus_verbose ("unlocking dispatch_mutex\n"); 04077 _dbus_mutex_unlock (connection->dispatch_mutex); 04078 04079 CONNECTION_LOCK (connection); 04080 _dbus_connection_unref_unlocked (connection); 04081 } 04082 04090 static void 04091 _dbus_connection_release_dispatch (DBusConnection *connection) 04092 { 04093 HAVE_LOCK_CHECK (connection); 04094 04095 _dbus_verbose ("locking dispatch_mutex\n"); 04096 _dbus_mutex_lock (connection->dispatch_mutex); 04097 04098 _dbus_assert (connection->dispatch_acquired); 04099 04100 connection->dispatch_acquired = FALSE; 04101 _dbus_condvar_wake_one (connection->dispatch_cond); 04102 04103 _dbus_verbose ("unlocking dispatch_mutex\n"); 04104 _dbus_mutex_unlock (connection->dispatch_mutex); 04105 } 04106 04107 static void 04108 _dbus_connection_failed_pop (DBusConnection *connection, 04109 DBusList *message_link) 04110 { 04111 _dbus_list_prepend_link (&connection->incoming_messages, 04112 message_link); 04113 connection->n_incoming += 1; 04114 } 04115 04116 /* Note this may be called multiple times since we don't track whether we already did it */ 04117 static void 04118 notify_disconnected_unlocked (DBusConnection *connection) 04119 { 04120 HAVE_LOCK_CHECK (connection); 04121 04122 /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected 04123 * connection from dbus_bus_get(). We make the same guarantee for 04124 * dbus_connection_open() but in a different way since we don't want to 04125 * unref right here; we instead check for connectedness before returning 04126 * the connection from the hash. 04127 */ 04128 _dbus_bus_notify_shared_connection_disconnected_unlocked (connection); 04129 04130 /* Dump the outgoing queue, we aren't going to be able to 04131 * send it now, and we'd like accessors like 04132 * dbus_connection_get_outgoing_size() to be accurate. 04133 */ 04134 if (connection->n_outgoing > 0) 04135 { 04136 DBusList *link; 04137 04138 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n", 04139 connection->n_outgoing); 04140 04141 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages))) 04142 { 04143 _dbus_connection_message_sent (connection, link->data); 04144 } 04145 } 04146 } 04147 04148 /* Note this may be called multiple times since we don't track whether we already did it */ 04149 static DBusDispatchStatus 04150 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection) 04151 { 04152 HAVE_LOCK_CHECK (connection); 04153 04154 if (connection->disconnect_message_link != NULL) 04155 { 04156 _dbus_verbose ("Sending disconnect message\n"); 04157 04158 /* If we have pending calls, queue their timeouts - we want the Disconnected 04159 * to be the last message, after these timeouts. 04160 */ 04161 connection_timeout_and_complete_all_pending_calls_unlocked (connection); 04162 04163 /* We haven't sent the disconnect message already, 04164 * and all real messages have been queued up. 04165 */ 04166 _dbus_connection_queue_synthesized_message_link (connection, 04167 connection->disconnect_message_link); 04168 connection->disconnect_message_link = NULL; 04169 04170 return DBUS_DISPATCH_DATA_REMAINS; 04171 } 04172 04173 return DBUS_DISPATCH_COMPLETE; 04174 } 04175 04176 static DBusDispatchStatus 04177 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection) 04178 { 04179 HAVE_LOCK_CHECK (connection); 04180 04181 if (connection->n_incoming > 0) 04182 return DBUS_DISPATCH_DATA_REMAINS; 04183 else if (!_dbus_transport_queue_messages (connection->transport)) 04184 return DBUS_DISPATCH_NEED_MEMORY; 04185 else 04186 { 04187 DBusDispatchStatus status; 04188 dbus_bool_t is_connected; 04189 04190 status = _dbus_transport_get_dispatch_status (connection->transport); 04191 is_connected = _dbus_transport_get_is_connected (connection->transport); 04192 04193 _dbus_verbose ("dispatch status = %s is_connected = %d\n", 04194 DISPATCH_STATUS_NAME (status), is_connected); 04195 04196 if (!is_connected) 04197 { 04198 /* It's possible this would be better done by having an explicit 04199 * notification from _dbus_transport_disconnect() that would 04200 * synchronously do this, instead of waiting for the next dispatch 04201 * status check. However, probably not good to change until it causes 04202 * a problem. 04203 */ 04204 notify_disconnected_unlocked (connection); 04205 04206 /* I'm not sure this is needed; the idea is that we want to 04207 * queue the Disconnected only after we've read all the 04208 * messages, but if we're disconnected maybe we are guaranteed 04209 * to have read them all ? 04210 */ 04211 if (status == DBUS_DISPATCH_COMPLETE) 04212 status = notify_disconnected_and_dispatch_complete_unlocked (connection); 04213 } 04214 04215 if (status != DBUS_DISPATCH_COMPLETE) 04216 return status; 04217 else if (connection->n_incoming > 0) 04218 return DBUS_DISPATCH_DATA_REMAINS; 04219 else 04220 return DBUS_DISPATCH_COMPLETE; 04221 } 04222 } 04223 04224 static void 04225 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection, 04226 DBusDispatchStatus new_status) 04227 { 04228 dbus_bool_t changed; 04229 DBusDispatchStatusFunction function; 04230 void *data; 04231 04232 HAVE_LOCK_CHECK (connection); 04233 04234 _dbus_connection_ref_unlocked (connection); 04235 04236 changed = new_status != connection->last_dispatch_status; 04237 04238 connection->last_dispatch_status = new_status; 04239 04240 function = connection->dispatch_status_function; 04241 data = connection->dispatch_status_data; 04242 04243 if (connection->disconnected_message_arrived && 04244 !connection->disconnected_message_processed) 04245 { 04246 connection->disconnected_message_processed = TRUE; 04247 04248 /* this does an unref, but we have a ref 04249 * so we should not run the finalizer here 04250 * inside the lock. 04251 */ 04252 connection_forget_shared_unlocked (connection); 04253 04254 if (connection->exit_on_disconnect) 04255 { 04256 CONNECTION_UNLOCK (connection); 04257 04258 _dbus_verbose ("Exiting on Disconnected signal\n"); 04259 _dbus_exit (1); 04260 _dbus_assert_not_reached ("Call to exit() returned"); 04261 } 04262 } 04263 04264 /* We drop the lock */ 04265 CONNECTION_UNLOCK (connection); 04266 04267 if (changed && function) 04268 { 04269 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n", 04270 connection, new_status, 04271 DISPATCH_STATUS_NAME (new_status)); 04272 (* function) (connection, new_status, data); 04273 } 04274 04275 dbus_connection_unref (connection); 04276 } 04277 04303 DBusDispatchStatus 04304 dbus_connection_get_dispatch_status (DBusConnection *connection) 04305 { 04306 DBusDispatchStatus status; 04307 04308 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE); 04309 04310 _dbus_verbose ("start\n"); 04311 04312 CONNECTION_LOCK (connection); 04313 04314 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04315 04316 CONNECTION_UNLOCK (connection); 04317 04318 return status; 04319 } 04320 04324 static DBusHandlerResult 04325 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection, 04326 DBusMessage *message) 04327 { 04328 if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL) 04329 { 04330 /* This means we're letting the bus route this message */ 04331 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04332 } 04333 else if (dbus_message_is_method_call (message, 04334 DBUS_INTERFACE_PEER, 04335 "Ping")) 04336 { 04337 DBusMessage *ret; 04338 dbus_bool_t sent; 04339 04340 ret = dbus_message_new_method_return (message); 04341 if (ret == NULL) 04342 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04343 04344 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04345 04346 dbus_message_unref (ret); 04347 04348 if (!sent) 04349 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04350 04351 return DBUS_HANDLER_RESULT_HANDLED; 04352 } 04353 else if (dbus_message_is_method_call (message, 04354 DBUS_INTERFACE_PEER, 04355 "GetMachineId")) 04356 { 04357 DBusMessage *ret; 04358 dbus_bool_t sent; 04359 DBusString uuid; 04360 04361 ret = dbus_message_new_method_return (message); 04362 if (ret == NULL) 04363 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04364 04365 sent = FALSE; 04366 _dbus_string_init (&uuid); 04367 if (_dbus_get_local_machine_uuid_encoded (&uuid)) 04368 { 04369 const char *v_STRING = _dbus_string_get_const_data (&uuid); 04370 if (dbus_message_append_args (ret, 04371 DBUS_TYPE_STRING, &v_STRING, 04372 DBUS_TYPE_INVALID)) 04373 { 04374 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04375 } 04376 } 04377 _dbus_string_free (&uuid); 04378 04379 dbus_message_unref (ret); 04380 04381 if (!sent) 04382 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04383 04384 return DBUS_HANDLER_RESULT_HANDLED; 04385 } 04386 else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER)) 04387 { 04388 /* We need to bounce anything else with this interface, otherwise apps 04389 * could start extending the interface and when we added extensions 04390 * here to DBusConnection we'd break those apps. 04391 */ 04392 04393 DBusMessage *ret; 04394 dbus_bool_t sent; 04395 04396 ret = dbus_message_new_error (message, 04397 DBUS_ERROR_UNKNOWN_METHOD, 04398 "Unknown method invoked on org.freedesktop.DBus.Peer interface"); 04399 if (ret == NULL) 04400 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04401 04402 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04403 04404 dbus_message_unref (ret); 04405 04406 if (!sent) 04407 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04408 04409 return DBUS_HANDLER_RESULT_HANDLED; 04410 } 04411 else 04412 { 04413 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04414 } 04415 } 04416 04423 static DBusHandlerResult 04424 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection, 04425 DBusMessage *message) 04426 { 04427 /* We just run one filter for now but have the option to run more 04428 if the spec calls for it in the future */ 04429 04430 return _dbus_connection_peer_filter_unlocked_no_update (connection, message); 04431 } 04432 04475 DBusDispatchStatus 04476 dbus_connection_dispatch (DBusConnection *connection) 04477 { 04478 DBusMessage *message; 04479 DBusList *link, *filter_list_copy, *message_link; 04480 DBusHandlerResult result; 04481 DBusPendingCall *pending; 04482 dbus_int32_t reply_serial; 04483 DBusDispatchStatus status; 04484 04485 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE); 04486 04487 _dbus_verbose ("\n"); 04488 04489 CONNECTION_LOCK (connection); 04490 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04491 if (status != DBUS_DISPATCH_DATA_REMAINS) 04492 { 04493 /* unlocks and calls out to user code */ 04494 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04495 return status; 04496 } 04497 04498 /* We need to ref the connection since the callback could potentially 04499 * drop the last ref to it 04500 */ 04501 _dbus_connection_ref_unlocked (connection); 04502 04503 _dbus_connection_acquire_dispatch (connection); 04504 HAVE_LOCK_CHECK (connection); 04505 04506 message_link = _dbus_connection_pop_message_link_unlocked (connection); 04507 if (message_link == NULL) 04508 { 04509 /* another thread dispatched our stuff */ 04510 04511 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n"); 04512 04513 _dbus_connection_release_dispatch (connection); 04514 04515 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04516 04517 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04518 04519 dbus_connection_unref (connection); 04520 04521 return status; 04522 } 04523 04524 message = message_link->data; 04525 04526 _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n", 04527 message, 04528 dbus_message_type_to_string (dbus_message_get_type (message)), 04529 dbus_message_get_interface (message) ? 04530 dbus_message_get_interface (message) : 04531 "no interface", 04532 dbus_message_get_member (message) ? 04533 dbus_message_get_member (message) : 04534 "no member", 04535 dbus_message_get_signature (message)); 04536 04537 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04538 04539 /* Pending call handling must be first, because if you do 04540 * dbus_connection_send_with_reply_and_block() or 04541 * dbus_pending_call_block() then no handlers/filters will be run on 04542 * the reply. We want consistent semantics in the case where we 04543 * dbus_connection_dispatch() the reply. 04544 */ 04545 04546 reply_serial = dbus_message_get_reply_serial (message); 04547 pending = _dbus_hash_table_lookup_int (connection->pending_replies, 04548 reply_serial); 04549 if (pending) 04550 { 04551 _dbus_verbose ("Dispatching a pending reply\n"); 04552 complete_pending_call_and_unlock (connection, pending, message); 04553 pending = NULL; /* it's probably unref'd */ 04554 04555 CONNECTION_LOCK (connection); 04556 _dbus_verbose ("pending call completed in dispatch\n"); 04557 result = DBUS_HANDLER_RESULT_HANDLED; 04558 goto out; 04559 } 04560 04561 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message); 04562 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04563 goto out; 04564 04565 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy)) 04566 { 04567 _dbus_connection_release_dispatch (connection); 04568 HAVE_LOCK_CHECK (connection); 04569 04570 _dbus_connection_failed_pop (connection, message_link); 04571 04572 /* unlocks and calls user code */ 04573 _dbus_connection_update_dispatch_status_and_unlock (connection, 04574 DBUS_DISPATCH_NEED_MEMORY); 04575 dbus_connection_unref (connection); 04576 04577 return DBUS_DISPATCH_NEED_MEMORY; 04578 } 04579 04580 _dbus_list_foreach (&filter_list_copy, 04581 (DBusForeachFunction)_dbus_message_filter_ref, 04582 NULL); 04583 04584 /* We're still protected from dispatch() reentrancy here 04585 * since we acquired the dispatcher 04586 */ 04587 CONNECTION_UNLOCK (connection); 04588 04589 link = _dbus_list_get_first_link (&filter_list_copy); 04590 while (link != NULL) 04591 { 04592 DBusMessageFilter *filter = link->data; 04593 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link); 04594 04595 if (filter->function == NULL) 04596 { 04597 _dbus_verbose (" filter was removed in a callback function\n"); 04598 link = next; 04599 continue; 04600 } 04601 04602 _dbus_verbose (" running filter on message %p\n", message); 04603 result = (* filter->function) (connection, message, filter->user_data); 04604 04605 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04606 break; 04607 04608 link = next; 04609 } 04610 04611 _dbus_list_foreach (&filter_list_copy, 04612 (DBusForeachFunction)_dbus_message_filter_unref, 04613 NULL); 04614 _dbus_list_clear (&filter_list_copy); 04615 04616 CONNECTION_LOCK (connection); 04617 04618 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) 04619 { 04620 _dbus_verbose ("No memory\n"); 04621 goto out; 04622 } 04623 else if (result == DBUS_HANDLER_RESULT_HANDLED) 04624 { 04625 _dbus_verbose ("filter handled message in dispatch\n"); 04626 goto out; 04627 } 04628 04629 /* We're still protected from dispatch() reentrancy here 04630 * since we acquired the dispatcher 04631 */ 04632 _dbus_verbose (" running object path dispatch on message %p (%s %s %s '%s')\n", 04633 message, 04634 dbus_message_type_to_string (dbus_message_get_type (message)), 04635 dbus_message_get_interface (message) ? 04636 dbus_message_get_interface (message) : 04637 "no interface", 04638 dbus_message_get_member (message) ? 04639 dbus_message_get_member (message) : 04640 "no member", 04641 dbus_message_get_signature (message)); 04642 04643 HAVE_LOCK_CHECK (connection); 04644 result = _dbus_object_tree_dispatch_and_unlock (connection->objects, 04645 message); 04646 04647 CONNECTION_LOCK (connection); 04648 04649 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04650 { 04651 _dbus_verbose ("object tree handled message in dispatch\n"); 04652 goto out; 04653 } 04654 04655 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL) 04656 { 04657 DBusMessage *reply; 04658 DBusString str; 04659 DBusPreallocatedSend *preallocated; 04660 04661 _dbus_verbose (" sending error %s\n", 04662 DBUS_ERROR_UNKNOWN_METHOD); 04663 04664 if (!_dbus_string_init (&str)) 04665 { 04666 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04667 _dbus_verbose ("no memory for error string in dispatch\n"); 04668 goto out; 04669 } 04670 04671 if (!_dbus_string_append_printf (&str, 04672 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n", 04673 dbus_message_get_member (message), 04674 dbus_message_get_signature (message), 04675 dbus_message_get_interface (message))) 04676 { 04677 _dbus_string_free (&str); 04678 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04679 _dbus_verbose ("no memory for error string in dispatch\n"); 04680 goto out; 04681 } 04682 04683 reply = dbus_message_new_error (message, 04684 DBUS_ERROR_UNKNOWN_METHOD, 04685 _dbus_string_get_const_data (&str)); 04686 _dbus_string_free (&str); 04687 04688 if (reply == NULL) 04689 { 04690 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04691 _dbus_verbose ("no memory for error reply in dispatch\n"); 04692 goto out; 04693 } 04694 04695 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 04696 04697 if (preallocated == NULL) 04698 { 04699 dbus_message_unref (reply); 04700 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04701 _dbus_verbose ("no memory for error send in dispatch\n"); 04702 goto out; 04703 } 04704 04705 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated, 04706 reply, NULL); 04707 04708 dbus_message_unref (reply); 04709 04710 result = DBUS_HANDLER_RESULT_HANDLED; 04711 } 04712 04713 _dbus_verbose (" done dispatching %p (%s %s %s '%s') on connection %p\n", message, 04714 dbus_message_type_to_string (dbus_message_get_type (message)), 04715 dbus_message_get_interface (message) ? 04716 dbus_message_get_interface (message) : 04717 "no interface", 04718 dbus_message_get_member (message) ? 04719 dbus_message_get_member (message) : 04720 "no member", 04721 dbus_message_get_signature (message), 04722 connection); 04723 04724 out: 04725 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) 04726 { 04727 _dbus_verbose ("out of memory\n"); 04728 04729 /* Put message back, and we'll start over. 04730 * Yes this means handlers must be idempotent if they 04731 * don't return HANDLED; c'est la vie. 04732 */ 04733 _dbus_connection_putback_message_link_unlocked (connection, 04734 message_link); 04735 } 04736 else 04737 { 04738 _dbus_verbose (" ... done dispatching\n"); 04739 04740 _dbus_list_free_link (message_link); 04741 dbus_message_unref (message); /* don't want the message to count in max message limits 04742 * in computing dispatch status below 04743 */ 04744 } 04745 04746 _dbus_connection_release_dispatch (connection); 04747 HAVE_LOCK_CHECK (connection); 04748 04749 _dbus_verbose ("before final status update\n"); 04750 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04751 04752 /* unlocks and calls user code */ 04753 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04754 04755 dbus_connection_unref (connection); 04756 04757 return status; 04758 } 04759 04821 dbus_bool_t 04822 dbus_connection_set_watch_functions (DBusConnection *connection, 04823 DBusAddWatchFunction add_function, 04824 DBusRemoveWatchFunction remove_function, 04825 DBusWatchToggledFunction toggled_function, 04826 void *data, 04827 DBusFreeFunction free_data_function) 04828 { 04829 dbus_bool_t retval; 04830 04831 _dbus_return_val_if_fail (connection != NULL, FALSE); 04832 04833 CONNECTION_LOCK (connection); 04834 04835 retval = _dbus_watch_list_set_functions (connection->watches, 04836 add_function, remove_function, 04837 toggled_function, 04838 data, free_data_function); 04839 04840 CONNECTION_UNLOCK (connection); 04841 04842 return retval; 04843 } 04844 04884 dbus_bool_t 04885 dbus_connection_set_timeout_functions (DBusConnection *connection, 04886 DBusAddTimeoutFunction add_function, 04887 DBusRemoveTimeoutFunction remove_function, 04888 DBusTimeoutToggledFunction toggled_function, 04889 void *data, 04890 DBusFreeFunction free_data_function) 04891 { 04892 dbus_bool_t retval; 04893 04894 _dbus_return_val_if_fail (connection != NULL, FALSE); 04895 04896 CONNECTION_LOCK (connection); 04897 04898 retval = _dbus_timeout_list_set_functions (connection->timeouts, 04899 add_function, remove_function, 04900 toggled_function, 04901 data, free_data_function); 04902 04903 CONNECTION_UNLOCK (connection); 04904 04905 return retval; 04906 } 04907 04922 void 04923 dbus_connection_set_wakeup_main_function (DBusConnection *connection, 04924 DBusWakeupMainFunction wakeup_main_function, 04925 void *data, 04926 DBusFreeFunction free_data_function) 04927 { 04928 void *old_data; 04929 DBusFreeFunction old_free_data; 04930 04931 _dbus_return_if_fail (connection != NULL); 04932 04933 CONNECTION_LOCK (connection); 04934 old_data = connection->wakeup_main_data; 04935 old_free_data = connection->free_wakeup_main_data; 04936 04937 connection->wakeup_main_function = wakeup_main_function; 04938 connection->wakeup_main_data = data; 04939 connection->free_wakeup_main_data = free_data_function; 04940 04941 CONNECTION_UNLOCK (connection); 04942 04943 /* Callback outside the lock */ 04944 if (old_free_data) 04945 (*old_free_data) (old_data); 04946 } 04947 04968 void 04969 dbus_connection_set_dispatch_status_function (DBusConnection *connection, 04970 DBusDispatchStatusFunction function, 04971 void *data, 04972 DBusFreeFunction free_data_function) 04973 { 04974 void *old_data; 04975 DBusFreeFunction old_free_data; 04976 04977 _dbus_return_if_fail (connection != NULL); 04978 04979 CONNECTION_LOCK (connection); 04980 old_data = connection->dispatch_status_data; 04981 old_free_data = connection->free_dispatch_status_data; 04982 04983 connection->dispatch_status_function = function; 04984 connection->dispatch_status_data = data; 04985 connection->free_dispatch_status_data = free_data_function; 04986 04987 CONNECTION_UNLOCK (connection); 04988 04989 /* Callback outside the lock */ 04990 if (old_free_data) 04991 (*old_free_data) (old_data); 04992 } 04993 05013 dbus_bool_t 05014 dbus_connection_get_unix_fd (DBusConnection *connection, 05015 int *fd) 05016 { 05017 _dbus_return_val_if_fail (connection != NULL, FALSE); 05018 _dbus_return_val_if_fail (connection->transport != NULL, FALSE); 05019 05020 #ifdef DBUS_WIN 05021 /* FIXME do this on a lower level */ 05022 return FALSE; 05023 #endif 05024 05025 return dbus_connection_get_socket(connection, fd); 05026 } 05027 05043 dbus_bool_t 05044 dbus_connection_get_socket(DBusConnection *connection, 05045 int *fd) 05046 { 05047 dbus_bool_t retval; 05048 05049 _dbus_return_val_if_fail (connection != NULL, FALSE); 05050 _dbus_return_val_if_fail (connection->transport != NULL, FALSE); 05051 05052 CONNECTION_LOCK (connection); 05053 05054 retval = _dbus_transport_get_socket_fd (connection->transport, 05055 fd); 05056 05057 CONNECTION_UNLOCK (connection); 05058 05059 return retval; 05060 } 05061 05062 05085 dbus_bool_t 05086 dbus_connection_get_unix_user (DBusConnection *connection, 05087 unsigned long *uid) 05088 { 05089 dbus_bool_t result; 05090 05091 _dbus_return_val_if_fail (connection != NULL, FALSE); 05092 _dbus_return_val_if_fail (uid != NULL, FALSE); 05093 05094 CONNECTION_LOCK (connection); 05095 05096 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05097 result = FALSE; 05098 else 05099 result = _dbus_transport_get_unix_user (connection->transport, 05100 uid); 05101 05102 #ifdef DBUS_WIN 05103 _dbus_assert (!result); 05104 #endif 05105 05106 CONNECTION_UNLOCK (connection); 05107 05108 return result; 05109 } 05110 05121 dbus_bool_t 05122 dbus_connection_get_unix_process_id (DBusConnection *connection, 05123 unsigned long *pid) 05124 { 05125 dbus_bool_t result; 05126 05127 _dbus_return_val_if_fail (connection != NULL, FALSE); 05128 _dbus_return_val_if_fail (pid != NULL, FALSE); 05129 05130 CONNECTION_LOCK (connection); 05131 05132 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05133 result = FALSE; 05134 else 05135 result = _dbus_transport_get_unix_process_id (connection->transport, 05136 pid); 05137 05138 CONNECTION_UNLOCK (connection); 05139 05140 return result; 05141 } 05142 05153 dbus_bool_t 05154 dbus_connection_get_adt_audit_session_data (DBusConnection *connection, 05155 void **data, 05156 dbus_int32_t *data_size) 05157 { 05158 dbus_bool_t result; 05159 05160 _dbus_return_val_if_fail (connection != NULL, FALSE); 05161 _dbus_return_val_if_fail (data != NULL, FALSE); 05162 _dbus_return_val_if_fail (data_size != NULL, FALSE); 05163 05164 CONNECTION_LOCK (connection); 05165 05166 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05167 result = FALSE; 05168 else 05169 result = _dbus_transport_get_adt_audit_session_data (connection->transport, 05170 data, 05171 data_size); 05172 CONNECTION_UNLOCK (connection); 05173 05174 return result; 05175 } 05176 05199 void 05200 dbus_connection_set_unix_user_function (DBusConnection *connection, 05201 DBusAllowUnixUserFunction function, 05202 void *data, 05203 DBusFreeFunction free_data_function) 05204 { 05205 void *old_data = NULL; 05206 DBusFreeFunction old_free_function = NULL; 05207 05208 _dbus_return_if_fail (connection != NULL); 05209 05210 CONNECTION_LOCK (connection); 05211 _dbus_transport_set_unix_user_function (connection->transport, 05212 function, data, free_data_function, 05213 &old_data, &old_free_function); 05214 CONNECTION_UNLOCK (connection); 05215 05216 if (old_free_function != NULL) 05217 (* old_free_function) (old_data); 05218 } 05219 05251 dbus_bool_t 05252 dbus_connection_get_windows_user (DBusConnection *connection, 05253 char **windows_sid_p) 05254 { 05255 dbus_bool_t result; 05256 05257 _dbus_return_val_if_fail (connection != NULL, FALSE); 05258 _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE); 05259 05260 CONNECTION_LOCK (connection); 05261 05262 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05263 result = FALSE; 05264 else 05265 result = _dbus_transport_get_windows_user (connection->transport, 05266 windows_sid_p); 05267 05268 #ifdef DBUS_UNIX 05269 _dbus_assert (!result); 05270 #endif 05271 05272 CONNECTION_UNLOCK (connection); 05273 05274 return result; 05275 } 05276 05298 void 05299 dbus_connection_set_windows_user_function (DBusConnection *connection, 05300 DBusAllowWindowsUserFunction function, 05301 void *data, 05302 DBusFreeFunction free_data_function) 05303 { 05304 void *old_data = NULL; 05305 DBusFreeFunction old_free_function = NULL; 05306 05307 _dbus_return_if_fail (connection != NULL); 05308 05309 CONNECTION_LOCK (connection); 05310 _dbus_transport_set_windows_user_function (connection->transport, 05311 function, data, free_data_function, 05312 &old_data, &old_free_function); 05313 CONNECTION_UNLOCK (connection); 05314 05315 if (old_free_function != NULL) 05316 (* old_free_function) (old_data); 05317 } 05318 05345 void 05346 dbus_connection_set_allow_anonymous (DBusConnection *connection, 05347 dbus_bool_t value) 05348 { 05349 _dbus_return_if_fail (connection != NULL); 05350 05351 CONNECTION_LOCK (connection); 05352 _dbus_transport_set_allow_anonymous (connection->transport, value); 05353 CONNECTION_UNLOCK (connection); 05354 } 05355 05373 void 05374 dbus_connection_set_route_peer_messages (DBusConnection *connection, 05375 dbus_bool_t value) 05376 { 05377 _dbus_return_if_fail (connection != NULL); 05378 05379 CONNECTION_LOCK (connection); 05380 connection->route_peer_messages = TRUE; 05381 CONNECTION_UNLOCK (connection); 05382 } 05383 05405 dbus_bool_t 05406 dbus_connection_add_filter (DBusConnection *connection, 05407 DBusHandleMessageFunction function, 05408 void *user_data, 05409 DBusFreeFunction free_data_function) 05410 { 05411 DBusMessageFilter *filter; 05412 05413 _dbus_return_val_if_fail (connection != NULL, FALSE); 05414 _dbus_return_val_if_fail (function != NULL, FALSE); 05415 05416 filter = dbus_new0 (DBusMessageFilter, 1); 05417 if (filter == NULL) 05418 return FALSE; 05419 05420 _dbus_atomic_inc (&filter->refcount); 05421 05422 CONNECTION_LOCK (connection); 05423 05424 if (!_dbus_list_append (&connection->filter_list, 05425 filter)) 05426 { 05427 _dbus_message_filter_unref (filter); 05428 CONNECTION_UNLOCK (connection); 05429 return FALSE; 05430 } 05431 05432 /* Fill in filter after all memory allocated, 05433 * so we don't run the free_user_data_function 05434 * if the add_filter() fails 05435 */ 05436 05437 filter->function = function; 05438 filter->user_data = user_data; 05439 filter->free_user_data_function = free_data_function; 05440 05441 CONNECTION_UNLOCK (connection); 05442 return TRUE; 05443 } 05444 05457 void 05458 dbus_connection_remove_filter (DBusConnection *connection, 05459 DBusHandleMessageFunction function, 05460 void *user_data) 05461 { 05462 DBusList *link; 05463 DBusMessageFilter *filter; 05464 05465 _dbus_return_if_fail (connection != NULL); 05466 _dbus_return_if_fail (function != NULL); 05467 05468 CONNECTION_LOCK (connection); 05469 05470 filter = NULL; 05471 05472 link = _dbus_list_get_last_link (&connection->filter_list); 05473 while (link != NULL) 05474 { 05475 filter = link->data; 05476 05477 if (filter->function == function && 05478 filter->user_data == user_data) 05479 { 05480 _dbus_list_remove_link (&connection->filter_list, link); 05481 filter->function = NULL; 05482 05483 break; 05484 } 05485 05486 link = _dbus_list_get_prev_link (&connection->filter_list, link); 05487 filter = NULL; 05488 } 05489 05490 CONNECTION_UNLOCK (connection); 05491 05492 #ifndef DBUS_DISABLE_CHECKS 05493 if (filter == NULL) 05494 { 05495 _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n", 05496 function, user_data); 05497 return; 05498 } 05499 #endif 05500 05501 /* Call application code */ 05502 if (filter->free_user_data_function) 05503 (* filter->free_user_data_function) (filter->user_data); 05504 05505 filter->free_user_data_function = NULL; 05506 filter->user_data = NULL; 05507 05508 _dbus_message_filter_unref (filter); 05509 } 05510 05523 dbus_bool_t 05524 dbus_connection_try_register_object_path (DBusConnection *connection, 05525 const char *path, 05526 const DBusObjectPathVTable *vtable, 05527 void *user_data, 05528 DBusError *error) 05529 { 05530 char **decomposed_path; 05531 dbus_bool_t retval; 05532 05533 _dbus_return_val_if_fail (connection != NULL, FALSE); 05534 _dbus_return_val_if_fail (path != NULL, FALSE); 05535 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05536 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05537 05538 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05539 return FALSE; 05540 05541 CONNECTION_LOCK (connection); 05542 05543 retval = _dbus_object_tree_register (connection->objects, 05544 FALSE, 05545 (const char **) decomposed_path, vtable, 05546 user_data, error); 05547 05548 CONNECTION_UNLOCK (connection); 05549 05550 dbus_free_string_array (decomposed_path); 05551 05552 return retval; 05553 } 05554 05570 dbus_bool_t 05571 dbus_connection_register_object_path (DBusConnection *connection, 05572 const char *path, 05573 const DBusObjectPathVTable *vtable, 05574 void *user_data) 05575 { 05576 char **decomposed_path; 05577 dbus_bool_t retval; 05578 DBusError error = DBUS_ERROR_INIT; 05579 05580 _dbus_return_val_if_fail (connection != NULL, FALSE); 05581 _dbus_return_val_if_fail (path != NULL, FALSE); 05582 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05583 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05584 05585 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05586 return FALSE; 05587 05588 CONNECTION_LOCK (connection); 05589 05590 retval = _dbus_object_tree_register (connection->objects, 05591 FALSE, 05592 (const char **) decomposed_path, vtable, 05593 user_data, &error); 05594 05595 CONNECTION_UNLOCK (connection); 05596 05597 dbus_free_string_array (decomposed_path); 05598 05599 if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE)) 05600 { 05601 _dbus_warn ("%s\n", error.message); 05602 dbus_error_free (&error); 05603 return FALSE; 05604 } 05605 05606 return retval; 05607 } 05608 05623 dbus_bool_t 05624 dbus_connection_try_register_fallback (DBusConnection *connection, 05625 const char *path, 05626 const DBusObjectPathVTable *vtable, 05627 void *user_data, 05628 DBusError *error) 05629 { 05630 char **decomposed_path; 05631 dbus_bool_t retval; 05632 05633 _dbus_return_val_if_fail (connection != NULL, FALSE); 05634 _dbus_return_val_if_fail (path != NULL, FALSE); 05635 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05636 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05637 05638 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05639 return FALSE; 05640 05641 CONNECTION_LOCK (connection); 05642 05643 retval = _dbus_object_tree_register (connection->objects, 05644 TRUE, 05645 (const char **) decomposed_path, vtable, 05646 user_data, error); 05647 05648 CONNECTION_UNLOCK (connection); 05649 05650 dbus_free_string_array (decomposed_path); 05651 05652 return retval; 05653 } 05654 05672 dbus_bool_t 05673 dbus_connection_register_fallback (DBusConnection *connection, 05674 const char *path, 05675 const DBusObjectPathVTable *vtable, 05676 void *user_data) 05677 { 05678 char **decomposed_path; 05679 dbus_bool_t retval; 05680 DBusError error = DBUS_ERROR_INIT; 05681 05682 _dbus_return_val_if_fail (connection != NULL, FALSE); 05683 _dbus_return_val_if_fail (path != NULL, FALSE); 05684 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05685 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05686 05687 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05688 return FALSE; 05689 05690 CONNECTION_LOCK (connection); 05691 05692 retval = _dbus_object_tree_register (connection->objects, 05693 TRUE, 05694 (const char **) decomposed_path, vtable, 05695 user_data, &error); 05696 05697 CONNECTION_UNLOCK (connection); 05698 05699 dbus_free_string_array (decomposed_path); 05700 05701 if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE)) 05702 { 05703 _dbus_warn ("%s\n", error.message); 05704 dbus_error_free (&error); 05705 return FALSE; 05706 } 05707 05708 return retval; 05709 } 05710 05720 dbus_bool_t 05721 dbus_connection_unregister_object_path (DBusConnection *connection, 05722 const char *path) 05723 { 05724 char **decomposed_path; 05725 05726 _dbus_return_val_if_fail (connection != NULL, FALSE); 05727 _dbus_return_val_if_fail (path != NULL, FALSE); 05728 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05729 05730 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05731 return FALSE; 05732 05733 CONNECTION_LOCK (connection); 05734 05735 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path); 05736 05737 dbus_free_string_array (decomposed_path); 05738 05739 return TRUE; 05740 } 05741 05752 dbus_bool_t 05753 dbus_connection_get_object_path_data (DBusConnection *connection, 05754 const char *path, 05755 void **data_p) 05756 { 05757 char **decomposed_path; 05758 05759 _dbus_return_val_if_fail (connection != NULL, FALSE); 05760 _dbus_return_val_if_fail (path != NULL, FALSE); 05761 _dbus_return_val_if_fail (data_p != NULL, FALSE); 05762 05763 *data_p = NULL; 05764 05765 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05766 return FALSE; 05767 05768 CONNECTION_LOCK (connection); 05769 05770 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path); 05771 05772 CONNECTION_UNLOCK (connection); 05773 05774 dbus_free_string_array (decomposed_path); 05775 05776 return TRUE; 05777 } 05778 05789 dbus_bool_t 05790 dbus_connection_list_registered (DBusConnection *connection, 05791 const char *parent_path, 05792 char ***child_entries) 05793 { 05794 char **decomposed_path; 05795 dbus_bool_t retval; 05796 _dbus_return_val_if_fail (connection != NULL, FALSE); 05797 _dbus_return_val_if_fail (parent_path != NULL, FALSE); 05798 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE); 05799 _dbus_return_val_if_fail (child_entries != NULL, FALSE); 05800 05801 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL)) 05802 return FALSE; 05803 05804 CONNECTION_LOCK (connection); 05805 05806 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects, 05807 (const char **) decomposed_path, 05808 child_entries); 05809 dbus_free_string_array (decomposed_path); 05810 05811 return retval; 05812 } 05813 05814 static DBusDataSlotAllocator slot_allocator; 05815 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots); 05816 05831 dbus_bool_t 05832 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p) 05833 { 05834 return _dbus_data_slot_allocator_alloc (&slot_allocator, 05835 &_DBUS_LOCK_NAME (connection_slots), 05836 slot_p); 05837 } 05838 05850 void 05851 dbus_connection_free_data_slot (dbus_int32_t *slot_p) 05852 { 05853 _dbus_return_if_fail (*slot_p >= 0); 05854 05855 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 05856 } 05857 05880 dbus_bool_t 05881 dbus_connection_set_data (DBusConnection *connection, 05882 dbus_int32_t slot, 05883 void *data, 05884 DBusFreeFunction free_data_func) 05885 { 05886 DBusFreeFunction old_free_func; 05887 void *old_data; 05888 dbus_bool_t retval; 05889 05890 _dbus_return_val_if_fail (connection != NULL, FALSE); 05891 _dbus_return_val_if_fail (slot >= 0, FALSE); 05892 05893 SLOTS_LOCK (connection); 05894 05895 retval = _dbus_data_slot_list_set (&slot_allocator, 05896 &connection->slot_list, 05897 slot, data, free_data_func, 05898 &old_free_func, &old_data); 05899 05900 SLOTS_UNLOCK (connection); 05901 05902 if (retval) 05903 { 05904 /* Do the actual free outside the connection lock */ 05905 if (old_free_func) 05906 (* old_free_func) (old_data); 05907 } 05908 05909 return retval; 05910 } 05911 05929 void* 05930 dbus_connection_get_data (DBusConnection *connection, 05931 dbus_int32_t slot) 05932 { 05933 void *res; 05934 05935 _dbus_return_val_if_fail (connection != NULL, NULL); 05936 05937 SLOTS_LOCK (connection); 05938 05939 res = _dbus_data_slot_list_get (&slot_allocator, 05940 &connection->slot_list, 05941 slot); 05942 05943 SLOTS_UNLOCK (connection); 05944 05945 return res; 05946 } 05947 05954 void 05955 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe) 05956 { 05957 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE; 05958 } 05959 05968 void 05969 dbus_connection_set_max_message_size (DBusConnection *connection, 05970 long size) 05971 { 05972 _dbus_return_if_fail (connection != NULL); 05973 05974 CONNECTION_LOCK (connection); 05975 _dbus_transport_set_max_message_size (connection->transport, 05976 size); 05977 CONNECTION_UNLOCK (connection); 05978 } 05979 05986 long 05987 dbus_connection_get_max_message_size (DBusConnection *connection) 05988 { 05989 long res; 05990 05991 _dbus_return_val_if_fail (connection != NULL, 0); 05992 05993 CONNECTION_LOCK (connection); 05994 res = _dbus_transport_get_max_message_size (connection->transport); 05995 CONNECTION_UNLOCK (connection); 05996 return res; 05997 } 05998 06007 void 06008 dbus_connection_set_max_message_unix_fds (DBusConnection *connection, 06009 long n) 06010 { 06011 _dbus_return_if_fail (connection != NULL); 06012 06013 CONNECTION_LOCK (connection); 06014 _dbus_transport_set_max_message_unix_fds (connection->transport, 06015 n); 06016 CONNECTION_UNLOCK (connection); 06017 } 06018 06025 long 06026 dbus_connection_get_max_message_unix_fds (DBusConnection *connection) 06027 { 06028 long res; 06029 06030 _dbus_return_val_if_fail (connection != NULL, 0); 06031 06032 CONNECTION_LOCK (connection); 06033 res = _dbus_transport_get_max_message_unix_fds (connection->transport); 06034 CONNECTION_UNLOCK (connection); 06035 return res; 06036 } 06037 06063 void 06064 dbus_connection_set_max_received_size (DBusConnection *connection, 06065 long size) 06066 { 06067 _dbus_return_if_fail (connection != NULL); 06068 06069 CONNECTION_LOCK (connection); 06070 _dbus_transport_set_max_received_size (connection->transport, 06071 size); 06072 CONNECTION_UNLOCK (connection); 06073 } 06074 06081 long 06082 dbus_connection_get_max_received_size (DBusConnection *connection) 06083 { 06084 long res; 06085 06086 _dbus_return_val_if_fail (connection != NULL, 0); 06087 06088 CONNECTION_LOCK (connection); 06089 res = _dbus_transport_get_max_received_size (connection->transport); 06090 CONNECTION_UNLOCK (connection); 06091 return res; 06092 } 06093 06105 void 06106 dbus_connection_set_max_received_unix_fds (DBusConnection *connection, 06107 long n) 06108 { 06109 _dbus_return_if_fail (connection != NULL); 06110 06111 CONNECTION_LOCK (connection); 06112 _dbus_transport_set_max_received_unix_fds (connection->transport, 06113 n); 06114 CONNECTION_UNLOCK (connection); 06115 } 06116 06123 long 06124 dbus_connection_get_max_received_unix_fds (DBusConnection *connection) 06125 { 06126 long res; 06127 06128 _dbus_return_val_if_fail (connection != NULL, 0); 06129 06130 CONNECTION_LOCK (connection); 06131 res = _dbus_transport_get_max_received_unix_fds (connection->transport); 06132 CONNECTION_UNLOCK (connection); 06133 return res; 06134 } 06135 06146 long 06147 dbus_connection_get_outgoing_size (DBusConnection *connection) 06148 { 06149 long res; 06150 06151 _dbus_return_val_if_fail (connection != NULL, 0); 06152 06153 CONNECTION_LOCK (connection); 06154 res = _dbus_counter_get_size_value (connection->outgoing_counter); 06155 CONNECTION_UNLOCK (connection); 06156 return res; 06157 } 06158 06166 long 06167 dbus_connection_get_outgoing_unix_fds (DBusConnection *connection) 06168 { 06169 long res; 06170 06171 _dbus_return_val_if_fail (connection != NULL, 0); 06172 06173 CONNECTION_LOCK (connection); 06174 res = _dbus_counter_get_unix_fd_value (connection->outgoing_counter); 06175 CONNECTION_UNLOCK (connection); 06176 return res; 06177 } 06178