D-Bus 1.4.6
|
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 _dbus_assert (filter->refcount.value > 0); 00345 _dbus_atomic_inc (&filter->refcount); 00346 00347 return filter; 00348 } 00349 00350 static void 00351 _dbus_message_filter_unref (DBusMessageFilter *filter) 00352 { 00353 _dbus_assert (filter->refcount.value > 0); 00354 00355 if (_dbus_atomic_dec (&filter->refcount) == 1) 00356 { 00357 if (filter->free_user_data_function) 00358 (* filter->free_user_data_function) (filter->user_data); 00359 00360 dbus_free (filter); 00361 } 00362 } 00363 00369 void 00370 _dbus_connection_lock (DBusConnection *connection) 00371 { 00372 CONNECTION_LOCK (connection); 00373 } 00374 00380 void 00381 _dbus_connection_unlock (DBusConnection *connection) 00382 { 00383 CONNECTION_UNLOCK (connection); 00384 } 00385 00393 static void 00394 _dbus_connection_wakeup_mainloop (DBusConnection *connection) 00395 { 00396 if (connection->wakeup_main_function) 00397 (*connection->wakeup_main_function) (connection->wakeup_main_data); 00398 } 00399 00400 #ifdef DBUS_BUILD_TESTS 00401 /* For now this function isn't used */ 00411 dbus_bool_t 00412 _dbus_connection_queue_received_message (DBusConnection *connection, 00413 DBusMessage *message) 00414 { 00415 DBusList *link; 00416 00417 link = _dbus_list_alloc_link (message); 00418 if (link == NULL) 00419 return FALSE; 00420 00421 dbus_message_ref (message); 00422 _dbus_connection_queue_received_message_link (connection, link); 00423 00424 return TRUE; 00425 } 00426 00439 void 00440 _dbus_connection_test_get_locks (DBusConnection *connection, 00441 DBusMutex **mutex_loc, 00442 DBusMutex **dispatch_mutex_loc, 00443 DBusMutex **io_path_mutex_loc, 00444 DBusCondVar **dispatch_cond_loc, 00445 DBusCondVar **io_path_cond_loc) 00446 { 00447 *mutex_loc = connection->mutex; 00448 *dispatch_mutex_loc = connection->dispatch_mutex; 00449 *io_path_mutex_loc = connection->io_path_mutex; 00450 *dispatch_cond_loc = connection->dispatch_cond; 00451 *io_path_cond_loc = connection->io_path_cond; 00452 } 00453 #endif 00454 00463 void 00464 _dbus_connection_queue_received_message_link (DBusConnection *connection, 00465 DBusList *link) 00466 { 00467 DBusPendingCall *pending; 00468 dbus_uint32_t reply_serial; 00469 DBusMessage *message; 00470 00471 _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport)); 00472 00473 _dbus_list_append_link (&connection->incoming_messages, 00474 link); 00475 message = link->data; 00476 00477 /* If this is a reply we're waiting on, remove timeout for it */ 00478 reply_serial = dbus_message_get_reply_serial (message); 00479 if (reply_serial != 0) 00480 { 00481 pending = _dbus_hash_table_lookup_int (connection->pending_replies, 00482 reply_serial); 00483 if (pending != NULL) 00484 { 00485 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 00486 _dbus_connection_remove_timeout_unlocked (connection, 00487 _dbus_pending_call_get_timeout_unlocked (pending)); 00488 00489 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 00490 } 00491 } 00492 00493 00494 00495 connection->n_incoming += 1; 00496 00497 _dbus_connection_wakeup_mainloop (connection); 00498 00499 _dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n", 00500 message, 00501 dbus_message_type_to_string (dbus_message_get_type (message)), 00502 dbus_message_get_path (message) ? 00503 dbus_message_get_path (message) : 00504 "no path", 00505 dbus_message_get_interface (message) ? 00506 dbus_message_get_interface (message) : 00507 "no interface", 00508 dbus_message_get_member (message) ? 00509 dbus_message_get_member (message) : 00510 "no member", 00511 dbus_message_get_signature (message), 00512 dbus_message_get_reply_serial (message), 00513 connection, 00514 connection->n_incoming);} 00515 00524 void 00525 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection, 00526 DBusList *link) 00527 { 00528 HAVE_LOCK_CHECK (connection); 00529 00530 _dbus_list_append_link (&connection->incoming_messages, link); 00531 00532 connection->n_incoming += 1; 00533 00534 _dbus_connection_wakeup_mainloop (connection); 00535 00536 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n", 00537 link->data, connection, connection->n_incoming); 00538 } 00539 00540 00548 dbus_bool_t 00549 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection) 00550 { 00551 HAVE_LOCK_CHECK (connection); 00552 return connection->outgoing_messages != NULL; 00553 } 00554 00564 dbus_bool_t 00565 dbus_connection_has_messages_to_send (DBusConnection *connection) 00566 { 00567 dbus_bool_t v; 00568 00569 _dbus_return_val_if_fail (connection != NULL, FALSE); 00570 00571 CONNECTION_LOCK (connection); 00572 v = _dbus_connection_has_messages_to_send_unlocked (connection); 00573 CONNECTION_UNLOCK (connection); 00574 00575 return v; 00576 } 00577 00585 DBusMessage* 00586 _dbus_connection_get_message_to_send (DBusConnection *connection) 00587 { 00588 HAVE_LOCK_CHECK (connection); 00589 00590 return _dbus_list_get_last (&connection->outgoing_messages); 00591 } 00592 00601 void 00602 _dbus_connection_message_sent (DBusConnection *connection, 00603 DBusMessage *message) 00604 { 00605 DBusList *link; 00606 00607 HAVE_LOCK_CHECK (connection); 00608 00609 /* This can be called before we even complete authentication, since 00610 * it's called on disconnect to clean up the outgoing queue. 00611 * It's also called as we successfully send each message. 00612 */ 00613 00614 link = _dbus_list_get_last_link (&connection->outgoing_messages); 00615 _dbus_assert (link != NULL); 00616 _dbus_assert (link->data == message); 00617 00618 /* Save this link in the link cache */ 00619 _dbus_list_unlink (&connection->outgoing_messages, 00620 link); 00621 _dbus_list_prepend_link (&connection->link_cache, link); 00622 00623 connection->n_outgoing -= 1; 00624 00625 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n", 00626 message, 00627 dbus_message_type_to_string (dbus_message_get_type (message)), 00628 dbus_message_get_path (message) ? 00629 dbus_message_get_path (message) : 00630 "no path", 00631 dbus_message_get_interface (message) ? 00632 dbus_message_get_interface (message) : 00633 "no interface", 00634 dbus_message_get_member (message) ? 00635 dbus_message_get_member (message) : 00636 "no member", 00637 dbus_message_get_signature (message), 00638 connection, connection->n_outgoing); 00639 00640 /* Save this link in the link cache also */ 00641 _dbus_message_remove_counter (message, connection->outgoing_counter, 00642 &link); 00643 _dbus_list_prepend_link (&connection->link_cache, link); 00644 00645 dbus_message_unref (message); 00646 } 00647 00649 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list, 00650 DBusWatch *watch); 00652 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list, 00653 DBusWatch *watch); 00655 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list, 00656 DBusWatch *watch, 00657 dbus_bool_t enabled); 00658 00659 static dbus_bool_t 00660 protected_change_watch (DBusConnection *connection, 00661 DBusWatch *watch, 00662 DBusWatchAddFunction add_function, 00663 DBusWatchRemoveFunction remove_function, 00664 DBusWatchToggleFunction toggle_function, 00665 dbus_bool_t enabled) 00666 { 00667 dbus_bool_t retval; 00668 00669 HAVE_LOCK_CHECK (connection); 00670 00671 /* The original purpose of protected_change_watch() was to hold a 00672 * ref on the connection while dropping the connection lock, then 00673 * calling out to the app. This was a broken hack that did not 00674 * work, since the connection was in a hosed state (no WatchList 00675 * field) while calling out. 00676 * 00677 * So for now we'll just keep the lock while calling out. This means 00678 * apps are not allowed to call DBusConnection methods inside a 00679 * watch function or they will deadlock. 00680 * 00681 * The "real fix" is to use the _and_unlock() pattern found 00682 * elsewhere in the code, to defer calling out to the app until 00683 * we're about to drop locks and return flow of control to the app 00684 * anyway. 00685 * 00686 * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144 00687 */ 00688 00689 if (connection->watches) 00690 { 00691 if (add_function) 00692 retval = (* add_function) (connection->watches, watch); 00693 else if (remove_function) 00694 { 00695 retval = TRUE; 00696 (* remove_function) (connection->watches, watch); 00697 } 00698 else 00699 { 00700 retval = TRUE; 00701 (* toggle_function) (connection->watches, watch, enabled); 00702 } 00703 return retval; 00704 } 00705 else 00706 return FALSE; 00707 } 00708 00709 00721 dbus_bool_t 00722 _dbus_connection_add_watch_unlocked (DBusConnection *connection, 00723 DBusWatch *watch) 00724 { 00725 return protected_change_watch (connection, watch, 00726 _dbus_watch_list_add_watch, 00727 NULL, NULL, FALSE); 00728 } 00729 00739 void 00740 _dbus_connection_remove_watch_unlocked (DBusConnection *connection, 00741 DBusWatch *watch) 00742 { 00743 protected_change_watch (connection, watch, 00744 NULL, 00745 _dbus_watch_list_remove_watch, 00746 NULL, FALSE); 00747 } 00748 00759 void 00760 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection, 00761 DBusWatch *watch, 00762 dbus_bool_t enabled) 00763 { 00764 _dbus_assert (watch != NULL); 00765 00766 protected_change_watch (connection, watch, 00767 NULL, NULL, 00768 _dbus_watch_list_toggle_watch, 00769 enabled); 00770 } 00771 00773 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list, 00774 DBusTimeout *timeout); 00776 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list, 00777 DBusTimeout *timeout); 00779 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list, 00780 DBusTimeout *timeout, 00781 dbus_bool_t enabled); 00782 00783 static dbus_bool_t 00784 protected_change_timeout (DBusConnection *connection, 00785 DBusTimeout *timeout, 00786 DBusTimeoutAddFunction add_function, 00787 DBusTimeoutRemoveFunction remove_function, 00788 DBusTimeoutToggleFunction toggle_function, 00789 dbus_bool_t enabled) 00790 { 00791 dbus_bool_t retval; 00792 00793 HAVE_LOCK_CHECK (connection); 00794 00795 /* The original purpose of protected_change_timeout() was to hold a 00796 * ref on the connection while dropping the connection lock, then 00797 * calling out to the app. This was a broken hack that did not 00798 * work, since the connection was in a hosed state (no TimeoutList 00799 * field) while calling out. 00800 * 00801 * So for now we'll just keep the lock while calling out. This means 00802 * apps are not allowed to call DBusConnection methods inside a 00803 * timeout function or they will deadlock. 00804 * 00805 * The "real fix" is to use the _and_unlock() pattern found 00806 * elsewhere in the code, to defer calling out to the app until 00807 * we're about to drop locks and return flow of control to the app 00808 * anyway. 00809 * 00810 * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144 00811 */ 00812 00813 if (connection->timeouts) 00814 { 00815 if (add_function) 00816 retval = (* add_function) (connection->timeouts, timeout); 00817 else if (remove_function) 00818 { 00819 retval = TRUE; 00820 (* remove_function) (connection->timeouts, timeout); 00821 } 00822 else 00823 { 00824 retval = TRUE; 00825 (* toggle_function) (connection->timeouts, timeout, enabled); 00826 } 00827 return retval; 00828 } 00829 else 00830 return FALSE; 00831 } 00832 00845 dbus_bool_t 00846 _dbus_connection_add_timeout_unlocked (DBusConnection *connection, 00847 DBusTimeout *timeout) 00848 { 00849 return protected_change_timeout (connection, timeout, 00850 _dbus_timeout_list_add_timeout, 00851 NULL, NULL, FALSE); 00852 } 00853 00863 void 00864 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection, 00865 DBusTimeout *timeout) 00866 { 00867 protected_change_timeout (connection, timeout, 00868 NULL, 00869 _dbus_timeout_list_remove_timeout, 00870 NULL, FALSE); 00871 } 00872 00883 void 00884 _dbus_connection_toggle_timeout_unlocked (DBusConnection *connection, 00885 DBusTimeout *timeout, 00886 dbus_bool_t enabled) 00887 { 00888 protected_change_timeout (connection, timeout, 00889 NULL, NULL, 00890 _dbus_timeout_list_toggle_timeout, 00891 enabled); 00892 } 00893 00894 static dbus_bool_t 00895 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection, 00896 DBusPendingCall *pending) 00897 { 00898 dbus_uint32_t reply_serial; 00899 DBusTimeout *timeout; 00900 00901 HAVE_LOCK_CHECK (connection); 00902 00903 reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending); 00904 00905 _dbus_assert (reply_serial != 0); 00906 00907 timeout = _dbus_pending_call_get_timeout_unlocked (pending); 00908 00909 if (timeout) 00910 { 00911 if (!_dbus_connection_add_timeout_unlocked (connection, timeout)) 00912 return FALSE; 00913 00914 if (!_dbus_hash_table_insert_int (connection->pending_replies, 00915 reply_serial, 00916 pending)) 00917 { 00918 _dbus_connection_remove_timeout_unlocked (connection, timeout); 00919 00920 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 00921 HAVE_LOCK_CHECK (connection); 00922 return FALSE; 00923 } 00924 00925 _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE); 00926 } 00927 else 00928 { 00929 if (!_dbus_hash_table_insert_int (connection->pending_replies, 00930 reply_serial, 00931 pending)) 00932 { 00933 HAVE_LOCK_CHECK (connection); 00934 return FALSE; 00935 } 00936 } 00937 00938 _dbus_pending_call_ref_unlocked (pending); 00939 00940 HAVE_LOCK_CHECK (connection); 00941 00942 return TRUE; 00943 } 00944 00945 static void 00946 free_pending_call_on_hash_removal (void *data) 00947 { 00948 DBusPendingCall *pending; 00949 DBusConnection *connection; 00950 00951 if (data == NULL) 00952 return; 00953 00954 pending = data; 00955 00956 connection = _dbus_pending_call_get_connection_unlocked (pending); 00957 00958 HAVE_LOCK_CHECK (connection); 00959 00960 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 00961 { 00962 _dbus_connection_remove_timeout_unlocked (connection, 00963 _dbus_pending_call_get_timeout_unlocked (pending)); 00964 00965 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 00966 } 00967 00968 /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock 00969 * here, but the pending call finalizer could in principle call out to 00970 * application code so we pretty much have to... some larger code reorg 00971 * might be needed. 00972 */ 00973 _dbus_connection_ref_unlocked (connection); 00974 _dbus_pending_call_unref_and_unlock (pending); 00975 CONNECTION_LOCK (connection); 00976 _dbus_connection_unref_unlocked (connection); 00977 } 00978 00979 static void 00980 _dbus_connection_detach_pending_call_unlocked (DBusConnection *connection, 00981 DBusPendingCall *pending) 00982 { 00983 /* This ends up unlocking to call the pending call finalizer, which is unexpected to 00984 * say the least. 00985 */ 00986 _dbus_hash_table_remove_int (connection->pending_replies, 00987 _dbus_pending_call_get_reply_serial_unlocked (pending)); 00988 } 00989 00990 static void 00991 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection, 00992 DBusPendingCall *pending) 00993 { 00994 /* The idea here is to avoid finalizing the pending call 00995 * with the lock held, since there's a destroy notifier 00996 * in pending call that goes out to application code. 00997 * 00998 * There's an extra unlock inside the hash table 00999 * "free pending call" function FIXME... 01000 */ 01001 _dbus_pending_call_ref_unlocked (pending); 01002 _dbus_hash_table_remove_int (connection->pending_replies, 01003 _dbus_pending_call_get_reply_serial_unlocked (pending)); 01004 01005 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 01006 _dbus_connection_remove_timeout_unlocked (connection, 01007 _dbus_pending_call_get_timeout_unlocked (pending)); 01008 01009 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 01010 01011 _dbus_pending_call_unref_and_unlock (pending); 01012 } 01013 01022 void 01023 _dbus_connection_remove_pending_call (DBusConnection *connection, 01024 DBusPendingCall *pending) 01025 { 01026 CONNECTION_LOCK (connection); 01027 _dbus_connection_detach_pending_call_and_unlock (connection, pending); 01028 } 01029 01039 static dbus_bool_t 01040 _dbus_connection_acquire_io_path (DBusConnection *connection, 01041 int timeout_milliseconds) 01042 { 01043 dbus_bool_t we_acquired; 01044 01045 HAVE_LOCK_CHECK (connection); 01046 01047 /* We don't want the connection to vanish */ 01048 _dbus_connection_ref_unlocked (connection); 01049 01050 /* We will only touch io_path_acquired which is protected by our mutex */ 01051 CONNECTION_UNLOCK (connection); 01052 01053 _dbus_verbose ("locking io_path_mutex\n"); 01054 _dbus_mutex_lock (connection->io_path_mutex); 01055 01056 _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n", 01057 connection->io_path_acquired, timeout_milliseconds); 01058 01059 we_acquired = FALSE; 01060 01061 if (connection->io_path_acquired) 01062 { 01063 if (timeout_milliseconds != -1) 01064 { 01065 _dbus_verbose ("waiting %d for IO path to be acquirable\n", 01066 timeout_milliseconds); 01067 01068 if (!_dbus_condvar_wait_timeout (connection->io_path_cond, 01069 connection->io_path_mutex, 01070 timeout_milliseconds)) 01071 { 01072 /* We timed out before anyone signaled. */ 01073 /* (writing the loop to handle the !timedout case by 01074 * waiting longer if needed is a pain since dbus 01075 * wraps pthread_cond_timedwait to take a relative 01076 * time instead of absolute, something kind of stupid 01077 * on our part. for now it doesn't matter, we will just 01078 * end up back here eventually.) 01079 */ 01080 } 01081 } 01082 else 01083 { 01084 while (connection->io_path_acquired) 01085 { 01086 _dbus_verbose ("waiting for IO path to be acquirable\n"); 01087 _dbus_condvar_wait (connection->io_path_cond, 01088 connection->io_path_mutex); 01089 } 01090 } 01091 } 01092 01093 if (!connection->io_path_acquired) 01094 { 01095 we_acquired = TRUE; 01096 connection->io_path_acquired = TRUE; 01097 } 01098 01099 _dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n", 01100 connection->io_path_acquired, we_acquired); 01101 01102 _dbus_verbose ("unlocking io_path_mutex\n"); 01103 _dbus_mutex_unlock (connection->io_path_mutex); 01104 01105 CONNECTION_LOCK (connection); 01106 01107 HAVE_LOCK_CHECK (connection); 01108 01109 _dbus_connection_unref_unlocked (connection); 01110 01111 return we_acquired; 01112 } 01113 01121 static void 01122 _dbus_connection_release_io_path (DBusConnection *connection) 01123 { 01124 HAVE_LOCK_CHECK (connection); 01125 01126 _dbus_verbose ("locking io_path_mutex\n"); 01127 _dbus_mutex_lock (connection->io_path_mutex); 01128 01129 _dbus_assert (connection->io_path_acquired); 01130 01131 _dbus_verbose ("start connection->io_path_acquired = %d\n", 01132 connection->io_path_acquired); 01133 01134 connection->io_path_acquired = FALSE; 01135 _dbus_condvar_wake_one (connection->io_path_cond); 01136 01137 _dbus_verbose ("unlocking io_path_mutex\n"); 01138 _dbus_mutex_unlock (connection->io_path_mutex); 01139 } 01140 01176 void 01177 _dbus_connection_do_iteration_unlocked (DBusConnection *connection, 01178 DBusPendingCall *pending, 01179 unsigned int flags, 01180 int timeout_milliseconds) 01181 { 01182 _dbus_verbose ("start\n"); 01183 01184 HAVE_LOCK_CHECK (connection); 01185 01186 if (connection->n_outgoing == 0) 01187 flags &= ~DBUS_ITERATION_DO_WRITING; 01188 01189 if (_dbus_connection_acquire_io_path (connection, 01190 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0)) 01191 { 01192 HAVE_LOCK_CHECK (connection); 01193 01194 if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending)) 01195 { 01196 _dbus_verbose ("pending call completed while acquiring I/O path"); 01197 } 01198 else if ( (pending != NULL) && 01199 _dbus_connection_peek_for_reply_unlocked (connection, 01200 _dbus_pending_call_get_reply_serial_unlocked (pending))) 01201 { 01202 _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)"); 01203 } 01204 else 01205 { 01206 _dbus_transport_do_iteration (connection->transport, 01207 flags, timeout_milliseconds); 01208 } 01209 01210 _dbus_connection_release_io_path (connection); 01211 } 01212 01213 HAVE_LOCK_CHECK (connection); 01214 01215 _dbus_verbose ("end\n"); 01216 } 01217 01227 DBusConnection* 01228 _dbus_connection_new_for_transport (DBusTransport *transport) 01229 { 01230 DBusConnection *connection; 01231 DBusWatchList *watch_list; 01232 DBusTimeoutList *timeout_list; 01233 DBusHashTable *pending_replies; 01234 DBusList *disconnect_link; 01235 DBusMessage *disconnect_message; 01236 DBusCounter *outgoing_counter; 01237 DBusObjectTree *objects; 01238 01239 watch_list = NULL; 01240 connection = NULL; 01241 pending_replies = NULL; 01242 timeout_list = NULL; 01243 disconnect_link = NULL; 01244 disconnect_message = NULL; 01245 outgoing_counter = NULL; 01246 objects = NULL; 01247 01248 watch_list = _dbus_watch_list_new (); 01249 if (watch_list == NULL) 01250 goto error; 01251 01252 timeout_list = _dbus_timeout_list_new (); 01253 if (timeout_list == NULL) 01254 goto error; 01255 01256 pending_replies = 01257 _dbus_hash_table_new (DBUS_HASH_INT, 01258 NULL, 01259 (DBusFreeFunction)free_pending_call_on_hash_removal); 01260 if (pending_replies == NULL) 01261 goto error; 01262 01263 connection = dbus_new0 (DBusConnection, 1); 01264 if (connection == NULL) 01265 goto error; 01266 01267 _dbus_mutex_new_at_location (&connection->mutex); 01268 if (connection->mutex == NULL) 01269 goto error; 01270 01271 _dbus_mutex_new_at_location (&connection->io_path_mutex); 01272 if (connection->io_path_mutex == NULL) 01273 goto error; 01274 01275 _dbus_mutex_new_at_location (&connection->dispatch_mutex); 01276 if (connection->dispatch_mutex == NULL) 01277 goto error; 01278 01279 _dbus_condvar_new_at_location (&connection->dispatch_cond); 01280 if (connection->dispatch_cond == NULL) 01281 goto error; 01282 01283 _dbus_condvar_new_at_location (&connection->io_path_cond); 01284 if (connection->io_path_cond == NULL) 01285 goto error; 01286 01287 _dbus_mutex_new_at_location (&connection->slot_mutex); 01288 if (connection->slot_mutex == NULL) 01289 goto error; 01290 01291 disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL, 01292 DBUS_INTERFACE_LOCAL, 01293 "Disconnected"); 01294 01295 if (disconnect_message == NULL) 01296 goto error; 01297 01298 disconnect_link = _dbus_list_alloc_link (disconnect_message); 01299 if (disconnect_link == NULL) 01300 goto error; 01301 01302 outgoing_counter = _dbus_counter_new (); 01303 if (outgoing_counter == NULL) 01304 goto error; 01305 01306 objects = _dbus_object_tree_new (connection); 01307 if (objects == NULL) 01308 goto error; 01309 01310 if (_dbus_modify_sigpipe) 01311 _dbus_disable_sigpipe (); 01312 01313 connection->refcount.value = 1; 01314 connection->transport = transport; 01315 connection->watches = watch_list; 01316 connection->timeouts = timeout_list; 01317 connection->pending_replies = pending_replies; 01318 connection->outgoing_counter = outgoing_counter; 01319 connection->filter_list = NULL; 01320 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */ 01321 connection->objects = objects; 01322 connection->exit_on_disconnect = FALSE; 01323 connection->shareable = FALSE; 01324 connection->route_peer_messages = FALSE; 01325 connection->disconnected_message_arrived = FALSE; 01326 connection->disconnected_message_processed = FALSE; 01327 01328 #ifndef DBUS_DISABLE_CHECKS 01329 connection->generation = _dbus_current_generation; 01330 #endif 01331 01332 _dbus_data_slot_list_init (&connection->slot_list); 01333 01334 connection->client_serial = 1; 01335 01336 connection->disconnect_message_link = disconnect_link; 01337 01338 CONNECTION_LOCK (connection); 01339 01340 if (!_dbus_transport_set_connection (transport, connection)) 01341 { 01342 CONNECTION_UNLOCK (connection); 01343 01344 goto error; 01345 } 01346 01347 _dbus_transport_ref (transport); 01348 01349 CONNECTION_UNLOCK (connection); 01350 01351 return connection; 01352 01353 error: 01354 if (disconnect_message != NULL) 01355 dbus_message_unref (disconnect_message); 01356 01357 if (disconnect_link != NULL) 01358 _dbus_list_free_link (disconnect_link); 01359 01360 if (connection != NULL) 01361 { 01362 _dbus_condvar_free_at_location (&connection->io_path_cond); 01363 _dbus_condvar_free_at_location (&connection->dispatch_cond); 01364 _dbus_mutex_free_at_location (&connection->mutex); 01365 _dbus_mutex_free_at_location (&connection->io_path_mutex); 01366 _dbus_mutex_free_at_location (&connection->dispatch_mutex); 01367 _dbus_mutex_free_at_location (&connection->slot_mutex); 01368 dbus_free (connection); 01369 } 01370 if (pending_replies) 01371 _dbus_hash_table_unref (pending_replies); 01372 01373 if (watch_list) 01374 _dbus_watch_list_free (watch_list); 01375 01376 if (timeout_list) 01377 _dbus_timeout_list_free (timeout_list); 01378 01379 if (outgoing_counter) 01380 _dbus_counter_unref (outgoing_counter); 01381 01382 if (objects) 01383 _dbus_object_tree_unref (objects); 01384 01385 return NULL; 01386 } 01387 01395 DBusConnection * 01396 _dbus_connection_ref_unlocked (DBusConnection *connection) 01397 { 01398 _dbus_assert (connection != NULL); 01399 _dbus_assert (connection->generation == _dbus_current_generation); 01400 01401 HAVE_LOCK_CHECK (connection); 01402 01403 #ifdef DBUS_HAVE_ATOMIC_INT 01404 _dbus_atomic_inc (&connection->refcount); 01405 #else 01406 _dbus_assert (connection->refcount.value > 0); 01407 connection->refcount.value += 1; 01408 #endif 01409 01410 return connection; 01411 } 01412 01419 void 01420 _dbus_connection_unref_unlocked (DBusConnection *connection) 01421 { 01422 dbus_bool_t last_unref; 01423 01424 HAVE_LOCK_CHECK (connection); 01425 01426 _dbus_assert (connection != NULL); 01427 01428 /* The connection lock is better than the global 01429 * lock in the atomic increment fallback 01430 */ 01431 01432 #ifdef DBUS_HAVE_ATOMIC_INT 01433 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1); 01434 #else 01435 _dbus_assert (connection->refcount.value > 0); 01436 01437 connection->refcount.value -= 1; 01438 last_unref = (connection->refcount.value == 0); 01439 #if 0 01440 printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value); 01441 #endif 01442 #endif 01443 01444 if (last_unref) 01445 _dbus_connection_last_unref (connection); 01446 } 01447 01448 static dbus_uint32_t 01449 _dbus_connection_get_next_client_serial (DBusConnection *connection) 01450 { 01451 dbus_uint32_t serial; 01452 01453 serial = connection->client_serial++; 01454 01455 if (connection->client_serial == 0) 01456 connection->client_serial = 1; 01457 01458 return serial; 01459 } 01460 01474 dbus_bool_t 01475 _dbus_connection_handle_watch (DBusWatch *watch, 01476 unsigned int condition, 01477 void *data) 01478 { 01479 DBusConnection *connection; 01480 dbus_bool_t retval; 01481 DBusDispatchStatus status; 01482 01483 connection = data; 01484 01485 _dbus_verbose ("start\n"); 01486 01487 CONNECTION_LOCK (connection); 01488 01489 if (!_dbus_connection_acquire_io_path (connection, 1)) 01490 { 01491 /* another thread is handling the message */ 01492 CONNECTION_UNLOCK (connection); 01493 return TRUE; 01494 } 01495 01496 HAVE_LOCK_CHECK (connection); 01497 retval = _dbus_transport_handle_watch (connection->transport, 01498 watch, condition); 01499 01500 _dbus_connection_release_io_path (connection); 01501 01502 HAVE_LOCK_CHECK (connection); 01503 01504 _dbus_verbose ("middle\n"); 01505 01506 status = _dbus_connection_get_dispatch_status_unlocked (connection); 01507 01508 /* this calls out to user code */ 01509 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 01510 01511 _dbus_verbose ("end\n"); 01512 01513 return retval; 01514 } 01515 01516 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections); 01517 static DBusHashTable *shared_connections = NULL; 01518 static DBusList *shared_connections_no_guid = NULL; 01519 01520 static void 01521 close_connection_on_shutdown (DBusConnection *connection) 01522 { 01523 DBusMessage *message; 01524 01525 dbus_connection_ref (connection); 01526 _dbus_connection_close_possibly_shared (connection); 01527 01528 /* Churn through to the Disconnected message */ 01529 while ((message = dbus_connection_pop_message (connection))) 01530 { 01531 dbus_message_unref (message); 01532 } 01533 dbus_connection_unref (connection); 01534 } 01535 01536 static void 01537 shared_connections_shutdown (void *data) 01538 { 01539 int n_entries; 01540 01541 _DBUS_LOCK (shared_connections); 01542 01543 /* This is a little bit unpleasant... better ideas? */ 01544 while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0) 01545 { 01546 DBusConnection *connection; 01547 DBusHashIter iter; 01548 01549 _dbus_hash_iter_init (shared_connections, &iter); 01550 _dbus_hash_iter_next (&iter); 01551 01552 connection = _dbus_hash_iter_get_value (&iter); 01553 01554 _DBUS_UNLOCK (shared_connections); 01555 close_connection_on_shutdown (connection); 01556 _DBUS_LOCK (shared_connections); 01557 01558 /* The connection should now be dead and not in our hash ... */ 01559 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries); 01560 } 01561 01562 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0); 01563 01564 _dbus_hash_table_unref (shared_connections); 01565 shared_connections = NULL; 01566 01567 if (shared_connections_no_guid != NULL) 01568 { 01569 DBusConnection *connection; 01570 connection = _dbus_list_pop_first (&shared_connections_no_guid); 01571 while (connection != NULL) 01572 { 01573 _DBUS_UNLOCK (shared_connections); 01574 close_connection_on_shutdown (connection); 01575 _DBUS_LOCK (shared_connections); 01576 connection = _dbus_list_pop_first (&shared_connections_no_guid); 01577 } 01578 } 01579 01580 shared_connections_no_guid = NULL; 01581 01582 _DBUS_UNLOCK (shared_connections); 01583 } 01584 01585 static dbus_bool_t 01586 connection_lookup_shared (DBusAddressEntry *entry, 01587 DBusConnection **result) 01588 { 01589 _dbus_verbose ("checking for existing connection\n"); 01590 01591 *result = NULL; 01592 01593 _DBUS_LOCK (shared_connections); 01594 01595 if (shared_connections == NULL) 01596 { 01597 _dbus_verbose ("creating shared_connections hash table\n"); 01598 01599 shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING, 01600 dbus_free, 01601 NULL); 01602 if (shared_connections == NULL) 01603 { 01604 _DBUS_UNLOCK (shared_connections); 01605 return FALSE; 01606 } 01607 01608 if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL)) 01609 { 01610 _dbus_hash_table_unref (shared_connections); 01611 shared_connections = NULL; 01612 _DBUS_UNLOCK (shared_connections); 01613 return FALSE; 01614 } 01615 01616 _dbus_verbose (" successfully created shared_connections\n"); 01617 01618 _DBUS_UNLOCK (shared_connections); 01619 return TRUE; /* no point looking up in the hash we just made */ 01620 } 01621 else 01622 { 01623 const char *guid; 01624 01625 guid = dbus_address_entry_get_value (entry, "guid"); 01626 01627 if (guid != NULL) 01628 { 01629 DBusConnection *connection; 01630 01631 connection = _dbus_hash_table_lookup_string (shared_connections, 01632 guid); 01633 01634 if (connection) 01635 { 01636 /* The DBusConnection can't be finalized without taking 01637 * the shared_connections lock to remove it from the 01638 * hash. So it's safe to ref the connection here. 01639 * However, it may be disconnected if the Disconnected 01640 * message hasn't been processed yet, in which case we 01641 * want to pretend it isn't in the hash and avoid 01642 * returning it. 01643 * 01644 * The idea is to avoid ever returning a disconnected connection 01645 * from dbus_connection_open(). We could just synchronously 01646 * drop our shared ref to the connection on connection disconnect, 01647 * and then assert here that the connection is connected, but 01648 * that causes reentrancy headaches. 01649 */ 01650 CONNECTION_LOCK (connection); 01651 if (_dbus_connection_get_is_connected_unlocked (connection)) 01652 { 01653 _dbus_connection_ref_unlocked (connection); 01654 *result = connection; 01655 _dbus_verbose ("looked up existing connection to server guid %s\n", 01656 guid); 01657 } 01658 else 01659 { 01660 _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n", 01661 guid); 01662 } 01663 CONNECTION_UNLOCK (connection); 01664 } 01665 } 01666 01667 _DBUS_UNLOCK (shared_connections); 01668 return TRUE; 01669 } 01670 } 01671 01672 static dbus_bool_t 01673 connection_record_shared_unlocked (DBusConnection *connection, 01674 const char *guid) 01675 { 01676 char *guid_key; 01677 char *guid_in_connection; 01678 01679 HAVE_LOCK_CHECK (connection); 01680 _dbus_assert (connection->server_guid == NULL); 01681 _dbus_assert (connection->shareable); 01682 01683 /* get a hard ref on this connection, even if 01684 * we won't in fact store it in the hash, we still 01685 * need to hold a ref on it until it's disconnected. 01686 */ 01687 _dbus_connection_ref_unlocked (connection); 01688 01689 if (guid == NULL) 01690 { 01691 _DBUS_LOCK (shared_connections); 01692 01693 if (!_dbus_list_prepend (&shared_connections_no_guid, connection)) 01694 { 01695 _DBUS_UNLOCK (shared_connections); 01696 return FALSE; 01697 } 01698 01699 _DBUS_UNLOCK (shared_connections); 01700 return TRUE; /* don't store in the hash */ 01701 } 01702 01703 /* A separate copy of the key is required in the hash table, because 01704 * we don't have a lock on the connection when we are doing a hash 01705 * lookup. 01706 */ 01707 01708 guid_key = _dbus_strdup (guid); 01709 if (guid_key == NULL) 01710 return FALSE; 01711 01712 guid_in_connection = _dbus_strdup (guid); 01713 if (guid_in_connection == NULL) 01714 { 01715 dbus_free (guid_key); 01716 return FALSE; 01717 } 01718 01719 _DBUS_LOCK (shared_connections); 01720 _dbus_assert (shared_connections != NULL); 01721 01722 if (!_dbus_hash_table_insert_string (shared_connections, 01723 guid_key, connection)) 01724 { 01725 dbus_free (guid_key); 01726 dbus_free (guid_in_connection); 01727 _DBUS_UNLOCK (shared_connections); 01728 return FALSE; 01729 } 01730 01731 connection->server_guid = guid_in_connection; 01732 01733 _dbus_verbose ("stored connection to %s to be shared\n", 01734 connection->server_guid); 01735 01736 _DBUS_UNLOCK (shared_connections); 01737 01738 _dbus_assert (connection->server_guid != NULL); 01739 01740 return TRUE; 01741 } 01742 01743 static void 01744 connection_forget_shared_unlocked (DBusConnection *connection) 01745 { 01746 HAVE_LOCK_CHECK (connection); 01747 01748 if (!connection->shareable) 01749 return; 01750 01751 _DBUS_LOCK (shared_connections); 01752 01753 if (connection->server_guid != NULL) 01754 { 01755 _dbus_verbose ("dropping connection to %s out of the shared table\n", 01756 connection->server_guid); 01757 01758 if (!_dbus_hash_table_remove_string (shared_connections, 01759 connection->server_guid)) 01760 _dbus_assert_not_reached ("connection was not in the shared table"); 01761 01762 dbus_free (connection->server_guid); 01763 connection->server_guid = NULL; 01764 } 01765 else 01766 { 01767 _dbus_list_remove (&shared_connections_no_guid, connection); 01768 } 01769 01770 _DBUS_UNLOCK (shared_connections); 01771 01772 /* remove our reference held on all shareable connections */ 01773 _dbus_connection_unref_unlocked (connection); 01774 } 01775 01776 static DBusConnection* 01777 connection_try_from_address_entry (DBusAddressEntry *entry, 01778 DBusError *error) 01779 { 01780 DBusTransport *transport; 01781 DBusConnection *connection; 01782 01783 transport = _dbus_transport_open (entry, error); 01784 01785 if (transport == NULL) 01786 { 01787 _DBUS_ASSERT_ERROR_IS_SET (error); 01788 return NULL; 01789 } 01790 01791 connection = _dbus_connection_new_for_transport (transport); 01792 01793 _dbus_transport_unref (transport); 01794 01795 if (connection == NULL) 01796 { 01797 _DBUS_SET_OOM (error); 01798 return NULL; 01799 } 01800 01801 #ifndef DBUS_DISABLE_CHECKS 01802 _dbus_assert (!connection->have_connection_lock); 01803 #endif 01804 return connection; 01805 } 01806 01807 /* 01808 * If the shared parameter is true, then any existing connection will 01809 * be used (and if a new connection is created, it will be available 01810 * for use by others). If the shared parameter is false, a new 01811 * connection will always be created, and the new connection will 01812 * never be returned to other callers. 01813 * 01814 * @param address the address 01815 * @param shared whether the connection is shared or private 01816 * @param error error return 01817 * @returns the connection or #NULL on error 01818 */ 01819 static DBusConnection* 01820 _dbus_connection_open_internal (const char *address, 01821 dbus_bool_t shared, 01822 DBusError *error) 01823 { 01824 DBusConnection *connection; 01825 DBusAddressEntry **entries; 01826 DBusError tmp_error = DBUS_ERROR_INIT; 01827 DBusError first_error = DBUS_ERROR_INIT; 01828 int len, i; 01829 01830 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01831 01832 _dbus_verbose ("opening %s connection to: %s\n", 01833 shared ? "shared" : "private", address); 01834 01835 if (!dbus_parse_address (address, &entries, &len, error)) 01836 return NULL; 01837 01838 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01839 01840 connection = NULL; 01841 01842 for (i = 0; i < len; i++) 01843 { 01844 if (shared) 01845 { 01846 if (!connection_lookup_shared (entries[i], &connection)) 01847 _DBUS_SET_OOM (&tmp_error); 01848 } 01849 01850 if (connection == NULL) 01851 { 01852 connection = connection_try_from_address_entry (entries[i], 01853 &tmp_error); 01854 01855 if (connection != NULL && shared) 01856 { 01857 const char *guid; 01858 01859 connection->shareable = TRUE; 01860 01861 /* guid may be NULL */ 01862 guid = dbus_address_entry_get_value (entries[i], "guid"); 01863 01864 CONNECTION_LOCK (connection); 01865 01866 if (!connection_record_shared_unlocked (connection, guid)) 01867 { 01868 _DBUS_SET_OOM (&tmp_error); 01869 _dbus_connection_close_possibly_shared_and_unlock (connection); 01870 dbus_connection_unref (connection); 01871 connection = NULL; 01872 } 01873 else 01874 CONNECTION_UNLOCK (connection); 01875 } 01876 } 01877 01878 if (connection) 01879 break; 01880 01881 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 01882 01883 if (i == 0) 01884 dbus_move_error (&tmp_error, &first_error); 01885 else 01886 dbus_error_free (&tmp_error); 01887 } 01888 01889 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01890 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 01891 01892 if (connection == NULL) 01893 { 01894 _DBUS_ASSERT_ERROR_IS_SET (&first_error); 01895 dbus_move_error (&first_error, error); 01896 } 01897 else 01898 dbus_error_free (&first_error); 01899 01900 dbus_address_entries_free (entries); 01901 return connection; 01902 } 01903 01912 void 01913 _dbus_connection_close_possibly_shared (DBusConnection *connection) 01914 { 01915 _dbus_assert (connection != NULL); 01916 _dbus_assert (connection->generation == _dbus_current_generation); 01917 01918 CONNECTION_LOCK (connection); 01919 _dbus_connection_close_possibly_shared_and_unlock (connection); 01920 } 01921 01922 static DBusPreallocatedSend* 01923 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection) 01924 { 01925 DBusPreallocatedSend *preallocated; 01926 01927 HAVE_LOCK_CHECK (connection); 01928 01929 _dbus_assert (connection != NULL); 01930 01931 preallocated = dbus_new (DBusPreallocatedSend, 1); 01932 if (preallocated == NULL) 01933 return NULL; 01934 01935 if (connection->link_cache != NULL) 01936 { 01937 preallocated->queue_link = 01938 _dbus_list_pop_first_link (&connection->link_cache); 01939 preallocated->queue_link->data = NULL; 01940 } 01941 else 01942 { 01943 preallocated->queue_link = _dbus_list_alloc_link (NULL); 01944 if (preallocated->queue_link == NULL) 01945 goto failed_0; 01946 } 01947 01948 if (connection->link_cache != NULL) 01949 { 01950 preallocated->counter_link = 01951 _dbus_list_pop_first_link (&connection->link_cache); 01952 preallocated->counter_link->data = connection->outgoing_counter; 01953 } 01954 else 01955 { 01956 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter); 01957 if (preallocated->counter_link == NULL) 01958 goto failed_1; 01959 } 01960 01961 _dbus_counter_ref (preallocated->counter_link->data); 01962 01963 preallocated->connection = connection; 01964 01965 return preallocated; 01966 01967 failed_1: 01968 _dbus_list_free_link (preallocated->queue_link); 01969 failed_0: 01970 dbus_free (preallocated); 01971 01972 return NULL; 01973 } 01974 01975 /* Called with lock held, does not update dispatch status */ 01976 static void 01977 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection, 01978 DBusPreallocatedSend *preallocated, 01979 DBusMessage *message, 01980 dbus_uint32_t *client_serial) 01981 { 01982 dbus_uint32_t serial; 01983 01984 preallocated->queue_link->data = message; 01985 _dbus_list_prepend_link (&connection->outgoing_messages, 01986 preallocated->queue_link); 01987 01988 _dbus_message_add_counter_link (message, 01989 preallocated->counter_link); 01990 01991 dbus_free (preallocated); 01992 preallocated = NULL; 01993 01994 dbus_message_ref (message); 01995 01996 connection->n_outgoing += 1; 01997 01998 _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n", 01999 message, 02000 dbus_message_type_to_string (dbus_message_get_type (message)), 02001 dbus_message_get_path (message) ? 02002 dbus_message_get_path (message) : 02003 "no path", 02004 dbus_message_get_interface (message) ? 02005 dbus_message_get_interface (message) : 02006 "no interface", 02007 dbus_message_get_member (message) ? 02008 dbus_message_get_member (message) : 02009 "no member", 02010 dbus_message_get_signature (message), 02011 dbus_message_get_destination (message) ? 02012 dbus_message_get_destination (message) : 02013 "null", 02014 connection, 02015 connection->n_outgoing); 02016 02017 if (dbus_message_get_serial (message) == 0) 02018 { 02019 serial = _dbus_connection_get_next_client_serial (connection); 02020 dbus_message_set_serial (message, serial); 02021 if (client_serial) 02022 *client_serial = serial; 02023 } 02024 else 02025 { 02026 if (client_serial) 02027 *client_serial = dbus_message_get_serial (message); 02028 } 02029 02030 _dbus_verbose ("Message %p serial is %u\n", 02031 message, dbus_message_get_serial (message)); 02032 02033 dbus_message_lock (message); 02034 02035 /* Now we need to run an iteration to hopefully just write the messages 02036 * out immediately, and otherwise get them queued up 02037 */ 02038 _dbus_connection_do_iteration_unlocked (connection, 02039 NULL, 02040 DBUS_ITERATION_DO_WRITING, 02041 -1); 02042 02043 /* If stuff is still queued up, be sure we wake up the main loop */ 02044 if (connection->n_outgoing > 0) 02045 _dbus_connection_wakeup_mainloop (connection); 02046 } 02047 02048 static void 02049 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection, 02050 DBusPreallocatedSend *preallocated, 02051 DBusMessage *message, 02052 dbus_uint32_t *client_serial) 02053 { 02054 DBusDispatchStatus status; 02055 02056 HAVE_LOCK_CHECK (connection); 02057 02058 _dbus_connection_send_preallocated_unlocked_no_update (connection, 02059 preallocated, 02060 message, client_serial); 02061 02062 _dbus_verbose ("middle\n"); 02063 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02064 02065 /* this calls out to user code */ 02066 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02067 } 02068 02078 dbus_bool_t 02079 _dbus_connection_send_and_unlock (DBusConnection *connection, 02080 DBusMessage *message, 02081 dbus_uint32_t *client_serial) 02082 { 02083 DBusPreallocatedSend *preallocated; 02084 02085 _dbus_assert (connection != NULL); 02086 _dbus_assert (message != NULL); 02087 02088 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 02089 if (preallocated == NULL) 02090 { 02091 CONNECTION_UNLOCK (connection); 02092 return FALSE; 02093 } 02094 02095 _dbus_connection_send_preallocated_and_unlock (connection, 02096 preallocated, 02097 message, 02098 client_serial); 02099 return TRUE; 02100 } 02101 02126 void 02127 _dbus_connection_close_if_only_one_ref (DBusConnection *connection) 02128 { 02129 CONNECTION_LOCK (connection); 02130 02131 _dbus_assert (connection->refcount.value > 0); 02132 02133 if (connection->refcount.value == 1) 02134 _dbus_connection_close_possibly_shared_and_unlock (connection); 02135 else 02136 CONNECTION_UNLOCK (connection); 02137 } 02138 02139 02149 static void 02150 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds) 02151 { 02152 if (timeout_milliseconds == -1) 02153 _dbus_sleep_milliseconds (1000); 02154 else if (timeout_milliseconds < 100) 02155 ; /* just busy loop */ 02156 else if (timeout_milliseconds <= 1000) 02157 _dbus_sleep_milliseconds (timeout_milliseconds / 3); 02158 else 02159 _dbus_sleep_milliseconds (1000); 02160 } 02161 02162 static DBusMessage * 02163 generate_local_error_message (dbus_uint32_t serial, 02164 char *error_name, 02165 char *error_msg) 02166 { 02167 DBusMessage *message; 02168 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR); 02169 if (!message) 02170 goto out; 02171 02172 if (!dbus_message_set_error_name (message, error_name)) 02173 { 02174 dbus_message_unref (message); 02175 message = NULL; 02176 goto out; 02177 } 02178 02179 dbus_message_set_no_reply (message, TRUE); 02180 02181 if (!dbus_message_set_reply_serial (message, 02182 serial)) 02183 { 02184 dbus_message_unref (message); 02185 message = NULL; 02186 goto out; 02187 } 02188 02189 if (error_msg != NULL) 02190 { 02191 DBusMessageIter iter; 02192 02193 dbus_message_iter_init_append (message, &iter); 02194 if (!dbus_message_iter_append_basic (&iter, 02195 DBUS_TYPE_STRING, 02196 &error_msg)) 02197 { 02198 dbus_message_unref (message); 02199 message = NULL; 02200 goto out; 02201 } 02202 } 02203 02204 out: 02205 return message; 02206 } 02207 02208 /* 02209 * Peek the incoming queue to see if we got reply for a specific serial 02210 */ 02211 static dbus_bool_t 02212 _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection, 02213 dbus_uint32_t client_serial) 02214 { 02215 DBusList *link; 02216 HAVE_LOCK_CHECK (connection); 02217 02218 link = _dbus_list_get_first_link (&connection->incoming_messages); 02219 02220 while (link != NULL) 02221 { 02222 DBusMessage *reply = link->data; 02223 02224 if (dbus_message_get_reply_serial (reply) == client_serial) 02225 { 02226 _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial); 02227 return TRUE; 02228 } 02229 link = _dbus_list_get_next_link (&connection->incoming_messages, link); 02230 } 02231 02232 return FALSE; 02233 } 02234 02235 /* This is slightly strange since we can pop a message here without 02236 * the dispatch lock. 02237 */ 02238 static DBusMessage* 02239 check_for_reply_unlocked (DBusConnection *connection, 02240 dbus_uint32_t client_serial) 02241 { 02242 DBusList *link; 02243 02244 HAVE_LOCK_CHECK (connection); 02245 02246 link = _dbus_list_get_first_link (&connection->incoming_messages); 02247 02248 while (link != NULL) 02249 { 02250 DBusMessage *reply = link->data; 02251 02252 if (dbus_message_get_reply_serial (reply) == client_serial) 02253 { 02254 _dbus_list_remove_link (&connection->incoming_messages, link); 02255 connection->n_incoming -= 1; 02256 return reply; 02257 } 02258 link = _dbus_list_get_next_link (&connection->incoming_messages, link); 02259 } 02260 02261 return NULL; 02262 } 02263 02264 static void 02265 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection) 02266 { 02267 /* We can't iterate over the hash in the normal way since we'll be 02268 * dropping the lock for each item. So we restart the 02269 * iter each time as we drain the hash table. 02270 */ 02271 02272 while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0) 02273 { 02274 DBusPendingCall *pending; 02275 DBusHashIter iter; 02276 02277 _dbus_hash_iter_init (connection->pending_replies, &iter); 02278 _dbus_hash_iter_next (&iter); 02279 02280 pending = _dbus_hash_iter_get_value (&iter); 02281 _dbus_pending_call_ref_unlocked (pending); 02282 02283 _dbus_pending_call_queue_timeout_error_unlocked (pending, 02284 connection); 02285 02286 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 02287 _dbus_connection_remove_timeout_unlocked (connection, 02288 _dbus_pending_call_get_timeout_unlocked (pending)); 02289 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 02290 _dbus_hash_iter_remove_entry (&iter); 02291 02292 _dbus_pending_call_unref_and_unlock (pending); 02293 CONNECTION_LOCK (connection); 02294 } 02295 HAVE_LOCK_CHECK (connection); 02296 } 02297 02298 static void 02299 complete_pending_call_and_unlock (DBusConnection *connection, 02300 DBusPendingCall *pending, 02301 DBusMessage *message) 02302 { 02303 _dbus_pending_call_set_reply_unlocked (pending, message); 02304 _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */ 02305 _dbus_connection_detach_pending_call_and_unlock (connection, pending); 02306 02307 /* Must be called unlocked since it invokes app callback */ 02308 _dbus_pending_call_complete (pending); 02309 dbus_pending_call_unref (pending); 02310 } 02311 02312 static dbus_bool_t 02313 check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection, 02314 DBusPendingCall *pending) 02315 { 02316 DBusMessage *reply; 02317 DBusDispatchStatus status; 02318 02319 reply = check_for_reply_unlocked (connection, 02320 _dbus_pending_call_get_reply_serial_unlocked (pending)); 02321 if (reply != NULL) 02322 { 02323 _dbus_verbose ("checked for reply\n"); 02324 02325 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n"); 02326 02327 complete_pending_call_and_unlock (connection, pending, reply); 02328 dbus_message_unref (reply); 02329 02330 CONNECTION_LOCK (connection); 02331 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02332 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02333 dbus_pending_call_unref (pending); 02334 02335 return TRUE; 02336 } 02337 02338 return FALSE; 02339 } 02340 02355 void 02356 _dbus_connection_block_pending_call (DBusPendingCall *pending) 02357 { 02358 long start_tv_sec, start_tv_usec; 02359 long tv_sec, tv_usec; 02360 DBusDispatchStatus status; 02361 DBusConnection *connection; 02362 dbus_uint32_t client_serial; 02363 DBusTimeout *timeout; 02364 int timeout_milliseconds, elapsed_milliseconds; 02365 02366 _dbus_assert (pending != NULL); 02367 02368 if (dbus_pending_call_get_completed (pending)) 02369 return; 02370 02371 dbus_pending_call_ref (pending); /* necessary because the call could be canceled */ 02372 02373 connection = _dbus_pending_call_get_connection_and_lock (pending); 02374 02375 /* Flush message queue - note, can affect dispatch status */ 02376 _dbus_connection_flush_unlocked (connection); 02377 02378 client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending); 02379 02380 /* note that timeout_milliseconds is limited to a smallish value 02381 * in _dbus_pending_call_new() so overflows aren't possible 02382 * below 02383 */ 02384 timeout = _dbus_pending_call_get_timeout_unlocked (pending); 02385 _dbus_get_current_time (&start_tv_sec, &start_tv_usec); 02386 if (timeout) 02387 { 02388 timeout_milliseconds = dbus_timeout_get_interval (timeout); 02389 02390 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n", 02391 timeout_milliseconds, 02392 client_serial, 02393 start_tv_sec, start_tv_usec); 02394 } 02395 else 02396 { 02397 timeout_milliseconds = -1; 02398 02399 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial); 02400 } 02401 02402 /* check to see if we already got the data off the socket */ 02403 /* from another blocked pending call */ 02404 if (check_for_reply_and_update_dispatch_unlocked (connection, pending)) 02405 return; 02406 02407 /* Now we wait... */ 02408 /* always block at least once as we know we don't have the reply yet */ 02409 _dbus_connection_do_iteration_unlocked (connection, 02410 pending, 02411 DBUS_ITERATION_DO_READING | 02412 DBUS_ITERATION_BLOCK, 02413 timeout_milliseconds); 02414 02415 recheck_status: 02416 02417 _dbus_verbose ("top of recheck\n"); 02418 02419 HAVE_LOCK_CHECK (connection); 02420 02421 /* queue messages and get status */ 02422 02423 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02424 02425 /* the get_completed() is in case a dispatch() while we were blocking 02426 * got the reply instead of us. 02427 */ 02428 if (_dbus_pending_call_get_completed_unlocked (pending)) 02429 { 02430 _dbus_verbose ("Pending call completed by dispatch\n"); 02431 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02432 dbus_pending_call_unref (pending); 02433 return; 02434 } 02435 02436 if (status == DBUS_DISPATCH_DATA_REMAINS) 02437 { 02438 if (check_for_reply_and_update_dispatch_unlocked (connection, pending)) 02439 return; 02440 } 02441 02442 _dbus_get_current_time (&tv_sec, &tv_usec); 02443 elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 + 02444 (tv_usec - start_tv_usec) / 1000; 02445 02446 if (!_dbus_connection_get_is_connected_unlocked (connection)) 02447 { 02448 DBusMessage *error_msg; 02449 02450 error_msg = generate_local_error_message (client_serial, 02451 DBUS_ERROR_DISCONNECTED, 02452 "Connection was disconnected before a reply was received"); 02453 02454 /* on OOM error_msg is set to NULL */ 02455 complete_pending_call_and_unlock (connection, pending, error_msg); 02456 dbus_pending_call_unref (pending); 02457 return; 02458 } 02459 else if (connection->disconnect_message_link == NULL) 02460 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n"); 02461 else if (timeout == NULL) 02462 { 02463 if (status == DBUS_DISPATCH_NEED_MEMORY) 02464 { 02465 /* Try sleeping a bit, as we aren't sure we need to block for reading, 02466 * we may already have a reply in the buffer and just can't process 02467 * it. 02468 */ 02469 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n"); 02470 02471 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds); 02472 } 02473 else 02474 { 02475 /* block again, we don't have the reply buffered yet. */ 02476 _dbus_connection_do_iteration_unlocked (connection, 02477 pending, 02478 DBUS_ITERATION_DO_READING | 02479 DBUS_ITERATION_BLOCK, 02480 timeout_milliseconds - elapsed_milliseconds); 02481 } 02482 02483 goto recheck_status; 02484 } 02485 else if (tv_sec < start_tv_sec) 02486 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n"); 02487 else if (elapsed_milliseconds < timeout_milliseconds) 02488 { 02489 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds); 02490 02491 if (status == DBUS_DISPATCH_NEED_MEMORY) 02492 { 02493 /* Try sleeping a bit, as we aren't sure we need to block for reading, 02494 * we may already have a reply in the buffer and just can't process 02495 * it. 02496 */ 02497 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n"); 02498 02499 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds); 02500 } 02501 else 02502 { 02503 /* block again, we don't have the reply buffered yet. */ 02504 _dbus_connection_do_iteration_unlocked (connection, 02505 NULL, 02506 DBUS_ITERATION_DO_READING | 02507 DBUS_ITERATION_BLOCK, 02508 timeout_milliseconds - elapsed_milliseconds); 02509 } 02510 02511 goto recheck_status; 02512 } 02513 02514 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n", 02515 elapsed_milliseconds); 02516 02517 _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending)); 02518 02519 /* unlock and call user code */ 02520 complete_pending_call_and_unlock (connection, pending, NULL); 02521 02522 /* update user code on dispatch status */ 02523 CONNECTION_LOCK (connection); 02524 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02525 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02526 dbus_pending_call_unref (pending); 02527 } 02528 02565 DBusConnection* 02566 dbus_connection_open (const char *address, 02567 DBusError *error) 02568 { 02569 DBusConnection *connection; 02570 02571 _dbus_return_val_if_fail (address != NULL, NULL); 02572 _dbus_return_val_if_error_is_set (error, NULL); 02573 02574 connection = _dbus_connection_open_internal (address, 02575 TRUE, 02576 error); 02577 02578 return connection; 02579 } 02580 02608 DBusConnection* 02609 dbus_connection_open_private (const char *address, 02610 DBusError *error) 02611 { 02612 DBusConnection *connection; 02613 02614 _dbus_return_val_if_fail (address != NULL, NULL); 02615 _dbus_return_val_if_error_is_set (error, NULL); 02616 02617 connection = _dbus_connection_open_internal (address, 02618 FALSE, 02619 error); 02620 02621 return connection; 02622 } 02623 02630 DBusConnection * 02631 dbus_connection_ref (DBusConnection *connection) 02632 { 02633 _dbus_return_val_if_fail (connection != NULL, NULL); 02634 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL); 02635 02636 /* The connection lock is better than the global 02637 * lock in the atomic increment fallback 02638 * 02639 * (FIXME but for now we always use the atomic version, 02640 * to avoid taking the connection lock, due to 02641 * the mess with set_timeout_functions()/set_watch_functions() 02642 * calling out to the app without dropping locks) 02643 */ 02644 02645 #if 1 02646 _dbus_atomic_inc (&connection->refcount); 02647 #else 02648 CONNECTION_LOCK (connection); 02649 _dbus_assert (connection->refcount.value > 0); 02650 02651 connection->refcount.value += 1; 02652 CONNECTION_UNLOCK (connection); 02653 #endif 02654 02655 return connection; 02656 } 02657 02658 static void 02659 free_outgoing_message (void *element, 02660 void *data) 02661 { 02662 DBusMessage *message = element; 02663 DBusConnection *connection = data; 02664 02665 _dbus_message_remove_counter (message, 02666 connection->outgoing_counter, 02667 NULL); 02668 dbus_message_unref (message); 02669 } 02670 02671 /* This is run without the mutex held, but after the last reference 02672 * to the connection has been dropped we should have no thread-related 02673 * problems 02674 */ 02675 static void 02676 _dbus_connection_last_unref (DBusConnection *connection) 02677 { 02678 DBusList *link; 02679 02680 _dbus_verbose ("Finalizing connection %p\n", connection); 02681 02682 _dbus_assert (connection->refcount.value == 0); 02683 02684 /* You have to disconnect the connection before unref:ing it. Otherwise 02685 * you won't get the disconnected message. 02686 */ 02687 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport)); 02688 _dbus_assert (connection->server_guid == NULL); 02689 02690 /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */ 02691 _dbus_object_tree_free_all_unlocked (connection->objects); 02692 02693 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL); 02694 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL); 02695 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL); 02696 02697 _dbus_watch_list_free (connection->watches); 02698 connection->watches = NULL; 02699 02700 _dbus_timeout_list_free (connection->timeouts); 02701 connection->timeouts = NULL; 02702 02703 _dbus_data_slot_list_free (&connection->slot_list); 02704 02705 link = _dbus_list_get_first_link (&connection->filter_list); 02706 while (link != NULL) 02707 { 02708 DBusMessageFilter *filter = link->data; 02709 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link); 02710 02711 filter->function = NULL; 02712 _dbus_message_filter_unref (filter); /* calls app callback */ 02713 link->data = NULL; 02714 02715 link = next; 02716 } 02717 _dbus_list_clear (&connection->filter_list); 02718 02719 /* ---- Done with stuff that invokes application callbacks */ 02720 02721 _dbus_object_tree_unref (connection->objects); 02722 02723 _dbus_hash_table_unref (connection->pending_replies); 02724 connection->pending_replies = NULL; 02725 02726 _dbus_list_clear (&connection->filter_list); 02727 02728 _dbus_list_foreach (&connection->outgoing_messages, 02729 free_outgoing_message, 02730 connection); 02731 _dbus_list_clear (&connection->outgoing_messages); 02732 02733 _dbus_list_foreach (&connection->incoming_messages, 02734 (DBusForeachFunction) dbus_message_unref, 02735 NULL); 02736 _dbus_list_clear (&connection->incoming_messages); 02737 02738 _dbus_counter_unref (connection->outgoing_counter); 02739 02740 _dbus_transport_unref (connection->transport); 02741 02742 if (connection->disconnect_message_link) 02743 { 02744 DBusMessage *message = connection->disconnect_message_link->data; 02745 dbus_message_unref (message); 02746 _dbus_list_free_link (connection->disconnect_message_link); 02747 } 02748 02749 _dbus_list_clear (&connection->link_cache); 02750 02751 _dbus_condvar_free_at_location (&connection->dispatch_cond); 02752 _dbus_condvar_free_at_location (&connection->io_path_cond); 02753 02754 _dbus_mutex_free_at_location (&connection->io_path_mutex); 02755 _dbus_mutex_free_at_location (&connection->dispatch_mutex); 02756 02757 _dbus_mutex_free_at_location (&connection->slot_mutex); 02758 02759 _dbus_mutex_free_at_location (&connection->mutex); 02760 02761 dbus_free (connection); 02762 } 02763 02783 void 02784 dbus_connection_unref (DBusConnection *connection) 02785 { 02786 dbus_bool_t last_unref; 02787 02788 _dbus_return_if_fail (connection != NULL); 02789 _dbus_return_if_fail (connection->generation == _dbus_current_generation); 02790 02791 /* The connection lock is better than the global 02792 * lock in the atomic increment fallback 02793 * 02794 * (FIXME but for now we always use the atomic version, 02795 * to avoid taking the connection lock, due to 02796 * the mess with set_timeout_functions()/set_watch_functions() 02797 * calling out to the app without dropping locks) 02798 */ 02799 02800 #if 1 02801 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1); 02802 #else 02803 CONNECTION_LOCK (connection); 02804 02805 _dbus_assert (connection->refcount.value > 0); 02806 02807 connection->refcount.value -= 1; 02808 last_unref = (connection->refcount.value == 0); 02809 02810 #if 0 02811 printf ("unref() connection %p count = %d\n", connection, connection->refcount.value); 02812 #endif 02813 02814 CONNECTION_UNLOCK (connection); 02815 #endif 02816 02817 if (last_unref) 02818 { 02819 #ifndef DBUS_DISABLE_CHECKS 02820 if (_dbus_transport_get_is_connected (connection->transport)) 02821 { 02822 _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", 02823 connection->shareable ? 02824 "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" : 02825 "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n"); 02826 return; 02827 } 02828 #endif 02829 _dbus_connection_last_unref (connection); 02830 } 02831 } 02832 02833 /* 02834 * Note that the transport can disconnect itself (other end drops us) 02835 * and in that case this function never runs. So this function must 02836 * not do anything more than disconnect the transport and update the 02837 * dispatch status. 02838 * 02839 * If the transport self-disconnects, then we assume someone will 02840 * dispatch the connection to cause the dispatch status update. 02841 */ 02842 static void 02843 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection) 02844 { 02845 DBusDispatchStatus status; 02846 02847 HAVE_LOCK_CHECK (connection); 02848 02849 _dbus_verbose ("Disconnecting %p\n", connection); 02850 02851 /* We need to ref because update_dispatch_status_and_unlock will unref 02852 * the connection if it was shared and libdbus was the only remaining 02853 * refcount holder. 02854 */ 02855 _dbus_connection_ref_unlocked (connection); 02856 02857 _dbus_transport_disconnect (connection->transport); 02858 02859 /* This has the side effect of queuing the disconnect message link 02860 * (unless we don't have enough memory, possibly, so don't assert it). 02861 * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open 02862 * should never again return the newly-disconnected connection. 02863 * 02864 * However, we only unref the shared connection and exit_on_disconnect when 02865 * the disconnect message reaches the head of the message queue, 02866 * NOT when it's first queued. 02867 */ 02868 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02869 02870 /* This calls out to user code */ 02871 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02872 02873 /* Could also call out to user code */ 02874 dbus_connection_unref (connection); 02875 } 02876 02919 void 02920 dbus_connection_close (DBusConnection *connection) 02921 { 02922 _dbus_return_if_fail (connection != NULL); 02923 _dbus_return_if_fail (connection->generation == _dbus_current_generation); 02924 02925 CONNECTION_LOCK (connection); 02926 02927 #ifndef DBUS_DISABLE_CHECKS 02928 if (connection->shareable) 02929 { 02930 CONNECTION_UNLOCK (connection); 02931 02932 _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n"); 02933 return; 02934 } 02935 #endif 02936 02937 _dbus_connection_close_possibly_shared_and_unlock (connection); 02938 } 02939 02940 static dbus_bool_t 02941 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection) 02942 { 02943 HAVE_LOCK_CHECK (connection); 02944 return _dbus_transport_get_is_connected (connection->transport); 02945 } 02946 02960 dbus_bool_t 02961 dbus_connection_get_is_connected (DBusConnection *connection) 02962 { 02963 dbus_bool_t res; 02964 02965 _dbus_return_val_if_fail (connection != NULL, FALSE); 02966 02967 CONNECTION_LOCK (connection); 02968 res = _dbus_connection_get_is_connected_unlocked (connection); 02969 CONNECTION_UNLOCK (connection); 02970 02971 return res; 02972 } 02973 02982 dbus_bool_t 02983 dbus_connection_get_is_authenticated (DBusConnection *connection) 02984 { 02985 dbus_bool_t res; 02986 02987 _dbus_return_val_if_fail (connection != NULL, FALSE); 02988 02989 CONNECTION_LOCK (connection); 02990 res = _dbus_transport_get_is_authenticated (connection->transport); 02991 CONNECTION_UNLOCK (connection); 02992 02993 return res; 02994 } 02995 03016 dbus_bool_t 03017 dbus_connection_get_is_anonymous (DBusConnection *connection) 03018 { 03019 dbus_bool_t res; 03020 03021 _dbus_return_val_if_fail (connection != NULL, FALSE); 03022 03023 CONNECTION_LOCK (connection); 03024 res = _dbus_transport_get_is_anonymous (connection->transport); 03025 CONNECTION_UNLOCK (connection); 03026 03027 return res; 03028 } 03029 03061 char* 03062 dbus_connection_get_server_id (DBusConnection *connection) 03063 { 03064 char *id; 03065 03066 _dbus_return_val_if_fail (connection != NULL, NULL); 03067 03068 CONNECTION_LOCK (connection); 03069 id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport)); 03070 CONNECTION_UNLOCK (connection); 03071 03072 return id; 03073 } 03074 03092 dbus_bool_t 03093 dbus_connection_can_send_type(DBusConnection *connection, 03094 int type) 03095 { 03096 _dbus_return_val_if_fail (connection != NULL, FALSE); 03097 03098 if (!_dbus_type_is_valid(type)) 03099 return FALSE; 03100 03101 if (type != DBUS_TYPE_UNIX_FD) 03102 return TRUE; 03103 03104 #ifdef HAVE_UNIX_FD_PASSING 03105 { 03106 dbus_bool_t b; 03107 03108 CONNECTION_LOCK(connection); 03109 b = _dbus_transport_can_pass_unix_fd(connection->transport); 03110 CONNECTION_UNLOCK(connection); 03111 03112 return b; 03113 } 03114 #endif 03115 03116 return FALSE; 03117 } 03118 03132 void 03133 dbus_connection_set_exit_on_disconnect (DBusConnection *connection, 03134 dbus_bool_t exit_on_disconnect) 03135 { 03136 _dbus_return_if_fail (connection != NULL); 03137 03138 CONNECTION_LOCK (connection); 03139 connection->exit_on_disconnect = exit_on_disconnect != FALSE; 03140 CONNECTION_UNLOCK (connection); 03141 } 03142 03152 DBusPreallocatedSend* 03153 dbus_connection_preallocate_send (DBusConnection *connection) 03154 { 03155 DBusPreallocatedSend *preallocated; 03156 03157 _dbus_return_val_if_fail (connection != NULL, NULL); 03158 03159 CONNECTION_LOCK (connection); 03160 03161 preallocated = 03162 _dbus_connection_preallocate_send_unlocked (connection); 03163 03164 CONNECTION_UNLOCK (connection); 03165 03166 return preallocated; 03167 } 03168 03178 void 03179 dbus_connection_free_preallocated_send (DBusConnection *connection, 03180 DBusPreallocatedSend *preallocated) 03181 { 03182 _dbus_return_if_fail (connection != NULL); 03183 _dbus_return_if_fail (preallocated != NULL); 03184 _dbus_return_if_fail (connection == preallocated->connection); 03185 03186 _dbus_list_free_link (preallocated->queue_link); 03187 _dbus_counter_unref (preallocated->counter_link->data); 03188 _dbus_list_free_link (preallocated->counter_link); 03189 dbus_free (preallocated); 03190 } 03191 03204 void 03205 dbus_connection_send_preallocated (DBusConnection *connection, 03206 DBusPreallocatedSend *preallocated, 03207 DBusMessage *message, 03208 dbus_uint32_t *client_serial) 03209 { 03210 _dbus_return_if_fail (connection != NULL); 03211 _dbus_return_if_fail (preallocated != NULL); 03212 _dbus_return_if_fail (message != NULL); 03213 _dbus_return_if_fail (preallocated->connection == connection); 03214 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL || 03215 dbus_message_get_member (message) != NULL); 03216 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL || 03217 (dbus_message_get_interface (message) != NULL && 03218 dbus_message_get_member (message) != NULL)); 03219 03220 CONNECTION_LOCK (connection); 03221 03222 #ifdef HAVE_UNIX_FD_PASSING 03223 03224 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03225 message->n_unix_fds > 0) 03226 { 03227 /* Refuse to send fds on a connection that cannot handle 03228 them. Unfortunately we cannot return a proper error here, so 03229 the best we can is just return. */ 03230 CONNECTION_UNLOCK (connection); 03231 return; 03232 } 03233 03234 #endif 03235 03236 _dbus_connection_send_preallocated_and_unlock (connection, 03237 preallocated, 03238 message, client_serial); 03239 } 03240 03241 static dbus_bool_t 03242 _dbus_connection_send_unlocked_no_update (DBusConnection *connection, 03243 DBusMessage *message, 03244 dbus_uint32_t *client_serial) 03245 { 03246 DBusPreallocatedSend *preallocated; 03247 03248 _dbus_assert (connection != NULL); 03249 _dbus_assert (message != NULL); 03250 03251 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 03252 if (preallocated == NULL) 03253 return FALSE; 03254 03255 _dbus_connection_send_preallocated_unlocked_no_update (connection, 03256 preallocated, 03257 message, 03258 client_serial); 03259 return TRUE; 03260 } 03261 03289 dbus_bool_t 03290 dbus_connection_send (DBusConnection *connection, 03291 DBusMessage *message, 03292 dbus_uint32_t *serial) 03293 { 03294 _dbus_return_val_if_fail (connection != NULL, FALSE); 03295 _dbus_return_val_if_fail (message != NULL, FALSE); 03296 03297 CONNECTION_LOCK (connection); 03298 03299 #ifdef HAVE_UNIX_FD_PASSING 03300 03301 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03302 message->n_unix_fds > 0) 03303 { 03304 /* Refuse to send fds on a connection that cannot handle 03305 them. Unfortunately we cannot return a proper error here, so 03306 the best we can is just return. */ 03307 CONNECTION_UNLOCK (connection); 03308 return FALSE; 03309 } 03310 03311 #endif 03312 03313 return _dbus_connection_send_and_unlock (connection, 03314 message, 03315 serial); 03316 } 03317 03318 static dbus_bool_t 03319 reply_handler_timeout (void *data) 03320 { 03321 DBusConnection *connection; 03322 DBusDispatchStatus status; 03323 DBusPendingCall *pending = data; 03324 03325 connection = _dbus_pending_call_get_connection_and_lock (pending); 03326 03327 _dbus_pending_call_queue_timeout_error_unlocked (pending, 03328 connection); 03329 _dbus_connection_remove_timeout_unlocked (connection, 03330 _dbus_pending_call_get_timeout_unlocked (pending)); 03331 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 03332 03333 _dbus_verbose ("middle\n"); 03334 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03335 03336 /* Unlocks, and calls out to user code */ 03337 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03338 03339 return TRUE; 03340 } 03341 03381 dbus_bool_t 03382 dbus_connection_send_with_reply (DBusConnection *connection, 03383 DBusMessage *message, 03384 DBusPendingCall **pending_return, 03385 int timeout_milliseconds) 03386 { 03387 DBusPendingCall *pending; 03388 dbus_int32_t serial = -1; 03389 DBusDispatchStatus status; 03390 03391 _dbus_return_val_if_fail (connection != NULL, FALSE); 03392 _dbus_return_val_if_fail (message != NULL, FALSE); 03393 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03394 03395 if (pending_return) 03396 *pending_return = NULL; 03397 03398 CONNECTION_LOCK (connection); 03399 03400 #ifdef HAVE_UNIX_FD_PASSING 03401 03402 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03403 message->n_unix_fds > 0) 03404 { 03405 /* Refuse to send fds on a connection that cannot handle 03406 them. Unfortunately we cannot return a proper error here, so 03407 the best we can do is return TRUE but leave *pending_return 03408 as NULL. */ 03409 CONNECTION_UNLOCK (connection); 03410 return TRUE; 03411 } 03412 03413 #endif 03414 03415 if (!_dbus_connection_get_is_connected_unlocked (connection)) 03416 { 03417 CONNECTION_UNLOCK (connection); 03418 03419 return TRUE; 03420 } 03421 03422 pending = _dbus_pending_call_new_unlocked (connection, 03423 timeout_milliseconds, 03424 reply_handler_timeout); 03425 03426 if (pending == NULL) 03427 { 03428 CONNECTION_UNLOCK (connection); 03429 return FALSE; 03430 } 03431 03432 /* Assign a serial to the message */ 03433 serial = dbus_message_get_serial (message); 03434 if (serial == 0) 03435 { 03436 serial = _dbus_connection_get_next_client_serial (connection); 03437 dbus_message_set_serial (message, serial); 03438 } 03439 03440 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial)) 03441 goto error; 03442 03443 /* Insert the serial in the pending replies hash; 03444 * hash takes a refcount on DBusPendingCall. 03445 * Also, add the timeout. 03446 */ 03447 if (!_dbus_connection_attach_pending_call_unlocked (connection, 03448 pending)) 03449 goto error; 03450 03451 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL)) 03452 { 03453 _dbus_connection_detach_pending_call_and_unlock (connection, 03454 pending); 03455 goto error_unlocked; 03456 } 03457 03458 if (pending_return) 03459 *pending_return = pending; /* hand off refcount */ 03460 else 03461 { 03462 _dbus_connection_detach_pending_call_unlocked (connection, pending); 03463 /* we still have a ref to the pending call in this case, we unref 03464 * after unlocking, below 03465 */ 03466 } 03467 03468 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03469 03470 /* this calls out to user code */ 03471 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03472 03473 if (pending_return == NULL) 03474 dbus_pending_call_unref (pending); 03475 03476 return TRUE; 03477 03478 error: 03479 CONNECTION_UNLOCK (connection); 03480 error_unlocked: 03481 dbus_pending_call_unref (pending); 03482 return FALSE; 03483 } 03484 03515 DBusMessage* 03516 dbus_connection_send_with_reply_and_block (DBusConnection *connection, 03517 DBusMessage *message, 03518 int timeout_milliseconds, 03519 DBusError *error) 03520 { 03521 DBusMessage *reply; 03522 DBusPendingCall *pending; 03523 03524 _dbus_return_val_if_fail (connection != NULL, NULL); 03525 _dbus_return_val_if_fail (message != NULL, NULL); 03526 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL); 03527 _dbus_return_val_if_error_is_set (error, NULL); 03528 03529 #ifdef HAVE_UNIX_FD_PASSING 03530 03531 CONNECTION_LOCK (connection); 03532 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03533 message->n_unix_fds > 0) 03534 { 03535 CONNECTION_UNLOCK (connection); 03536 dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection."); 03537 return NULL; 03538 } 03539 CONNECTION_UNLOCK (connection); 03540 03541 #endif 03542 03543 if (!dbus_connection_send_with_reply (connection, message, 03544 &pending, timeout_milliseconds)) 03545 { 03546 _DBUS_SET_OOM (error); 03547 return NULL; 03548 } 03549 03550 if (pending == NULL) 03551 { 03552 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed"); 03553 return NULL; 03554 } 03555 03556 dbus_pending_call_block (pending); 03557 03558 reply = dbus_pending_call_steal_reply (pending); 03559 dbus_pending_call_unref (pending); 03560 03561 /* call_complete_and_unlock() called from pending_call_block() should 03562 * always fill this in. 03563 */ 03564 _dbus_assert (reply != NULL); 03565 03566 if (dbus_set_error_from_message (error, reply)) 03567 { 03568 dbus_message_unref (reply); 03569 return NULL; 03570 } 03571 else 03572 return reply; 03573 } 03574 03583 static DBusDispatchStatus 03584 _dbus_connection_flush_unlocked (DBusConnection *connection) 03585 { 03586 /* We have to specify DBUS_ITERATION_DO_READING here because 03587 * otherwise we could have two apps deadlock if they are both doing 03588 * a flush(), and the kernel buffers fill up. This could change the 03589 * dispatch status. 03590 */ 03591 DBusDispatchStatus status; 03592 03593 HAVE_LOCK_CHECK (connection); 03594 03595 while (connection->n_outgoing > 0 && 03596 _dbus_connection_get_is_connected_unlocked (connection)) 03597 { 03598 _dbus_verbose ("doing iteration in\n"); 03599 HAVE_LOCK_CHECK (connection); 03600 _dbus_connection_do_iteration_unlocked (connection, 03601 NULL, 03602 DBUS_ITERATION_DO_READING | 03603 DBUS_ITERATION_DO_WRITING | 03604 DBUS_ITERATION_BLOCK, 03605 -1); 03606 } 03607 03608 HAVE_LOCK_CHECK (connection); 03609 _dbus_verbose ("middle\n"); 03610 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03611 03612 HAVE_LOCK_CHECK (connection); 03613 return status; 03614 } 03615 03621 void 03622 dbus_connection_flush (DBusConnection *connection) 03623 { 03624 /* We have to specify DBUS_ITERATION_DO_READING here because 03625 * otherwise we could have two apps deadlock if they are both doing 03626 * a flush(), and the kernel buffers fill up. This could change the 03627 * dispatch status. 03628 */ 03629 DBusDispatchStatus status; 03630 03631 _dbus_return_if_fail (connection != NULL); 03632 03633 CONNECTION_LOCK (connection); 03634 03635 status = _dbus_connection_flush_unlocked (connection); 03636 03637 HAVE_LOCK_CHECK (connection); 03638 /* Unlocks and calls out to user code */ 03639 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03640 03641 _dbus_verbose ("end\n"); 03642 } 03643 03654 static dbus_bool_t 03655 _dbus_connection_read_write_dispatch (DBusConnection *connection, 03656 int timeout_milliseconds, 03657 dbus_bool_t dispatch) 03658 { 03659 DBusDispatchStatus dstatus; 03660 dbus_bool_t progress_possible; 03661 03662 /* Need to grab a ref here in case we're a private connection and 03663 * the user drops the last ref in a handler we call; see bug 03664 * https://bugs.freedesktop.org/show_bug.cgi?id=15635 03665 */ 03666 dbus_connection_ref (connection); 03667 dstatus = dbus_connection_get_dispatch_status (connection); 03668 03669 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS) 03670 { 03671 _dbus_verbose ("doing dispatch\n"); 03672 dbus_connection_dispatch (connection); 03673 CONNECTION_LOCK (connection); 03674 } 03675 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY) 03676 { 03677 _dbus_verbose ("pausing for memory\n"); 03678 _dbus_memory_pause_based_on_timeout (timeout_milliseconds); 03679 CONNECTION_LOCK (connection); 03680 } 03681 else 03682 { 03683 CONNECTION_LOCK (connection); 03684 if (_dbus_connection_get_is_connected_unlocked (connection)) 03685 { 03686 _dbus_verbose ("doing iteration\n"); 03687 _dbus_connection_do_iteration_unlocked (connection, 03688 NULL, 03689 DBUS_ITERATION_DO_READING | 03690 DBUS_ITERATION_DO_WRITING | 03691 DBUS_ITERATION_BLOCK, 03692 timeout_milliseconds); 03693 } 03694 } 03695 03696 HAVE_LOCK_CHECK (connection); 03697 /* If we can dispatch, we can make progress until the Disconnected message 03698 * has been processed; if we can only read/write, we can make progress 03699 * as long as the transport is open. 03700 */ 03701 if (dispatch) 03702 progress_possible = connection->n_incoming != 0 || 03703 connection->disconnect_message_link != NULL; 03704 else 03705 progress_possible = _dbus_connection_get_is_connected_unlocked (connection); 03706 03707 CONNECTION_UNLOCK (connection); 03708 03709 dbus_connection_unref (connection); 03710 03711 return progress_possible; /* TRUE if we can make more progress */ 03712 } 03713 03714 03749 dbus_bool_t 03750 dbus_connection_read_write_dispatch (DBusConnection *connection, 03751 int timeout_milliseconds) 03752 { 03753 _dbus_return_val_if_fail (connection != NULL, FALSE); 03754 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03755 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE); 03756 } 03757 03781 dbus_bool_t 03782 dbus_connection_read_write (DBusConnection *connection, 03783 int timeout_milliseconds) 03784 { 03785 _dbus_return_val_if_fail (connection != NULL, FALSE); 03786 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03787 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE); 03788 } 03789 03790 /* We need to call this anytime we pop the head of the queue, and then 03791 * update_dispatch_status_and_unlock needs to be called afterward 03792 * which will "process" the disconnected message and set 03793 * disconnected_message_processed. 03794 */ 03795 static void 03796 check_disconnected_message_arrived_unlocked (DBusConnection *connection, 03797 DBusMessage *head_of_queue) 03798 { 03799 HAVE_LOCK_CHECK (connection); 03800 03801 /* checking that the link is NULL is an optimization to avoid the is_signal call */ 03802 if (connection->disconnect_message_link == NULL && 03803 dbus_message_is_signal (head_of_queue, 03804 DBUS_INTERFACE_LOCAL, 03805 "Disconnected")) 03806 { 03807 connection->disconnected_message_arrived = TRUE; 03808 } 03809 } 03810 03830 DBusMessage* 03831 dbus_connection_borrow_message (DBusConnection *connection) 03832 { 03833 DBusDispatchStatus status; 03834 DBusMessage *message; 03835 03836 _dbus_return_val_if_fail (connection != NULL, NULL); 03837 03838 _dbus_verbose ("start\n"); 03839 03840 /* this is called for the side effect that it queues 03841 * up any messages from the transport 03842 */ 03843 status = dbus_connection_get_dispatch_status (connection); 03844 if (status != DBUS_DISPATCH_DATA_REMAINS) 03845 return NULL; 03846 03847 CONNECTION_LOCK (connection); 03848 03849 _dbus_connection_acquire_dispatch (connection); 03850 03851 /* While a message is outstanding, the dispatch lock is held */ 03852 _dbus_assert (connection->message_borrowed == NULL); 03853 03854 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages); 03855 03856 message = connection->message_borrowed; 03857 03858 check_disconnected_message_arrived_unlocked (connection, message); 03859 03860 /* Note that we KEEP the dispatch lock until the message is returned */ 03861 if (message == NULL) 03862 _dbus_connection_release_dispatch (connection); 03863 03864 CONNECTION_UNLOCK (connection); 03865 03866 /* We don't update dispatch status until it's returned or stolen */ 03867 03868 return message; 03869 } 03870 03879 void 03880 dbus_connection_return_message (DBusConnection *connection, 03881 DBusMessage *message) 03882 { 03883 DBusDispatchStatus status; 03884 03885 _dbus_return_if_fail (connection != NULL); 03886 _dbus_return_if_fail (message != NULL); 03887 _dbus_return_if_fail (message == connection->message_borrowed); 03888 _dbus_return_if_fail (connection->dispatch_acquired); 03889 03890 CONNECTION_LOCK (connection); 03891 03892 _dbus_assert (message == connection->message_borrowed); 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 03911 void 03912 dbus_connection_steal_borrowed_message (DBusConnection *connection, 03913 DBusMessage *message) 03914 { 03915 DBusMessage *pop_message; 03916 DBusDispatchStatus status; 03917 03918 _dbus_return_if_fail (connection != NULL); 03919 _dbus_return_if_fail (message != NULL); 03920 _dbus_return_if_fail (message == connection->message_borrowed); 03921 _dbus_return_if_fail (connection->dispatch_acquired); 03922 03923 CONNECTION_LOCK (connection); 03924 03925 _dbus_assert (message == connection->message_borrowed); 03926 03927 pop_message = _dbus_list_pop_first (&connection->incoming_messages); 03928 _dbus_assert (message == pop_message); 03929 03930 connection->n_incoming -= 1; 03931 03932 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n", 03933 message, connection->n_incoming); 03934 03935 connection->message_borrowed = NULL; 03936 03937 _dbus_connection_release_dispatch (connection); 03938 03939 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03940 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03941 } 03942 03943 /* See dbus_connection_pop_message, but requires the caller to own 03944 * the lock before calling. May drop the lock while running. 03945 */ 03946 static DBusList* 03947 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection) 03948 { 03949 HAVE_LOCK_CHECK (connection); 03950 03951 _dbus_assert (connection->message_borrowed == NULL); 03952 03953 if (connection->n_incoming > 0) 03954 { 03955 DBusList *link; 03956 03957 link = _dbus_list_pop_first_link (&connection->incoming_messages); 03958 connection->n_incoming -= 1; 03959 03960 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from incoming queue %p, %d incoming\n", 03961 link->data, 03962 dbus_message_type_to_string (dbus_message_get_type (link->data)), 03963 dbus_message_get_path (link->data) ? 03964 dbus_message_get_path (link->data) : 03965 "no path", 03966 dbus_message_get_interface (link->data) ? 03967 dbus_message_get_interface (link->data) : 03968 "no interface", 03969 dbus_message_get_member (link->data) ? 03970 dbus_message_get_member (link->data) : 03971 "no member", 03972 dbus_message_get_signature (link->data), 03973 connection, connection->n_incoming); 03974 03975 check_disconnected_message_arrived_unlocked (connection, link->data); 03976 03977 return link; 03978 } 03979 else 03980 return NULL; 03981 } 03982 03983 /* See dbus_connection_pop_message, but requires the caller to own 03984 * the lock before calling. May drop the lock while running. 03985 */ 03986 static DBusMessage* 03987 _dbus_connection_pop_message_unlocked (DBusConnection *connection) 03988 { 03989 DBusList *link; 03990 03991 HAVE_LOCK_CHECK (connection); 03992 03993 link = _dbus_connection_pop_message_link_unlocked (connection); 03994 03995 if (link != NULL) 03996 { 03997 DBusMessage *message; 03998 03999 message = link->data; 04000 04001 _dbus_list_free_link (link); 04002 04003 return message; 04004 } 04005 else 04006 return NULL; 04007 } 04008 04009 static void 04010 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection, 04011 DBusList *message_link) 04012 { 04013 HAVE_LOCK_CHECK (connection); 04014 04015 _dbus_assert (message_link != NULL); 04016 /* You can't borrow a message while a link is outstanding */ 04017 _dbus_assert (connection->message_borrowed == NULL); 04018 /* We had to have the dispatch lock across the pop/putback */ 04019 _dbus_assert (connection->dispatch_acquired); 04020 04021 _dbus_list_prepend_link (&connection->incoming_messages, 04022 message_link); 04023 connection->n_incoming += 1; 04024 04025 _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n", 04026 message_link->data, 04027 dbus_message_type_to_string (dbus_message_get_type (message_link->data)), 04028 dbus_message_get_interface (message_link->data) ? 04029 dbus_message_get_interface (message_link->data) : 04030 "no interface", 04031 dbus_message_get_member (message_link->data) ? 04032 dbus_message_get_member (message_link->data) : 04033 "no member", 04034 dbus_message_get_signature (message_link->data), 04035 connection, connection->n_incoming); 04036 } 04037 04057 DBusMessage* 04058 dbus_connection_pop_message (DBusConnection *connection) 04059 { 04060 DBusMessage *message; 04061 DBusDispatchStatus status; 04062 04063 _dbus_verbose ("start\n"); 04064 04065 /* this is called for the side effect that it queues 04066 * up any messages from the transport 04067 */ 04068 status = dbus_connection_get_dispatch_status (connection); 04069 if (status != DBUS_DISPATCH_DATA_REMAINS) 04070 return NULL; 04071 04072 CONNECTION_LOCK (connection); 04073 _dbus_connection_acquire_dispatch (connection); 04074 HAVE_LOCK_CHECK (connection); 04075 04076 message = _dbus_connection_pop_message_unlocked (connection); 04077 04078 _dbus_verbose ("Returning popped message %p\n", message); 04079 04080 _dbus_connection_release_dispatch (connection); 04081 04082 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04083 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04084 04085 return message; 04086 } 04087 04095 static void 04096 _dbus_connection_acquire_dispatch (DBusConnection *connection) 04097 { 04098 HAVE_LOCK_CHECK (connection); 04099 04100 _dbus_connection_ref_unlocked (connection); 04101 CONNECTION_UNLOCK (connection); 04102 04103 _dbus_verbose ("locking dispatch_mutex\n"); 04104 _dbus_mutex_lock (connection->dispatch_mutex); 04105 04106 while (connection->dispatch_acquired) 04107 { 04108 _dbus_verbose ("waiting for dispatch to be acquirable\n"); 04109 _dbus_condvar_wait (connection->dispatch_cond, 04110 connection->dispatch_mutex); 04111 } 04112 04113 _dbus_assert (!connection->dispatch_acquired); 04114 04115 connection->dispatch_acquired = TRUE; 04116 04117 _dbus_verbose ("unlocking dispatch_mutex\n"); 04118 _dbus_mutex_unlock (connection->dispatch_mutex); 04119 04120 CONNECTION_LOCK (connection); 04121 _dbus_connection_unref_unlocked (connection); 04122 } 04123 04131 static void 04132 _dbus_connection_release_dispatch (DBusConnection *connection) 04133 { 04134 HAVE_LOCK_CHECK (connection); 04135 04136 _dbus_verbose ("locking dispatch_mutex\n"); 04137 _dbus_mutex_lock (connection->dispatch_mutex); 04138 04139 _dbus_assert (connection->dispatch_acquired); 04140 04141 connection->dispatch_acquired = FALSE; 04142 _dbus_condvar_wake_one (connection->dispatch_cond); 04143 04144 _dbus_verbose ("unlocking dispatch_mutex\n"); 04145 _dbus_mutex_unlock (connection->dispatch_mutex); 04146 } 04147 04148 static void 04149 _dbus_connection_failed_pop (DBusConnection *connection, 04150 DBusList *message_link) 04151 { 04152 _dbus_list_prepend_link (&connection->incoming_messages, 04153 message_link); 04154 connection->n_incoming += 1; 04155 } 04156 04157 /* Note this may be called multiple times since we don't track whether we already did it */ 04158 static void 04159 notify_disconnected_unlocked (DBusConnection *connection) 04160 { 04161 HAVE_LOCK_CHECK (connection); 04162 04163 /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected 04164 * connection from dbus_bus_get(). We make the same guarantee for 04165 * dbus_connection_open() but in a different way since we don't want to 04166 * unref right here; we instead check for connectedness before returning 04167 * the connection from the hash. 04168 */ 04169 _dbus_bus_notify_shared_connection_disconnected_unlocked (connection); 04170 04171 /* Dump the outgoing queue, we aren't going to be able to 04172 * send it now, and we'd like accessors like 04173 * dbus_connection_get_outgoing_size() to be accurate. 04174 */ 04175 if (connection->n_outgoing > 0) 04176 { 04177 DBusList *link; 04178 04179 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n", 04180 connection->n_outgoing); 04181 04182 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages))) 04183 { 04184 _dbus_connection_message_sent (connection, link->data); 04185 } 04186 } 04187 } 04188 04189 /* Note this may be called multiple times since we don't track whether we already did it */ 04190 static DBusDispatchStatus 04191 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection) 04192 { 04193 HAVE_LOCK_CHECK (connection); 04194 04195 if (connection->disconnect_message_link != NULL) 04196 { 04197 _dbus_verbose ("Sending disconnect message\n"); 04198 04199 /* If we have pending calls, queue their timeouts - we want the Disconnected 04200 * to be the last message, after these timeouts. 04201 */ 04202 connection_timeout_and_complete_all_pending_calls_unlocked (connection); 04203 04204 /* We haven't sent the disconnect message already, 04205 * and all real messages have been queued up. 04206 */ 04207 _dbus_connection_queue_synthesized_message_link (connection, 04208 connection->disconnect_message_link); 04209 connection->disconnect_message_link = NULL; 04210 04211 return DBUS_DISPATCH_DATA_REMAINS; 04212 } 04213 04214 return DBUS_DISPATCH_COMPLETE; 04215 } 04216 04217 static DBusDispatchStatus 04218 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection) 04219 { 04220 HAVE_LOCK_CHECK (connection); 04221 04222 if (connection->n_incoming > 0) 04223 return DBUS_DISPATCH_DATA_REMAINS; 04224 else if (!_dbus_transport_queue_messages (connection->transport)) 04225 return DBUS_DISPATCH_NEED_MEMORY; 04226 else 04227 { 04228 DBusDispatchStatus status; 04229 dbus_bool_t is_connected; 04230 04231 status = _dbus_transport_get_dispatch_status (connection->transport); 04232 is_connected = _dbus_transport_get_is_connected (connection->transport); 04233 04234 _dbus_verbose ("dispatch status = %s is_connected = %d\n", 04235 DISPATCH_STATUS_NAME (status), is_connected); 04236 04237 if (!is_connected) 04238 { 04239 /* It's possible this would be better done by having an explicit 04240 * notification from _dbus_transport_disconnect() that would 04241 * synchronously do this, instead of waiting for the next dispatch 04242 * status check. However, probably not good to change until it causes 04243 * a problem. 04244 */ 04245 notify_disconnected_unlocked (connection); 04246 04247 /* I'm not sure this is needed; the idea is that we want to 04248 * queue the Disconnected only after we've read all the 04249 * messages, but if we're disconnected maybe we are guaranteed 04250 * to have read them all ? 04251 */ 04252 if (status == DBUS_DISPATCH_COMPLETE) 04253 status = notify_disconnected_and_dispatch_complete_unlocked (connection); 04254 } 04255 04256 if (status != DBUS_DISPATCH_COMPLETE) 04257 return status; 04258 else if (connection->n_incoming > 0) 04259 return DBUS_DISPATCH_DATA_REMAINS; 04260 else 04261 return DBUS_DISPATCH_COMPLETE; 04262 } 04263 } 04264 04265 static void 04266 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection, 04267 DBusDispatchStatus new_status) 04268 { 04269 dbus_bool_t changed; 04270 DBusDispatchStatusFunction function; 04271 void *data; 04272 04273 HAVE_LOCK_CHECK (connection); 04274 04275 _dbus_connection_ref_unlocked (connection); 04276 04277 changed = new_status != connection->last_dispatch_status; 04278 04279 connection->last_dispatch_status = new_status; 04280 04281 function = connection->dispatch_status_function; 04282 data = connection->dispatch_status_data; 04283 04284 if (connection->disconnected_message_arrived && 04285 !connection->disconnected_message_processed) 04286 { 04287 connection->disconnected_message_processed = TRUE; 04288 04289 /* this does an unref, but we have a ref 04290 * so we should not run the finalizer here 04291 * inside the lock. 04292 */ 04293 connection_forget_shared_unlocked (connection); 04294 04295 if (connection->exit_on_disconnect) 04296 { 04297 CONNECTION_UNLOCK (connection); 04298 04299 _dbus_verbose ("Exiting on Disconnected signal\n"); 04300 _dbus_exit (1); 04301 _dbus_assert_not_reached ("Call to exit() returned"); 04302 } 04303 } 04304 04305 /* We drop the lock */ 04306 CONNECTION_UNLOCK (connection); 04307 04308 if (changed && function) 04309 { 04310 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n", 04311 connection, new_status, 04312 DISPATCH_STATUS_NAME (new_status)); 04313 (* function) (connection, new_status, data); 04314 } 04315 04316 dbus_connection_unref (connection); 04317 } 04318 04344 DBusDispatchStatus 04345 dbus_connection_get_dispatch_status (DBusConnection *connection) 04346 { 04347 DBusDispatchStatus status; 04348 04349 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE); 04350 04351 _dbus_verbose ("start\n"); 04352 04353 CONNECTION_LOCK (connection); 04354 04355 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04356 04357 CONNECTION_UNLOCK (connection); 04358 04359 return status; 04360 } 04361 04365 static DBusHandlerResult 04366 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection, 04367 DBusMessage *message) 04368 { 04369 if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL) 04370 { 04371 /* This means we're letting the bus route this message */ 04372 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04373 } 04374 else if (dbus_message_is_method_call (message, 04375 DBUS_INTERFACE_PEER, 04376 "Ping")) 04377 { 04378 DBusMessage *ret; 04379 dbus_bool_t sent; 04380 04381 ret = dbus_message_new_method_return (message); 04382 if (ret == NULL) 04383 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04384 04385 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04386 04387 dbus_message_unref (ret); 04388 04389 if (!sent) 04390 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04391 04392 return DBUS_HANDLER_RESULT_HANDLED; 04393 } 04394 else if (dbus_message_is_method_call (message, 04395 DBUS_INTERFACE_PEER, 04396 "GetMachineId")) 04397 { 04398 DBusMessage *ret; 04399 dbus_bool_t sent; 04400 DBusString uuid; 04401 04402 ret = dbus_message_new_method_return (message); 04403 if (ret == NULL) 04404 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04405 04406 sent = FALSE; 04407 _dbus_string_init (&uuid); 04408 if (_dbus_get_local_machine_uuid_encoded (&uuid)) 04409 { 04410 const char *v_STRING = _dbus_string_get_const_data (&uuid); 04411 if (dbus_message_append_args (ret, 04412 DBUS_TYPE_STRING, &v_STRING, 04413 DBUS_TYPE_INVALID)) 04414 { 04415 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04416 } 04417 } 04418 _dbus_string_free (&uuid); 04419 04420 dbus_message_unref (ret); 04421 04422 if (!sent) 04423 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04424 04425 return DBUS_HANDLER_RESULT_HANDLED; 04426 } 04427 else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER)) 04428 { 04429 /* We need to bounce anything else with this interface, otherwise apps 04430 * could start extending the interface and when we added extensions 04431 * here to DBusConnection we'd break those apps. 04432 */ 04433 04434 DBusMessage *ret; 04435 dbus_bool_t sent; 04436 04437 ret = dbus_message_new_error (message, 04438 DBUS_ERROR_UNKNOWN_METHOD, 04439 "Unknown method invoked on org.freedesktop.DBus.Peer interface"); 04440 if (ret == NULL) 04441 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04442 04443 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04444 04445 dbus_message_unref (ret); 04446 04447 if (!sent) 04448 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04449 04450 return DBUS_HANDLER_RESULT_HANDLED; 04451 } 04452 else 04453 { 04454 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04455 } 04456 } 04457 04464 static DBusHandlerResult 04465 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection, 04466 DBusMessage *message) 04467 { 04468 /* We just run one filter for now but have the option to run more 04469 if the spec calls for it in the future */ 04470 04471 return _dbus_connection_peer_filter_unlocked_no_update (connection, message); 04472 } 04473 04516 DBusDispatchStatus 04517 dbus_connection_dispatch (DBusConnection *connection) 04518 { 04519 DBusMessage *message; 04520 DBusList *link, *filter_list_copy, *message_link; 04521 DBusHandlerResult result; 04522 DBusPendingCall *pending; 04523 dbus_int32_t reply_serial; 04524 DBusDispatchStatus status; 04525 04526 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE); 04527 04528 _dbus_verbose ("\n"); 04529 04530 CONNECTION_LOCK (connection); 04531 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04532 if (status != DBUS_DISPATCH_DATA_REMAINS) 04533 { 04534 /* unlocks and calls out to user code */ 04535 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04536 return status; 04537 } 04538 04539 /* We need to ref the connection since the callback could potentially 04540 * drop the last ref to it 04541 */ 04542 _dbus_connection_ref_unlocked (connection); 04543 04544 _dbus_connection_acquire_dispatch (connection); 04545 HAVE_LOCK_CHECK (connection); 04546 04547 message_link = _dbus_connection_pop_message_link_unlocked (connection); 04548 if (message_link == NULL) 04549 { 04550 /* another thread dispatched our stuff */ 04551 04552 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n"); 04553 04554 _dbus_connection_release_dispatch (connection); 04555 04556 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04557 04558 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04559 04560 dbus_connection_unref (connection); 04561 04562 return status; 04563 } 04564 04565 message = message_link->data; 04566 04567 _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n", 04568 message, 04569 dbus_message_type_to_string (dbus_message_get_type (message)), 04570 dbus_message_get_interface (message) ? 04571 dbus_message_get_interface (message) : 04572 "no interface", 04573 dbus_message_get_member (message) ? 04574 dbus_message_get_member (message) : 04575 "no member", 04576 dbus_message_get_signature (message)); 04577 04578 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04579 04580 /* Pending call handling must be first, because if you do 04581 * dbus_connection_send_with_reply_and_block() or 04582 * dbus_pending_call_block() then no handlers/filters will be run on 04583 * the reply. We want consistent semantics in the case where we 04584 * dbus_connection_dispatch() the reply. 04585 */ 04586 04587 reply_serial = dbus_message_get_reply_serial (message); 04588 pending = _dbus_hash_table_lookup_int (connection->pending_replies, 04589 reply_serial); 04590 if (pending) 04591 { 04592 _dbus_verbose ("Dispatching a pending reply\n"); 04593 complete_pending_call_and_unlock (connection, pending, message); 04594 pending = NULL; /* it's probably unref'd */ 04595 04596 CONNECTION_LOCK (connection); 04597 _dbus_verbose ("pending call completed in dispatch\n"); 04598 result = DBUS_HANDLER_RESULT_HANDLED; 04599 goto out; 04600 } 04601 04602 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message); 04603 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04604 goto out; 04605 04606 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy)) 04607 { 04608 _dbus_connection_release_dispatch (connection); 04609 HAVE_LOCK_CHECK (connection); 04610 04611 _dbus_connection_failed_pop (connection, message_link); 04612 04613 /* unlocks and calls user code */ 04614 _dbus_connection_update_dispatch_status_and_unlock (connection, 04615 DBUS_DISPATCH_NEED_MEMORY); 04616 04617 if (pending) 04618 dbus_pending_call_unref (pending); 04619 dbus_connection_unref (connection); 04620 04621 return DBUS_DISPATCH_NEED_MEMORY; 04622 } 04623 04624 _dbus_list_foreach (&filter_list_copy, 04625 (DBusForeachFunction)_dbus_message_filter_ref, 04626 NULL); 04627 04628 /* We're still protected from dispatch() reentrancy here 04629 * since we acquired the dispatcher 04630 */ 04631 CONNECTION_UNLOCK (connection); 04632 04633 link = _dbus_list_get_first_link (&filter_list_copy); 04634 while (link != NULL) 04635 { 04636 DBusMessageFilter *filter = link->data; 04637 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link); 04638 04639 if (filter->function == NULL) 04640 { 04641 _dbus_verbose (" filter was removed in a callback function\n"); 04642 link = next; 04643 continue; 04644 } 04645 04646 _dbus_verbose (" running filter on message %p\n", message); 04647 result = (* filter->function) (connection, message, filter->user_data); 04648 04649 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04650 break; 04651 04652 link = next; 04653 } 04654 04655 _dbus_list_foreach (&filter_list_copy, 04656 (DBusForeachFunction)_dbus_message_filter_unref, 04657 NULL); 04658 _dbus_list_clear (&filter_list_copy); 04659 04660 CONNECTION_LOCK (connection); 04661 04662 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) 04663 { 04664 _dbus_verbose ("No memory\n"); 04665 goto out; 04666 } 04667 else if (result == DBUS_HANDLER_RESULT_HANDLED) 04668 { 04669 _dbus_verbose ("filter handled message in dispatch\n"); 04670 goto out; 04671 } 04672 04673 /* We're still protected from dispatch() reentrancy here 04674 * since we acquired the dispatcher 04675 */ 04676 _dbus_verbose (" running object path dispatch on message %p (%s %s %s '%s')\n", 04677 message, 04678 dbus_message_type_to_string (dbus_message_get_type (message)), 04679 dbus_message_get_interface (message) ? 04680 dbus_message_get_interface (message) : 04681 "no interface", 04682 dbus_message_get_member (message) ? 04683 dbus_message_get_member (message) : 04684 "no member", 04685 dbus_message_get_signature (message)); 04686 04687 HAVE_LOCK_CHECK (connection); 04688 result = _dbus_object_tree_dispatch_and_unlock (connection->objects, 04689 message); 04690 04691 CONNECTION_LOCK (connection); 04692 04693 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04694 { 04695 _dbus_verbose ("object tree handled message in dispatch\n"); 04696 goto out; 04697 } 04698 04699 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL) 04700 { 04701 DBusMessage *reply; 04702 DBusString str; 04703 DBusPreallocatedSend *preallocated; 04704 04705 _dbus_verbose (" sending error %s\n", 04706 DBUS_ERROR_UNKNOWN_METHOD); 04707 04708 if (!_dbus_string_init (&str)) 04709 { 04710 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04711 _dbus_verbose ("no memory for error string in dispatch\n"); 04712 goto out; 04713 } 04714 04715 if (!_dbus_string_append_printf (&str, 04716 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n", 04717 dbus_message_get_member (message), 04718 dbus_message_get_signature (message), 04719 dbus_message_get_interface (message))) 04720 { 04721 _dbus_string_free (&str); 04722 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04723 _dbus_verbose ("no memory for error string in dispatch\n"); 04724 goto out; 04725 } 04726 04727 reply = dbus_message_new_error (message, 04728 DBUS_ERROR_UNKNOWN_METHOD, 04729 _dbus_string_get_const_data (&str)); 04730 _dbus_string_free (&str); 04731 04732 if (reply == NULL) 04733 { 04734 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04735 _dbus_verbose ("no memory for error reply in dispatch\n"); 04736 goto out; 04737 } 04738 04739 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 04740 04741 if (preallocated == NULL) 04742 { 04743 dbus_message_unref (reply); 04744 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04745 _dbus_verbose ("no memory for error send in dispatch\n"); 04746 goto out; 04747 } 04748 04749 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated, 04750 reply, NULL); 04751 04752 dbus_message_unref (reply); 04753 04754 result = DBUS_HANDLER_RESULT_HANDLED; 04755 } 04756 04757 _dbus_verbose (" done dispatching %p (%s %s %s '%s') on connection %p\n", message, 04758 dbus_message_type_to_string (dbus_message_get_type (message)), 04759 dbus_message_get_interface (message) ? 04760 dbus_message_get_interface (message) : 04761 "no interface", 04762 dbus_message_get_member (message) ? 04763 dbus_message_get_member (message) : 04764 "no member", 04765 dbus_message_get_signature (message), 04766 connection); 04767 04768 out: 04769 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) 04770 { 04771 _dbus_verbose ("out of memory\n"); 04772 04773 /* Put message back, and we'll start over. 04774 * Yes this means handlers must be idempotent if they 04775 * don't return HANDLED; c'est la vie. 04776 */ 04777 _dbus_connection_putback_message_link_unlocked (connection, 04778 message_link); 04779 } 04780 else 04781 { 04782 _dbus_verbose (" ... done dispatching\n"); 04783 04784 _dbus_list_free_link (message_link); 04785 dbus_message_unref (message); /* don't want the message to count in max message limits 04786 * in computing dispatch status below 04787 */ 04788 } 04789 04790 _dbus_connection_release_dispatch (connection); 04791 HAVE_LOCK_CHECK (connection); 04792 04793 _dbus_verbose ("before final status update\n"); 04794 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04795 04796 /* unlocks and calls user code */ 04797 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04798 04799 dbus_connection_unref (connection); 04800 04801 return status; 04802 } 04803 04865 dbus_bool_t 04866 dbus_connection_set_watch_functions (DBusConnection *connection, 04867 DBusAddWatchFunction add_function, 04868 DBusRemoveWatchFunction remove_function, 04869 DBusWatchToggledFunction toggled_function, 04870 void *data, 04871 DBusFreeFunction free_data_function) 04872 { 04873 dbus_bool_t retval; 04874 04875 _dbus_return_val_if_fail (connection != NULL, FALSE); 04876 04877 CONNECTION_LOCK (connection); 04878 04879 retval = _dbus_watch_list_set_functions (connection->watches, 04880 add_function, remove_function, 04881 toggled_function, 04882 data, free_data_function); 04883 04884 CONNECTION_UNLOCK (connection); 04885 04886 return retval; 04887 } 04888 04928 dbus_bool_t 04929 dbus_connection_set_timeout_functions (DBusConnection *connection, 04930 DBusAddTimeoutFunction add_function, 04931 DBusRemoveTimeoutFunction remove_function, 04932 DBusTimeoutToggledFunction toggled_function, 04933 void *data, 04934 DBusFreeFunction free_data_function) 04935 { 04936 dbus_bool_t retval; 04937 04938 _dbus_return_val_if_fail (connection != NULL, FALSE); 04939 04940 CONNECTION_LOCK (connection); 04941 04942 retval = _dbus_timeout_list_set_functions (connection->timeouts, 04943 add_function, remove_function, 04944 toggled_function, 04945 data, free_data_function); 04946 04947 CONNECTION_UNLOCK (connection); 04948 04949 return retval; 04950 } 04951 04966 void 04967 dbus_connection_set_wakeup_main_function (DBusConnection *connection, 04968 DBusWakeupMainFunction wakeup_main_function, 04969 void *data, 04970 DBusFreeFunction free_data_function) 04971 { 04972 void *old_data; 04973 DBusFreeFunction old_free_data; 04974 04975 _dbus_return_if_fail (connection != NULL); 04976 04977 CONNECTION_LOCK (connection); 04978 old_data = connection->wakeup_main_data; 04979 old_free_data = connection->free_wakeup_main_data; 04980 04981 connection->wakeup_main_function = wakeup_main_function; 04982 connection->wakeup_main_data = data; 04983 connection->free_wakeup_main_data = free_data_function; 04984 04985 CONNECTION_UNLOCK (connection); 04986 04987 /* Callback outside the lock */ 04988 if (old_free_data) 04989 (*old_free_data) (old_data); 04990 } 04991 05012 void 05013 dbus_connection_set_dispatch_status_function (DBusConnection *connection, 05014 DBusDispatchStatusFunction function, 05015 void *data, 05016 DBusFreeFunction free_data_function) 05017 { 05018 void *old_data; 05019 DBusFreeFunction old_free_data; 05020 05021 _dbus_return_if_fail (connection != NULL); 05022 05023 CONNECTION_LOCK (connection); 05024 old_data = connection->dispatch_status_data; 05025 old_free_data = connection->free_dispatch_status_data; 05026 05027 connection->dispatch_status_function = function; 05028 connection->dispatch_status_data = data; 05029 connection->free_dispatch_status_data = free_data_function; 05030 05031 CONNECTION_UNLOCK (connection); 05032 05033 /* Callback outside the lock */ 05034 if (old_free_data) 05035 (*old_free_data) (old_data); 05036 } 05037 05057 dbus_bool_t 05058 dbus_connection_get_unix_fd (DBusConnection *connection, 05059 int *fd) 05060 { 05061 _dbus_return_val_if_fail (connection != NULL, FALSE); 05062 _dbus_return_val_if_fail (connection->transport != NULL, FALSE); 05063 05064 #ifdef DBUS_WIN 05065 /* FIXME do this on a lower level */ 05066 return FALSE; 05067 #endif 05068 05069 return dbus_connection_get_socket(connection, fd); 05070 } 05071 05087 dbus_bool_t 05088 dbus_connection_get_socket(DBusConnection *connection, 05089 int *fd) 05090 { 05091 dbus_bool_t retval; 05092 05093 _dbus_return_val_if_fail (connection != NULL, FALSE); 05094 _dbus_return_val_if_fail (connection->transport != NULL, FALSE); 05095 05096 CONNECTION_LOCK (connection); 05097 05098 retval = _dbus_transport_get_socket_fd (connection->transport, 05099 fd); 05100 05101 CONNECTION_UNLOCK (connection); 05102 05103 return retval; 05104 } 05105 05106 05129 dbus_bool_t 05130 dbus_connection_get_unix_user (DBusConnection *connection, 05131 unsigned long *uid) 05132 { 05133 dbus_bool_t result; 05134 05135 _dbus_return_val_if_fail (connection != NULL, FALSE); 05136 _dbus_return_val_if_fail (uid != NULL, FALSE); 05137 05138 CONNECTION_LOCK (connection); 05139 05140 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05141 result = FALSE; 05142 else 05143 result = _dbus_transport_get_unix_user (connection->transport, 05144 uid); 05145 05146 #ifdef DBUS_WIN 05147 _dbus_assert (!result); 05148 #endif 05149 05150 CONNECTION_UNLOCK (connection); 05151 05152 return result; 05153 } 05154 05165 dbus_bool_t 05166 dbus_connection_get_unix_process_id (DBusConnection *connection, 05167 unsigned long *pid) 05168 { 05169 dbus_bool_t result; 05170 05171 _dbus_return_val_if_fail (connection != NULL, FALSE); 05172 _dbus_return_val_if_fail (pid != NULL, FALSE); 05173 05174 CONNECTION_LOCK (connection); 05175 05176 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05177 result = FALSE; 05178 else 05179 result = _dbus_transport_get_unix_process_id (connection->transport, 05180 pid); 05181 05182 CONNECTION_UNLOCK (connection); 05183 05184 return result; 05185 } 05186 05197 dbus_bool_t 05198 dbus_connection_get_adt_audit_session_data (DBusConnection *connection, 05199 void **data, 05200 dbus_int32_t *data_size) 05201 { 05202 dbus_bool_t result; 05203 05204 _dbus_return_val_if_fail (connection != NULL, FALSE); 05205 _dbus_return_val_if_fail (data != NULL, FALSE); 05206 _dbus_return_val_if_fail (data_size != NULL, FALSE); 05207 05208 CONNECTION_LOCK (connection); 05209 05210 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05211 result = FALSE; 05212 else 05213 result = _dbus_transport_get_adt_audit_session_data (connection->transport, 05214 data, 05215 data_size); 05216 CONNECTION_UNLOCK (connection); 05217 05218 return result; 05219 } 05220 05243 void 05244 dbus_connection_set_unix_user_function (DBusConnection *connection, 05245 DBusAllowUnixUserFunction function, 05246 void *data, 05247 DBusFreeFunction free_data_function) 05248 { 05249 void *old_data = NULL; 05250 DBusFreeFunction old_free_function = NULL; 05251 05252 _dbus_return_if_fail (connection != NULL); 05253 05254 CONNECTION_LOCK (connection); 05255 _dbus_transport_set_unix_user_function (connection->transport, 05256 function, data, free_data_function, 05257 &old_data, &old_free_function); 05258 CONNECTION_UNLOCK (connection); 05259 05260 if (old_free_function != NULL) 05261 (* old_free_function) (old_data); 05262 } 05263 05295 dbus_bool_t 05296 dbus_connection_get_windows_user (DBusConnection *connection, 05297 char **windows_sid_p) 05298 { 05299 dbus_bool_t result; 05300 05301 _dbus_return_val_if_fail (connection != NULL, FALSE); 05302 _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE); 05303 05304 CONNECTION_LOCK (connection); 05305 05306 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05307 result = FALSE; 05308 else 05309 result = _dbus_transport_get_windows_user (connection->transport, 05310 windows_sid_p); 05311 05312 #ifdef DBUS_UNIX 05313 _dbus_assert (!result); 05314 #endif 05315 05316 CONNECTION_UNLOCK (connection); 05317 05318 return result; 05319 } 05320 05342 void 05343 dbus_connection_set_windows_user_function (DBusConnection *connection, 05344 DBusAllowWindowsUserFunction function, 05345 void *data, 05346 DBusFreeFunction free_data_function) 05347 { 05348 void *old_data = NULL; 05349 DBusFreeFunction old_free_function = NULL; 05350 05351 _dbus_return_if_fail (connection != NULL); 05352 05353 CONNECTION_LOCK (connection); 05354 _dbus_transport_set_windows_user_function (connection->transport, 05355 function, data, free_data_function, 05356 &old_data, &old_free_function); 05357 CONNECTION_UNLOCK (connection); 05358 05359 if (old_free_function != NULL) 05360 (* old_free_function) (old_data); 05361 } 05362 05389 void 05390 dbus_connection_set_allow_anonymous (DBusConnection *connection, 05391 dbus_bool_t value) 05392 { 05393 _dbus_return_if_fail (connection != NULL); 05394 05395 CONNECTION_LOCK (connection); 05396 _dbus_transport_set_allow_anonymous (connection->transport, value); 05397 CONNECTION_UNLOCK (connection); 05398 } 05399 05417 void 05418 dbus_connection_set_route_peer_messages (DBusConnection *connection, 05419 dbus_bool_t value) 05420 { 05421 _dbus_return_if_fail (connection != NULL); 05422 05423 CONNECTION_LOCK (connection); 05424 connection->route_peer_messages = TRUE; 05425 CONNECTION_UNLOCK (connection); 05426 } 05427 05449 dbus_bool_t 05450 dbus_connection_add_filter (DBusConnection *connection, 05451 DBusHandleMessageFunction function, 05452 void *user_data, 05453 DBusFreeFunction free_data_function) 05454 { 05455 DBusMessageFilter *filter; 05456 05457 _dbus_return_val_if_fail (connection != NULL, FALSE); 05458 _dbus_return_val_if_fail (function != NULL, FALSE); 05459 05460 filter = dbus_new0 (DBusMessageFilter, 1); 05461 if (filter == NULL) 05462 return FALSE; 05463 05464 filter->refcount.value = 1; 05465 05466 CONNECTION_LOCK (connection); 05467 05468 if (!_dbus_list_append (&connection->filter_list, 05469 filter)) 05470 { 05471 _dbus_message_filter_unref (filter); 05472 CONNECTION_UNLOCK (connection); 05473 return FALSE; 05474 } 05475 05476 /* Fill in filter after all memory allocated, 05477 * so we don't run the free_user_data_function 05478 * if the add_filter() fails 05479 */ 05480 05481 filter->function = function; 05482 filter->user_data = user_data; 05483 filter->free_user_data_function = free_data_function; 05484 05485 CONNECTION_UNLOCK (connection); 05486 return TRUE; 05487 } 05488 05501 void 05502 dbus_connection_remove_filter (DBusConnection *connection, 05503 DBusHandleMessageFunction function, 05504 void *user_data) 05505 { 05506 DBusList *link; 05507 DBusMessageFilter *filter; 05508 05509 _dbus_return_if_fail (connection != NULL); 05510 _dbus_return_if_fail (function != NULL); 05511 05512 CONNECTION_LOCK (connection); 05513 05514 filter = NULL; 05515 05516 link = _dbus_list_get_last_link (&connection->filter_list); 05517 while (link != NULL) 05518 { 05519 filter = link->data; 05520 05521 if (filter->function == function && 05522 filter->user_data == user_data) 05523 { 05524 _dbus_list_remove_link (&connection->filter_list, link); 05525 filter->function = NULL; 05526 05527 break; 05528 } 05529 05530 link = _dbus_list_get_prev_link (&connection->filter_list, link); 05531 filter = NULL; 05532 } 05533 05534 CONNECTION_UNLOCK (connection); 05535 05536 #ifndef DBUS_DISABLE_CHECKS 05537 if (filter == NULL) 05538 { 05539 _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n", 05540 function, user_data); 05541 return; 05542 } 05543 #endif 05544 05545 /* Call application code */ 05546 if (filter->free_user_data_function) 05547 (* filter->free_user_data_function) (filter->user_data); 05548 05549 filter->free_user_data_function = NULL; 05550 filter->user_data = NULL; 05551 05552 _dbus_message_filter_unref (filter); 05553 } 05554 05567 dbus_bool_t 05568 dbus_connection_try_register_object_path (DBusConnection *connection, 05569 const char *path, 05570 const DBusObjectPathVTable *vtable, 05571 void *user_data, 05572 DBusError *error) 05573 { 05574 char **decomposed_path; 05575 dbus_bool_t retval; 05576 05577 _dbus_return_val_if_fail (connection != NULL, FALSE); 05578 _dbus_return_val_if_fail (path != NULL, FALSE); 05579 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05580 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05581 05582 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05583 return FALSE; 05584 05585 CONNECTION_LOCK (connection); 05586 05587 retval = _dbus_object_tree_register (connection->objects, 05588 FALSE, 05589 (const char **) decomposed_path, vtable, 05590 user_data, error); 05591 05592 CONNECTION_UNLOCK (connection); 05593 05594 dbus_free_string_array (decomposed_path); 05595 05596 return retval; 05597 } 05598 05613 dbus_bool_t 05614 dbus_connection_register_object_path (DBusConnection *connection, 05615 const char *path, 05616 const DBusObjectPathVTable *vtable, 05617 void *user_data) 05618 { 05619 char **decomposed_path; 05620 dbus_bool_t retval; 05621 DBusError error = DBUS_ERROR_INIT; 05622 05623 _dbus_return_val_if_fail (connection != NULL, FALSE); 05624 _dbus_return_val_if_fail (path != NULL, FALSE); 05625 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05626 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05627 05628 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05629 return FALSE; 05630 05631 CONNECTION_LOCK (connection); 05632 05633 retval = _dbus_object_tree_register (connection->objects, 05634 FALSE, 05635 (const char **) decomposed_path, vtable, 05636 user_data, &error); 05637 05638 CONNECTION_UNLOCK (connection); 05639 05640 dbus_free_string_array (decomposed_path); 05641 05642 if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE)) 05643 { 05644 _dbus_warn ("%s\n", error.message); 05645 dbus_error_free (&error); 05646 return FALSE; 05647 } 05648 05649 return retval; 05650 } 05651 05666 dbus_bool_t 05667 dbus_connection_try_register_fallback (DBusConnection *connection, 05668 const char *path, 05669 const DBusObjectPathVTable *vtable, 05670 void *user_data, 05671 DBusError *error) 05672 { 05673 char **decomposed_path; 05674 dbus_bool_t retval; 05675 05676 _dbus_return_val_if_fail (connection != NULL, FALSE); 05677 _dbus_return_val_if_fail (path != NULL, FALSE); 05678 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05679 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05680 05681 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05682 return FALSE; 05683 05684 CONNECTION_LOCK (connection); 05685 05686 retval = _dbus_object_tree_register (connection->objects, 05687 TRUE, 05688 (const char **) decomposed_path, vtable, 05689 user_data, error); 05690 05691 CONNECTION_UNLOCK (connection); 05692 05693 dbus_free_string_array (decomposed_path); 05694 05695 return retval; 05696 } 05697 05714 dbus_bool_t 05715 dbus_connection_register_fallback (DBusConnection *connection, 05716 const char *path, 05717 const DBusObjectPathVTable *vtable, 05718 void *user_data) 05719 { 05720 char **decomposed_path; 05721 dbus_bool_t retval; 05722 DBusError error = DBUS_ERROR_INIT; 05723 05724 _dbus_return_val_if_fail (connection != NULL, FALSE); 05725 _dbus_return_val_if_fail (path != NULL, FALSE); 05726 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05727 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05728 05729 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05730 return FALSE; 05731 05732 CONNECTION_LOCK (connection); 05733 05734 retval = _dbus_object_tree_register (connection->objects, 05735 TRUE, 05736 (const char **) decomposed_path, vtable, 05737 user_data, &error); 05738 05739 CONNECTION_UNLOCK (connection); 05740 05741 dbus_free_string_array (decomposed_path); 05742 05743 if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE)) 05744 { 05745 _dbus_warn ("%s\n", error.message); 05746 dbus_error_free (&error); 05747 return FALSE; 05748 } 05749 05750 return retval; 05751 } 05752 05762 dbus_bool_t 05763 dbus_connection_unregister_object_path (DBusConnection *connection, 05764 const char *path) 05765 { 05766 char **decomposed_path; 05767 05768 _dbus_return_val_if_fail (connection != NULL, FALSE); 05769 _dbus_return_val_if_fail (path != NULL, FALSE); 05770 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05771 05772 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05773 return FALSE; 05774 05775 CONNECTION_LOCK (connection); 05776 05777 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path); 05778 05779 dbus_free_string_array (decomposed_path); 05780 05781 return TRUE; 05782 } 05783 05794 dbus_bool_t 05795 dbus_connection_get_object_path_data (DBusConnection *connection, 05796 const char *path, 05797 void **data_p) 05798 { 05799 char **decomposed_path; 05800 05801 _dbus_return_val_if_fail (connection != NULL, FALSE); 05802 _dbus_return_val_if_fail (path != NULL, FALSE); 05803 _dbus_return_val_if_fail (data_p != NULL, FALSE); 05804 05805 *data_p = NULL; 05806 05807 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05808 return FALSE; 05809 05810 CONNECTION_LOCK (connection); 05811 05812 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path); 05813 05814 CONNECTION_UNLOCK (connection); 05815 05816 dbus_free_string_array (decomposed_path); 05817 05818 return TRUE; 05819 } 05820 05831 dbus_bool_t 05832 dbus_connection_list_registered (DBusConnection *connection, 05833 const char *parent_path, 05834 char ***child_entries) 05835 { 05836 char **decomposed_path; 05837 dbus_bool_t retval; 05838 _dbus_return_val_if_fail (connection != NULL, FALSE); 05839 _dbus_return_val_if_fail (parent_path != NULL, FALSE); 05840 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE); 05841 _dbus_return_val_if_fail (child_entries != NULL, FALSE); 05842 05843 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL)) 05844 return FALSE; 05845 05846 CONNECTION_LOCK (connection); 05847 05848 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects, 05849 (const char **) decomposed_path, 05850 child_entries); 05851 dbus_free_string_array (decomposed_path); 05852 05853 return retval; 05854 } 05855 05856 static DBusDataSlotAllocator slot_allocator; 05857 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots); 05858 05873 dbus_bool_t 05874 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p) 05875 { 05876 return _dbus_data_slot_allocator_alloc (&slot_allocator, 05877 &_DBUS_LOCK_NAME (connection_slots), 05878 slot_p); 05879 } 05880 05892 void 05893 dbus_connection_free_data_slot (dbus_int32_t *slot_p) 05894 { 05895 _dbus_return_if_fail (*slot_p >= 0); 05896 05897 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 05898 } 05899 05922 dbus_bool_t 05923 dbus_connection_set_data (DBusConnection *connection, 05924 dbus_int32_t slot, 05925 void *data, 05926 DBusFreeFunction free_data_func) 05927 { 05928 DBusFreeFunction old_free_func; 05929 void *old_data; 05930 dbus_bool_t retval; 05931 05932 _dbus_return_val_if_fail (connection != NULL, FALSE); 05933 _dbus_return_val_if_fail (slot >= 0, FALSE); 05934 05935 SLOTS_LOCK (connection); 05936 05937 retval = _dbus_data_slot_list_set (&slot_allocator, 05938 &connection->slot_list, 05939 slot, data, free_data_func, 05940 &old_free_func, &old_data); 05941 05942 SLOTS_UNLOCK (connection); 05943 05944 if (retval) 05945 { 05946 /* Do the actual free outside the connection lock */ 05947 if (old_free_func) 05948 (* old_free_func) (old_data); 05949 } 05950 05951 return retval; 05952 } 05953 05971 void* 05972 dbus_connection_get_data (DBusConnection *connection, 05973 dbus_int32_t slot) 05974 { 05975 void *res; 05976 05977 _dbus_return_val_if_fail (connection != NULL, NULL); 05978 05979 SLOTS_LOCK (connection); 05980 05981 res = _dbus_data_slot_list_get (&slot_allocator, 05982 &connection->slot_list, 05983 slot); 05984 05985 SLOTS_UNLOCK (connection); 05986 05987 return res; 05988 } 05989 05996 void 05997 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe) 05998 { 05999 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE; 06000 } 06001 06010 void 06011 dbus_connection_set_max_message_size (DBusConnection *connection, 06012 long size) 06013 { 06014 _dbus_return_if_fail (connection != NULL); 06015 06016 CONNECTION_LOCK (connection); 06017 _dbus_transport_set_max_message_size (connection->transport, 06018 size); 06019 CONNECTION_UNLOCK (connection); 06020 } 06021 06028 long 06029 dbus_connection_get_max_message_size (DBusConnection *connection) 06030 { 06031 long res; 06032 06033 _dbus_return_val_if_fail (connection != NULL, 0); 06034 06035 CONNECTION_LOCK (connection); 06036 res = _dbus_transport_get_max_message_size (connection->transport); 06037 CONNECTION_UNLOCK (connection); 06038 return res; 06039 } 06040 06049 void 06050 dbus_connection_set_max_message_unix_fds (DBusConnection *connection, 06051 long n) 06052 { 06053 _dbus_return_if_fail (connection != NULL); 06054 06055 CONNECTION_LOCK (connection); 06056 _dbus_transport_set_max_message_unix_fds (connection->transport, 06057 n); 06058 CONNECTION_UNLOCK (connection); 06059 } 06060 06067 long 06068 dbus_connection_get_max_message_unix_fds (DBusConnection *connection) 06069 { 06070 long res; 06071 06072 _dbus_return_val_if_fail (connection != NULL, 0); 06073 06074 CONNECTION_LOCK (connection); 06075 res = _dbus_transport_get_max_message_unix_fds (connection->transport); 06076 CONNECTION_UNLOCK (connection); 06077 return res; 06078 } 06079 06105 void 06106 dbus_connection_set_max_received_size (DBusConnection *connection, 06107 long size) 06108 { 06109 _dbus_return_if_fail (connection != NULL); 06110 06111 CONNECTION_LOCK (connection); 06112 _dbus_transport_set_max_received_size (connection->transport, 06113 size); 06114 CONNECTION_UNLOCK (connection); 06115 } 06116 06123 long 06124 dbus_connection_get_max_received_size (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_size (connection->transport); 06132 CONNECTION_UNLOCK (connection); 06133 return res; 06134 } 06135 06147 void 06148 dbus_connection_set_max_received_unix_fds (DBusConnection *connection, 06149 long n) 06150 { 06151 _dbus_return_if_fail (connection != NULL); 06152 06153 CONNECTION_LOCK (connection); 06154 _dbus_transport_set_max_received_unix_fds (connection->transport, 06155 n); 06156 CONNECTION_UNLOCK (connection); 06157 } 06158 06165 long 06166 dbus_connection_get_max_received_unix_fds (DBusConnection *connection) 06167 { 06168 long res; 06169 06170 _dbus_return_val_if_fail (connection != NULL, 0); 06171 06172 CONNECTION_LOCK (connection); 06173 res = _dbus_transport_get_max_received_unix_fds (connection->transport); 06174 CONNECTION_UNLOCK (connection); 06175 return res; 06176 } 06177 06188 long 06189 dbus_connection_get_outgoing_size (DBusConnection *connection) 06190 { 06191 long res; 06192 06193 _dbus_return_val_if_fail (connection != NULL, 0); 06194 06195 CONNECTION_LOCK (connection); 06196 res = _dbus_counter_get_size_value (connection->outgoing_counter); 06197 CONNECTION_UNLOCK (connection); 06198 return res; 06199 } 06200 06208 long 06209 dbus_connection_get_outgoing_unix_fds (DBusConnection *connection) 06210 { 06211 long res; 06212 06213 _dbus_return_val_if_fail (connection != NULL, 0); 06214 06215 CONNECTION_LOCK (connection); 06216 res = _dbus_counter_get_unix_fd_value (connection->outgoing_counter); 06217 CONNECTION_UNLOCK (connection); 06218 return res; 06219 } 06220