D-Bus 1.2.24
|
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-threads.h" 00037 #include "dbus-protocol.h" 00038 #include "dbus-dataslot.h" 00039 #include "dbus-string.h" 00040 #include "dbus-pending-call.h" 00041 #include "dbus-object-tree.h" 00042 #include "dbus-threads-internal.h" 00043 #include "dbus-bus.h" 00044 00045 #ifdef DBUS_DISABLE_CHECKS 00046 #define TOOK_LOCK_CHECK(connection) 00047 #define RELEASING_LOCK_CHECK(connection) 00048 #define HAVE_LOCK_CHECK(connection) 00049 #else 00050 #define TOOK_LOCK_CHECK(connection) do { \ 00051 _dbus_assert (!(connection)->have_connection_lock); \ 00052 (connection)->have_connection_lock = TRUE; \ 00053 } while (0) 00054 #define RELEASING_LOCK_CHECK(connection) do { \ 00055 _dbus_assert ((connection)->have_connection_lock); \ 00056 (connection)->have_connection_lock = FALSE; \ 00057 } while (0) 00058 #define HAVE_LOCK_CHECK(connection) _dbus_assert ((connection)->have_connection_lock) 00059 /* A "DO_NOT_HAVE_LOCK_CHECK" is impossible since we need the lock to check the flag */ 00060 #endif 00061 00062 #define TRACE_LOCKS 1 00063 00064 #define CONNECTION_LOCK(connection) do { \ 00065 if (TRACE_LOCKS) { _dbus_verbose (" LOCK: %s\n", _DBUS_FUNCTION_NAME); } \ 00066 _dbus_mutex_lock ((connection)->mutex); \ 00067 TOOK_LOCK_CHECK (connection); \ 00068 } while (0) 00069 00070 #define CONNECTION_UNLOCK(connection) do { \ 00071 if (TRACE_LOCKS) { _dbus_verbose (" UNLOCK: %s\n", _DBUS_FUNCTION_NAME); } \ 00072 RELEASING_LOCK_CHECK (connection); \ 00073 _dbus_mutex_unlock ((connection)->mutex); \ 00074 } while (0) 00075 00076 #define DISPATCH_STATUS_NAME(s) \ 00077 ((s) == DBUS_DISPATCH_COMPLETE ? "complete" : \ 00078 (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \ 00079 (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" : \ 00080 "???") 00081 00202 typedef struct DBusMessageFilter DBusMessageFilter; 00203 00207 struct DBusMessageFilter 00208 { 00209 DBusAtomic refcount; 00210 DBusHandleMessageFunction function; 00211 void *user_data; 00212 DBusFreeFunction free_user_data_function; 00213 }; 00214 00215 00219 struct DBusPreallocatedSend 00220 { 00221 DBusConnection *connection; 00222 DBusList *queue_link; 00223 DBusList *counter_link; 00224 }; 00225 00226 static dbus_bool_t _dbus_modify_sigpipe = TRUE; 00227 00231 struct DBusConnection 00232 { 00233 DBusAtomic refcount; 00235 DBusMutex *mutex; 00237 DBusMutex *dispatch_mutex; 00238 DBusCondVar *dispatch_cond; 00239 DBusMutex *io_path_mutex; 00240 DBusCondVar *io_path_cond; 00242 DBusList *outgoing_messages; 00243 DBusList *incoming_messages; 00245 DBusMessage *message_borrowed; 00249 int n_outgoing; 00250 int n_incoming; 00252 DBusCounter *outgoing_counter; 00254 DBusTransport *transport; 00255 DBusWatchList *watches; 00256 DBusTimeoutList *timeouts; 00258 DBusList *filter_list; 00260 DBusDataSlotList slot_list; 00262 DBusHashTable *pending_replies; 00264 dbus_uint32_t client_serial; 00265 DBusList *disconnect_message_link; 00267 DBusWakeupMainFunction wakeup_main_function; 00268 void *wakeup_main_data; 00269 DBusFreeFunction free_wakeup_main_data; 00271 DBusDispatchStatusFunction dispatch_status_function; 00272 void *dispatch_status_data; 00273 DBusFreeFunction free_dispatch_status_data; 00275 DBusDispatchStatus last_dispatch_status; 00277 DBusList *link_cache; 00280 DBusObjectTree *objects; 00282 char *server_guid; 00284 /* These two MUST be bools and not bitfields, because they are protected by a separate lock 00285 * from connection->mutex and all bitfields in a word have to be read/written together. 00286 * So you can't have a different lock for different bitfields in the same word. 00287 */ 00288 dbus_bool_t dispatch_acquired; 00289 dbus_bool_t io_path_acquired; 00291 unsigned int shareable : 1; 00293 unsigned int exit_on_disconnect : 1; 00295 unsigned int route_peer_messages : 1; 00297 unsigned int disconnected_message_arrived : 1; 00301 unsigned int disconnected_message_processed : 1; 00305 #ifndef DBUS_DISABLE_CHECKS 00306 unsigned int have_connection_lock : 1; 00307 #endif 00308 00309 #ifndef DBUS_DISABLE_CHECKS 00310 int generation; 00311 #endif 00312 }; 00313 00314 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection); 00315 static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection, 00316 DBusDispatchStatus new_status); 00317 static void _dbus_connection_last_unref (DBusConnection *connection); 00318 static void _dbus_connection_acquire_dispatch (DBusConnection *connection); 00319 static void _dbus_connection_release_dispatch (DBusConnection *connection); 00320 static DBusDispatchStatus _dbus_connection_flush_unlocked (DBusConnection *connection); 00321 static void _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection); 00322 static dbus_bool_t _dbus_connection_get_is_connected_unlocked (DBusConnection *connection); 00323 00324 static DBusMessageFilter * 00325 _dbus_message_filter_ref (DBusMessageFilter *filter) 00326 { 00327 _dbus_assert (filter->refcount.value > 0); 00328 _dbus_atomic_inc (&filter->refcount); 00329 00330 return filter; 00331 } 00332 00333 static void 00334 _dbus_message_filter_unref (DBusMessageFilter *filter) 00335 { 00336 _dbus_assert (filter->refcount.value > 0); 00337 00338 if (_dbus_atomic_dec (&filter->refcount) == 1) 00339 { 00340 if (filter->free_user_data_function) 00341 (* filter->free_user_data_function) (filter->user_data); 00342 00343 dbus_free (filter); 00344 } 00345 } 00346 00352 void 00353 _dbus_connection_lock (DBusConnection *connection) 00354 { 00355 CONNECTION_LOCK (connection); 00356 } 00357 00363 void 00364 _dbus_connection_unlock (DBusConnection *connection) 00365 { 00366 CONNECTION_UNLOCK (connection); 00367 } 00368 00376 static void 00377 _dbus_connection_wakeup_mainloop (DBusConnection *connection) 00378 { 00379 if (connection->wakeup_main_function) 00380 (*connection->wakeup_main_function) (connection->wakeup_main_data); 00381 } 00382 00383 #ifdef DBUS_BUILD_TESTS 00384 /* For now this function isn't used */ 00394 dbus_bool_t 00395 _dbus_connection_queue_received_message (DBusConnection *connection, 00396 DBusMessage *message) 00397 { 00398 DBusList *link; 00399 00400 link = _dbus_list_alloc_link (message); 00401 if (link == NULL) 00402 return FALSE; 00403 00404 dbus_message_ref (message); 00405 _dbus_connection_queue_received_message_link (connection, link); 00406 00407 return TRUE; 00408 } 00409 00422 void 00423 _dbus_connection_test_get_locks (DBusConnection *connection, 00424 DBusMutex **mutex_loc, 00425 DBusMutex **dispatch_mutex_loc, 00426 DBusMutex **io_path_mutex_loc, 00427 DBusCondVar **dispatch_cond_loc, 00428 DBusCondVar **io_path_cond_loc) 00429 { 00430 *mutex_loc = connection->mutex; 00431 *dispatch_mutex_loc = connection->dispatch_mutex; 00432 *io_path_mutex_loc = connection->io_path_mutex; 00433 *dispatch_cond_loc = connection->dispatch_cond; 00434 *io_path_cond_loc = connection->io_path_cond; 00435 } 00436 #endif 00437 00446 void 00447 _dbus_connection_queue_received_message_link (DBusConnection *connection, 00448 DBusList *link) 00449 { 00450 DBusPendingCall *pending; 00451 dbus_uint32_t reply_serial; 00452 DBusMessage *message; 00453 00454 _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport)); 00455 00456 _dbus_list_append_link (&connection->incoming_messages, 00457 link); 00458 message = link->data; 00459 00460 /* If this is a reply we're waiting on, remove timeout for it */ 00461 reply_serial = dbus_message_get_reply_serial (message); 00462 if (reply_serial != 0) 00463 { 00464 pending = _dbus_hash_table_lookup_int (connection->pending_replies, 00465 reply_serial); 00466 if (pending != NULL) 00467 { 00468 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 00469 _dbus_connection_remove_timeout_unlocked (connection, 00470 _dbus_pending_call_get_timeout_unlocked (pending)); 00471 00472 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 00473 } 00474 } 00475 00476 00477 00478 connection->n_incoming += 1; 00479 00480 _dbus_connection_wakeup_mainloop (connection); 00481 00482 _dbus_verbose ("Message %p (%d %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n", 00483 message, 00484 dbus_message_get_type (message), 00485 dbus_message_get_path (message) ? 00486 dbus_message_get_path (message) : 00487 "no path", 00488 dbus_message_get_interface (message) ? 00489 dbus_message_get_interface (message) : 00490 "no interface", 00491 dbus_message_get_member (message) ? 00492 dbus_message_get_member (message) : 00493 "no member", 00494 dbus_message_get_signature (message), 00495 dbus_message_get_reply_serial (message), 00496 connection, 00497 connection->n_incoming);} 00498 00507 void 00508 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection, 00509 DBusList *link) 00510 { 00511 HAVE_LOCK_CHECK (connection); 00512 00513 _dbus_list_append_link (&connection->incoming_messages, link); 00514 00515 connection->n_incoming += 1; 00516 00517 _dbus_connection_wakeup_mainloop (connection); 00518 00519 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n", 00520 link->data, connection, connection->n_incoming); 00521 } 00522 00523 00531 dbus_bool_t 00532 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection) 00533 { 00534 HAVE_LOCK_CHECK (connection); 00535 return connection->outgoing_messages != NULL; 00536 } 00537 00547 dbus_bool_t 00548 dbus_connection_has_messages_to_send (DBusConnection *connection) 00549 { 00550 dbus_bool_t v; 00551 00552 _dbus_return_val_if_fail (connection != NULL, FALSE); 00553 00554 CONNECTION_LOCK (connection); 00555 v = _dbus_connection_has_messages_to_send_unlocked (connection); 00556 CONNECTION_UNLOCK (connection); 00557 00558 return v; 00559 } 00560 00568 DBusMessage* 00569 _dbus_connection_get_message_to_send (DBusConnection *connection) 00570 { 00571 HAVE_LOCK_CHECK (connection); 00572 00573 return _dbus_list_get_last (&connection->outgoing_messages); 00574 } 00575 00584 void 00585 _dbus_connection_message_sent (DBusConnection *connection, 00586 DBusMessage *message) 00587 { 00588 DBusList *link; 00589 00590 HAVE_LOCK_CHECK (connection); 00591 00592 /* This can be called before we even complete authentication, since 00593 * it's called on disconnect to clean up the outgoing queue. 00594 * It's also called as we successfully send each message. 00595 */ 00596 00597 link = _dbus_list_get_last_link (&connection->outgoing_messages); 00598 _dbus_assert (link != NULL); 00599 _dbus_assert (link->data == message); 00600 00601 /* Save this link in the link cache */ 00602 _dbus_list_unlink (&connection->outgoing_messages, 00603 link); 00604 _dbus_list_prepend_link (&connection->link_cache, link); 00605 00606 connection->n_outgoing -= 1; 00607 00608 _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from outgoing queue %p, %d left to send\n", 00609 message, 00610 dbus_message_get_type (message), 00611 dbus_message_get_path (message) ? 00612 dbus_message_get_path (message) : 00613 "no path", 00614 dbus_message_get_interface (message) ? 00615 dbus_message_get_interface (message) : 00616 "no interface", 00617 dbus_message_get_member (message) ? 00618 dbus_message_get_member (message) : 00619 "no member", 00620 dbus_message_get_signature (message), 00621 connection, connection->n_outgoing); 00622 00623 /* Save this link in the link cache also */ 00624 _dbus_message_remove_size_counter (message, connection->outgoing_counter, 00625 &link); 00626 _dbus_list_prepend_link (&connection->link_cache, link); 00627 00628 dbus_message_unref (message); 00629 } 00630 00632 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list, 00633 DBusWatch *watch); 00635 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list, 00636 DBusWatch *watch); 00638 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list, 00639 DBusWatch *watch, 00640 dbus_bool_t enabled); 00641 00642 static dbus_bool_t 00643 protected_change_watch (DBusConnection *connection, 00644 DBusWatch *watch, 00645 DBusWatchAddFunction add_function, 00646 DBusWatchRemoveFunction remove_function, 00647 DBusWatchToggleFunction toggle_function, 00648 dbus_bool_t enabled) 00649 { 00650 DBusWatchList *watches; 00651 dbus_bool_t retval; 00652 00653 HAVE_LOCK_CHECK (connection); 00654 00655 /* This isn't really safe or reasonable; a better pattern is the "do everything, then 00656 * drop lock and call out" one; but it has to be propagated up through all callers 00657 */ 00658 00659 watches = connection->watches; 00660 if (watches) 00661 { 00662 connection->watches = NULL; 00663 _dbus_connection_ref_unlocked (connection); 00664 CONNECTION_UNLOCK (connection); 00665 00666 if (add_function) 00667 retval = (* add_function) (watches, watch); 00668 else if (remove_function) 00669 { 00670 retval = TRUE; 00671 (* remove_function) (watches, watch); 00672 } 00673 else 00674 { 00675 retval = TRUE; 00676 (* toggle_function) (watches, watch, enabled); 00677 } 00678 00679 CONNECTION_LOCK (connection); 00680 connection->watches = watches; 00681 _dbus_connection_unref_unlocked (connection); 00682 00683 return retval; 00684 } 00685 else 00686 return FALSE; 00687 } 00688 00689 00701 dbus_bool_t 00702 _dbus_connection_add_watch_unlocked (DBusConnection *connection, 00703 DBusWatch *watch) 00704 { 00705 return protected_change_watch (connection, watch, 00706 _dbus_watch_list_add_watch, 00707 NULL, NULL, FALSE); 00708 } 00709 00719 void 00720 _dbus_connection_remove_watch_unlocked (DBusConnection *connection, 00721 DBusWatch *watch) 00722 { 00723 protected_change_watch (connection, watch, 00724 NULL, 00725 _dbus_watch_list_remove_watch, 00726 NULL, FALSE); 00727 } 00728 00739 void 00740 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection, 00741 DBusWatch *watch, 00742 dbus_bool_t enabled) 00743 { 00744 _dbus_assert (watch != NULL); 00745 00746 protected_change_watch (connection, watch, 00747 NULL, NULL, 00748 _dbus_watch_list_toggle_watch, 00749 enabled); 00750 } 00751 00753 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list, 00754 DBusTimeout *timeout); 00756 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list, 00757 DBusTimeout *timeout); 00759 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list, 00760 DBusTimeout *timeout, 00761 dbus_bool_t enabled); 00762 00763 static dbus_bool_t 00764 protected_change_timeout (DBusConnection *connection, 00765 DBusTimeout *timeout, 00766 DBusTimeoutAddFunction add_function, 00767 DBusTimeoutRemoveFunction remove_function, 00768 DBusTimeoutToggleFunction toggle_function, 00769 dbus_bool_t enabled) 00770 { 00771 DBusTimeoutList *timeouts; 00772 dbus_bool_t retval; 00773 00774 HAVE_LOCK_CHECK (connection); 00775 00776 /* This isn't really safe or reasonable; a better pattern is the "do everything, then 00777 * drop lock and call out" one; but it has to be propagated up through all callers 00778 */ 00779 00780 timeouts = connection->timeouts; 00781 if (timeouts) 00782 { 00783 connection->timeouts = NULL; 00784 _dbus_connection_ref_unlocked (connection); 00785 CONNECTION_UNLOCK (connection); 00786 00787 if (add_function) 00788 retval = (* add_function) (timeouts, timeout); 00789 else if (remove_function) 00790 { 00791 retval = TRUE; 00792 (* remove_function) (timeouts, timeout); 00793 } 00794 else 00795 { 00796 retval = TRUE; 00797 (* toggle_function) (timeouts, timeout, enabled); 00798 } 00799 00800 CONNECTION_LOCK (connection); 00801 connection->timeouts = timeouts; 00802 _dbus_connection_unref_unlocked (connection); 00803 00804 return retval; 00805 } 00806 else 00807 return FALSE; 00808 } 00809 00822 dbus_bool_t 00823 _dbus_connection_add_timeout_unlocked (DBusConnection *connection, 00824 DBusTimeout *timeout) 00825 { 00826 return protected_change_timeout (connection, timeout, 00827 _dbus_timeout_list_add_timeout, 00828 NULL, NULL, FALSE); 00829 } 00830 00840 void 00841 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection, 00842 DBusTimeout *timeout) 00843 { 00844 protected_change_timeout (connection, timeout, 00845 NULL, 00846 _dbus_timeout_list_remove_timeout, 00847 NULL, FALSE); 00848 } 00849 00860 void 00861 _dbus_connection_toggle_timeout_unlocked (DBusConnection *connection, 00862 DBusTimeout *timeout, 00863 dbus_bool_t enabled) 00864 { 00865 protected_change_timeout (connection, timeout, 00866 NULL, NULL, 00867 _dbus_timeout_list_toggle_timeout, 00868 enabled); 00869 } 00870 00871 static dbus_bool_t 00872 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection, 00873 DBusPendingCall *pending) 00874 { 00875 dbus_uint32_t reply_serial; 00876 DBusTimeout *timeout; 00877 00878 HAVE_LOCK_CHECK (connection); 00879 00880 reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending); 00881 00882 _dbus_assert (reply_serial != 0); 00883 00884 timeout = _dbus_pending_call_get_timeout_unlocked (pending); 00885 00886 if (timeout) 00887 { 00888 if (!_dbus_connection_add_timeout_unlocked (connection, timeout)) 00889 return FALSE; 00890 00891 if (!_dbus_hash_table_insert_int (connection->pending_replies, 00892 reply_serial, 00893 pending)) 00894 { 00895 _dbus_connection_remove_timeout_unlocked (connection, timeout); 00896 00897 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 00898 HAVE_LOCK_CHECK (connection); 00899 return FALSE; 00900 } 00901 00902 _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE); 00903 } 00904 else 00905 { 00906 if (!_dbus_hash_table_insert_int (connection->pending_replies, 00907 reply_serial, 00908 pending)) 00909 { 00910 HAVE_LOCK_CHECK (connection); 00911 return FALSE; 00912 } 00913 } 00914 00915 _dbus_pending_call_ref_unlocked (pending); 00916 00917 HAVE_LOCK_CHECK (connection); 00918 00919 return TRUE; 00920 } 00921 00922 static void 00923 free_pending_call_on_hash_removal (void *data) 00924 { 00925 DBusPendingCall *pending; 00926 DBusConnection *connection; 00927 00928 if (data == NULL) 00929 return; 00930 00931 pending = data; 00932 00933 connection = _dbus_pending_call_get_connection_unlocked (pending); 00934 00935 HAVE_LOCK_CHECK (connection); 00936 00937 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 00938 { 00939 _dbus_connection_remove_timeout_unlocked (connection, 00940 _dbus_pending_call_get_timeout_unlocked (pending)); 00941 00942 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 00943 } 00944 00945 /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock 00946 * here, but the pending call finalizer could in principle call out to 00947 * application code so we pretty much have to... some larger code reorg 00948 * might be needed. 00949 */ 00950 _dbus_connection_ref_unlocked (connection); 00951 _dbus_pending_call_unref_and_unlock (pending); 00952 CONNECTION_LOCK (connection); 00953 _dbus_connection_unref_unlocked (connection); 00954 } 00955 00956 static void 00957 _dbus_connection_detach_pending_call_unlocked (DBusConnection *connection, 00958 DBusPendingCall *pending) 00959 { 00960 /* This ends up unlocking to call the pending call finalizer, which is unexpected to 00961 * say the least. 00962 */ 00963 _dbus_hash_table_remove_int (connection->pending_replies, 00964 _dbus_pending_call_get_reply_serial_unlocked (pending)); 00965 } 00966 00967 static void 00968 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection, 00969 DBusPendingCall *pending) 00970 { 00971 /* The idea here is to avoid finalizing the pending call 00972 * with the lock held, since there's a destroy notifier 00973 * in pending call that goes out to application code. 00974 * 00975 * There's an extra unlock inside the hash table 00976 * "free pending call" function FIXME... 00977 */ 00978 _dbus_pending_call_ref_unlocked (pending); 00979 _dbus_hash_table_remove_int (connection->pending_replies, 00980 _dbus_pending_call_get_reply_serial_unlocked (pending)); 00981 00982 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 00983 _dbus_connection_remove_timeout_unlocked (connection, 00984 _dbus_pending_call_get_timeout_unlocked (pending)); 00985 00986 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 00987 00988 _dbus_pending_call_unref_and_unlock (pending); 00989 } 00990 00999 void 01000 _dbus_connection_remove_pending_call (DBusConnection *connection, 01001 DBusPendingCall *pending) 01002 { 01003 CONNECTION_LOCK (connection); 01004 _dbus_connection_detach_pending_call_and_unlock (connection, pending); 01005 } 01006 01016 static dbus_bool_t 01017 _dbus_connection_acquire_io_path (DBusConnection *connection, 01018 int timeout_milliseconds) 01019 { 01020 dbus_bool_t we_acquired; 01021 01022 HAVE_LOCK_CHECK (connection); 01023 01024 /* We don't want the connection to vanish */ 01025 _dbus_connection_ref_unlocked (connection); 01026 01027 /* We will only touch io_path_acquired which is protected by our mutex */ 01028 CONNECTION_UNLOCK (connection); 01029 01030 _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME); 01031 _dbus_mutex_lock (connection->io_path_mutex); 01032 01033 _dbus_verbose ("%s start connection->io_path_acquired = %d timeout = %d\n", 01034 _DBUS_FUNCTION_NAME, connection->io_path_acquired, timeout_milliseconds); 01035 01036 we_acquired = FALSE; 01037 01038 if (connection->io_path_acquired) 01039 { 01040 if (timeout_milliseconds != -1) 01041 { 01042 _dbus_verbose ("%s waiting %d for IO path to be acquirable\n", 01043 _DBUS_FUNCTION_NAME, timeout_milliseconds); 01044 01045 if (!_dbus_condvar_wait_timeout (connection->io_path_cond, 01046 connection->io_path_mutex, 01047 timeout_milliseconds)) 01048 { 01049 /* We timed out before anyone signaled. */ 01050 /* (writing the loop to handle the !timedout case by 01051 * waiting longer if needed is a pain since dbus 01052 * wraps pthread_cond_timedwait to take a relative 01053 * time instead of absolute, something kind of stupid 01054 * on our part. for now it doesn't matter, we will just 01055 * end up back here eventually.) 01056 */ 01057 } 01058 } 01059 else 01060 { 01061 while (connection->io_path_acquired) 01062 { 01063 _dbus_verbose ("%s waiting for IO path to be acquirable\n", _DBUS_FUNCTION_NAME); 01064 _dbus_condvar_wait (connection->io_path_cond, 01065 connection->io_path_mutex); 01066 } 01067 } 01068 } 01069 01070 if (!connection->io_path_acquired) 01071 { 01072 we_acquired = TRUE; 01073 connection->io_path_acquired = TRUE; 01074 } 01075 01076 _dbus_verbose ("%s end connection->io_path_acquired = %d we_acquired = %d\n", 01077 _DBUS_FUNCTION_NAME, connection->io_path_acquired, we_acquired); 01078 01079 _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME); 01080 _dbus_mutex_unlock (connection->io_path_mutex); 01081 01082 CONNECTION_LOCK (connection); 01083 01084 HAVE_LOCK_CHECK (connection); 01085 01086 _dbus_connection_unref_unlocked (connection); 01087 01088 return we_acquired; 01089 } 01090 01098 static void 01099 _dbus_connection_release_io_path (DBusConnection *connection) 01100 { 01101 HAVE_LOCK_CHECK (connection); 01102 01103 _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME); 01104 _dbus_mutex_lock (connection->io_path_mutex); 01105 01106 _dbus_assert (connection->io_path_acquired); 01107 01108 _dbus_verbose ("%s start connection->io_path_acquired = %d\n", 01109 _DBUS_FUNCTION_NAME, connection->io_path_acquired); 01110 01111 connection->io_path_acquired = FALSE; 01112 _dbus_condvar_wake_one (connection->io_path_cond); 01113 01114 _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME); 01115 _dbus_mutex_unlock (connection->io_path_mutex); 01116 } 01117 01146 void 01147 _dbus_connection_do_iteration_unlocked (DBusConnection *connection, 01148 unsigned int flags, 01149 int timeout_milliseconds) 01150 { 01151 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME); 01152 01153 HAVE_LOCK_CHECK (connection); 01154 01155 if (connection->n_outgoing == 0) 01156 flags &= ~DBUS_ITERATION_DO_WRITING; 01157 01158 if (_dbus_connection_acquire_io_path (connection, 01159 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0)) 01160 { 01161 HAVE_LOCK_CHECK (connection); 01162 01163 _dbus_transport_do_iteration (connection->transport, 01164 flags, timeout_milliseconds); 01165 _dbus_connection_release_io_path (connection); 01166 } 01167 01168 HAVE_LOCK_CHECK (connection); 01169 01170 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME); 01171 } 01172 01182 DBusConnection* 01183 _dbus_connection_new_for_transport (DBusTransport *transport) 01184 { 01185 DBusConnection *connection; 01186 DBusWatchList *watch_list; 01187 DBusTimeoutList *timeout_list; 01188 DBusHashTable *pending_replies; 01189 DBusList *disconnect_link; 01190 DBusMessage *disconnect_message; 01191 DBusCounter *outgoing_counter; 01192 DBusObjectTree *objects; 01193 01194 watch_list = NULL; 01195 connection = NULL; 01196 pending_replies = NULL; 01197 timeout_list = NULL; 01198 disconnect_link = NULL; 01199 disconnect_message = NULL; 01200 outgoing_counter = NULL; 01201 objects = NULL; 01202 01203 watch_list = _dbus_watch_list_new (); 01204 if (watch_list == NULL) 01205 goto error; 01206 01207 timeout_list = _dbus_timeout_list_new (); 01208 if (timeout_list == NULL) 01209 goto error; 01210 01211 pending_replies = 01212 _dbus_hash_table_new (DBUS_HASH_INT, 01213 NULL, 01214 (DBusFreeFunction)free_pending_call_on_hash_removal); 01215 if (pending_replies == NULL) 01216 goto error; 01217 01218 connection = dbus_new0 (DBusConnection, 1); 01219 if (connection == NULL) 01220 goto error; 01221 01222 _dbus_mutex_new_at_location (&connection->mutex); 01223 if (connection->mutex == NULL) 01224 goto error; 01225 01226 _dbus_mutex_new_at_location (&connection->io_path_mutex); 01227 if (connection->io_path_mutex == NULL) 01228 goto error; 01229 01230 _dbus_mutex_new_at_location (&connection->dispatch_mutex); 01231 if (connection->dispatch_mutex == NULL) 01232 goto error; 01233 01234 _dbus_condvar_new_at_location (&connection->dispatch_cond); 01235 if (connection->dispatch_cond == NULL) 01236 goto error; 01237 01238 _dbus_condvar_new_at_location (&connection->io_path_cond); 01239 if (connection->io_path_cond == NULL) 01240 goto error; 01241 01242 disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL, 01243 DBUS_INTERFACE_LOCAL, 01244 "Disconnected"); 01245 01246 if (disconnect_message == NULL) 01247 goto error; 01248 01249 disconnect_link = _dbus_list_alloc_link (disconnect_message); 01250 if (disconnect_link == NULL) 01251 goto error; 01252 01253 outgoing_counter = _dbus_counter_new (); 01254 if (outgoing_counter == NULL) 01255 goto error; 01256 01257 objects = _dbus_object_tree_new (connection); 01258 if (objects == NULL) 01259 goto error; 01260 01261 if (_dbus_modify_sigpipe) 01262 _dbus_disable_sigpipe (); 01263 01264 connection->refcount.value = 1; 01265 connection->transport = transport; 01266 connection->watches = watch_list; 01267 connection->timeouts = timeout_list; 01268 connection->pending_replies = pending_replies; 01269 connection->outgoing_counter = outgoing_counter; 01270 connection->filter_list = NULL; 01271 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */ 01272 connection->objects = objects; 01273 connection->exit_on_disconnect = FALSE; 01274 connection->shareable = FALSE; 01275 connection->route_peer_messages = FALSE; 01276 connection->disconnected_message_arrived = FALSE; 01277 connection->disconnected_message_processed = FALSE; 01278 01279 #ifndef DBUS_DISABLE_CHECKS 01280 connection->generation = _dbus_current_generation; 01281 #endif 01282 01283 _dbus_data_slot_list_init (&connection->slot_list); 01284 01285 connection->client_serial = 1; 01286 01287 connection->disconnect_message_link = disconnect_link; 01288 01289 CONNECTION_LOCK (connection); 01290 01291 if (!_dbus_transport_set_connection (transport, connection)) 01292 { 01293 CONNECTION_UNLOCK (connection); 01294 01295 goto error; 01296 } 01297 01298 _dbus_transport_ref (transport); 01299 01300 CONNECTION_UNLOCK (connection); 01301 01302 return connection; 01303 01304 error: 01305 if (disconnect_message != NULL) 01306 dbus_message_unref (disconnect_message); 01307 01308 if (disconnect_link != NULL) 01309 _dbus_list_free_link (disconnect_link); 01310 01311 if (connection != NULL) 01312 { 01313 _dbus_condvar_free_at_location (&connection->io_path_cond); 01314 _dbus_condvar_free_at_location (&connection->dispatch_cond); 01315 _dbus_mutex_free_at_location (&connection->mutex); 01316 _dbus_mutex_free_at_location (&connection->io_path_mutex); 01317 _dbus_mutex_free_at_location (&connection->dispatch_mutex); 01318 dbus_free (connection); 01319 } 01320 if (pending_replies) 01321 _dbus_hash_table_unref (pending_replies); 01322 01323 if (watch_list) 01324 _dbus_watch_list_free (watch_list); 01325 01326 if (timeout_list) 01327 _dbus_timeout_list_free (timeout_list); 01328 01329 if (outgoing_counter) 01330 _dbus_counter_unref (outgoing_counter); 01331 01332 if (objects) 01333 _dbus_object_tree_unref (objects); 01334 01335 return NULL; 01336 } 01337 01345 DBusConnection * 01346 _dbus_connection_ref_unlocked (DBusConnection *connection) 01347 { 01348 _dbus_assert (connection != NULL); 01349 _dbus_assert (connection->generation == _dbus_current_generation); 01350 01351 HAVE_LOCK_CHECK (connection); 01352 01353 #ifdef DBUS_HAVE_ATOMIC_INT 01354 _dbus_atomic_inc (&connection->refcount); 01355 #else 01356 _dbus_assert (connection->refcount.value > 0); 01357 connection->refcount.value += 1; 01358 #endif 01359 01360 return connection; 01361 } 01362 01369 void 01370 _dbus_connection_unref_unlocked (DBusConnection *connection) 01371 { 01372 dbus_bool_t last_unref; 01373 01374 HAVE_LOCK_CHECK (connection); 01375 01376 _dbus_assert (connection != NULL); 01377 01378 /* The connection lock is better than the global 01379 * lock in the atomic increment fallback 01380 */ 01381 01382 #ifdef DBUS_HAVE_ATOMIC_INT 01383 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1); 01384 #else 01385 _dbus_assert (connection->refcount.value > 0); 01386 01387 connection->refcount.value -= 1; 01388 last_unref = (connection->refcount.value == 0); 01389 #if 0 01390 printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value); 01391 #endif 01392 #endif 01393 01394 if (last_unref) 01395 _dbus_connection_last_unref (connection); 01396 } 01397 01398 static dbus_uint32_t 01399 _dbus_connection_get_next_client_serial (DBusConnection *connection) 01400 { 01401 dbus_uint32_t serial; 01402 01403 serial = connection->client_serial++; 01404 01405 if (connection->client_serial == 0) 01406 connection->client_serial = 1; 01407 01408 return serial; 01409 } 01410 01424 dbus_bool_t 01425 _dbus_connection_handle_watch (DBusWatch *watch, 01426 unsigned int condition, 01427 void *data) 01428 { 01429 DBusConnection *connection; 01430 dbus_bool_t retval; 01431 DBusDispatchStatus status; 01432 01433 connection = data; 01434 01435 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME); 01436 01437 CONNECTION_LOCK (connection); 01438 01439 if (!_dbus_connection_acquire_io_path (connection, 1)) 01440 { 01441 /* another thread is handling the message */ 01442 CONNECTION_UNLOCK (connection); 01443 return TRUE; 01444 } 01445 01446 HAVE_LOCK_CHECK (connection); 01447 retval = _dbus_transport_handle_watch (connection->transport, 01448 watch, condition); 01449 01450 _dbus_connection_release_io_path (connection); 01451 01452 HAVE_LOCK_CHECK (connection); 01453 01454 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME); 01455 01456 status = _dbus_connection_get_dispatch_status_unlocked (connection); 01457 01458 /* this calls out to user code */ 01459 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 01460 01461 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME); 01462 01463 return retval; 01464 } 01465 01466 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections); 01467 static DBusHashTable *shared_connections = NULL; 01468 static DBusList *shared_connections_no_guid = NULL; 01469 01470 static void 01471 close_connection_on_shutdown (DBusConnection *connection) 01472 { 01473 DBusMessage *message; 01474 01475 dbus_connection_ref (connection); 01476 _dbus_connection_close_possibly_shared (connection); 01477 01478 /* Churn through to the Disconnected message */ 01479 while ((message = dbus_connection_pop_message (connection))) 01480 { 01481 dbus_message_unref (message); 01482 } 01483 dbus_connection_unref (connection); 01484 } 01485 01486 static void 01487 shared_connections_shutdown (void *data) 01488 { 01489 int n_entries; 01490 01491 _DBUS_LOCK (shared_connections); 01492 01493 /* This is a little bit unpleasant... better ideas? */ 01494 while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0) 01495 { 01496 DBusConnection *connection; 01497 DBusHashIter iter; 01498 01499 _dbus_hash_iter_init (shared_connections, &iter); 01500 _dbus_hash_iter_next (&iter); 01501 01502 connection = _dbus_hash_iter_get_value (&iter); 01503 01504 _DBUS_UNLOCK (shared_connections); 01505 close_connection_on_shutdown (connection); 01506 _DBUS_LOCK (shared_connections); 01507 01508 /* The connection should now be dead and not in our hash ... */ 01509 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries); 01510 } 01511 01512 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0); 01513 01514 _dbus_hash_table_unref (shared_connections); 01515 shared_connections = NULL; 01516 01517 if (shared_connections_no_guid != NULL) 01518 { 01519 DBusConnection *connection; 01520 connection = _dbus_list_pop_first (&shared_connections_no_guid); 01521 while (connection != NULL) 01522 { 01523 _DBUS_UNLOCK (shared_connections); 01524 close_connection_on_shutdown (connection); 01525 _DBUS_LOCK (shared_connections); 01526 connection = _dbus_list_pop_first (&shared_connections_no_guid); 01527 } 01528 } 01529 01530 shared_connections_no_guid = NULL; 01531 01532 _DBUS_UNLOCK (shared_connections); 01533 } 01534 01535 static dbus_bool_t 01536 connection_lookup_shared (DBusAddressEntry *entry, 01537 DBusConnection **result) 01538 { 01539 _dbus_verbose ("checking for existing connection\n"); 01540 01541 *result = NULL; 01542 01543 _DBUS_LOCK (shared_connections); 01544 01545 if (shared_connections == NULL) 01546 { 01547 _dbus_verbose ("creating shared_connections hash table\n"); 01548 01549 shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING, 01550 dbus_free, 01551 NULL); 01552 if (shared_connections == NULL) 01553 { 01554 _DBUS_UNLOCK (shared_connections); 01555 return FALSE; 01556 } 01557 01558 if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL)) 01559 { 01560 _dbus_hash_table_unref (shared_connections); 01561 shared_connections = NULL; 01562 _DBUS_UNLOCK (shared_connections); 01563 return FALSE; 01564 } 01565 01566 _dbus_verbose (" successfully created shared_connections\n"); 01567 01568 _DBUS_UNLOCK (shared_connections); 01569 return TRUE; /* no point looking up in the hash we just made */ 01570 } 01571 else 01572 { 01573 const char *guid; 01574 01575 guid = dbus_address_entry_get_value (entry, "guid"); 01576 01577 if (guid != NULL) 01578 { 01579 DBusConnection *connection; 01580 01581 connection = _dbus_hash_table_lookup_string (shared_connections, 01582 guid); 01583 01584 if (connection) 01585 { 01586 /* The DBusConnection can't be finalized without taking 01587 * the shared_connections lock to remove it from the 01588 * hash. So it's safe to ref the connection here. 01589 * However, it may be disconnected if the Disconnected 01590 * message hasn't been processed yet, in which case we 01591 * want to pretend it isn't in the hash and avoid 01592 * returning it. 01593 * 01594 * The idea is to avoid ever returning a disconnected connection 01595 * from dbus_connection_open(). We could just synchronously 01596 * drop our shared ref to the connection on connection disconnect, 01597 * and then assert here that the connection is connected, but 01598 * that causes reentrancy headaches. 01599 */ 01600 CONNECTION_LOCK (connection); 01601 if (_dbus_connection_get_is_connected_unlocked (connection)) 01602 { 01603 _dbus_connection_ref_unlocked (connection); 01604 *result = connection; 01605 _dbus_verbose ("looked up existing connection to server guid %s\n", 01606 guid); 01607 } 01608 else 01609 { 01610 _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n", 01611 guid); 01612 } 01613 CONNECTION_UNLOCK (connection); 01614 } 01615 } 01616 01617 _DBUS_UNLOCK (shared_connections); 01618 return TRUE; 01619 } 01620 } 01621 01622 static dbus_bool_t 01623 connection_record_shared_unlocked (DBusConnection *connection, 01624 const char *guid) 01625 { 01626 char *guid_key; 01627 char *guid_in_connection; 01628 01629 HAVE_LOCK_CHECK (connection); 01630 _dbus_assert (connection->server_guid == NULL); 01631 _dbus_assert (connection->shareable); 01632 01633 /* get a hard ref on this connection, even if 01634 * we won't in fact store it in the hash, we still 01635 * need to hold a ref on it until it's disconnected. 01636 */ 01637 _dbus_connection_ref_unlocked (connection); 01638 01639 if (guid == NULL) 01640 { 01641 _DBUS_LOCK (shared_connections); 01642 01643 if (!_dbus_list_prepend (&shared_connections_no_guid, connection)) 01644 { 01645 _DBUS_UNLOCK (shared_connections); 01646 return FALSE; 01647 } 01648 01649 _DBUS_UNLOCK (shared_connections); 01650 return TRUE; /* don't store in the hash */ 01651 } 01652 01653 /* A separate copy of the key is required in the hash table, because 01654 * we don't have a lock on the connection when we are doing a hash 01655 * lookup. 01656 */ 01657 01658 guid_key = _dbus_strdup (guid); 01659 if (guid_key == NULL) 01660 return FALSE; 01661 01662 guid_in_connection = _dbus_strdup (guid); 01663 if (guid_in_connection == NULL) 01664 { 01665 dbus_free (guid_key); 01666 return FALSE; 01667 } 01668 01669 _DBUS_LOCK (shared_connections); 01670 _dbus_assert (shared_connections != NULL); 01671 01672 if (!_dbus_hash_table_insert_string (shared_connections, 01673 guid_key, connection)) 01674 { 01675 dbus_free (guid_key); 01676 dbus_free (guid_in_connection); 01677 _DBUS_UNLOCK (shared_connections); 01678 return FALSE; 01679 } 01680 01681 connection->server_guid = guid_in_connection; 01682 01683 _dbus_verbose ("stored connection to %s to be shared\n", 01684 connection->server_guid); 01685 01686 _DBUS_UNLOCK (shared_connections); 01687 01688 _dbus_assert (connection->server_guid != NULL); 01689 01690 return TRUE; 01691 } 01692 01693 static void 01694 connection_forget_shared_unlocked (DBusConnection *connection) 01695 { 01696 HAVE_LOCK_CHECK (connection); 01697 01698 if (!connection->shareable) 01699 return; 01700 01701 _DBUS_LOCK (shared_connections); 01702 01703 if (connection->server_guid != NULL) 01704 { 01705 _dbus_verbose ("dropping connection to %s out of the shared table\n", 01706 connection->server_guid); 01707 01708 if (!_dbus_hash_table_remove_string (shared_connections, 01709 connection->server_guid)) 01710 _dbus_assert_not_reached ("connection was not in the shared table"); 01711 01712 dbus_free (connection->server_guid); 01713 connection->server_guid = NULL; 01714 } 01715 else 01716 { 01717 _dbus_list_remove (&shared_connections_no_guid, connection); 01718 } 01719 01720 _DBUS_UNLOCK (shared_connections); 01721 01722 /* remove our reference held on all shareable connections */ 01723 _dbus_connection_unref_unlocked (connection); 01724 } 01725 01726 static DBusConnection* 01727 connection_try_from_address_entry (DBusAddressEntry *entry, 01728 DBusError *error) 01729 { 01730 DBusTransport *transport; 01731 DBusConnection *connection; 01732 01733 transport = _dbus_transport_open (entry, error); 01734 01735 if (transport == NULL) 01736 { 01737 _DBUS_ASSERT_ERROR_IS_SET (error); 01738 return NULL; 01739 } 01740 01741 connection = _dbus_connection_new_for_transport (transport); 01742 01743 _dbus_transport_unref (transport); 01744 01745 if (connection == NULL) 01746 { 01747 _DBUS_SET_OOM (error); 01748 return NULL; 01749 } 01750 01751 #ifndef DBUS_DISABLE_CHECKS 01752 _dbus_assert (!connection->have_connection_lock); 01753 #endif 01754 return connection; 01755 } 01756 01757 /* 01758 * If the shared parameter is true, then any existing connection will 01759 * be used (and if a new connection is created, it will be available 01760 * for use by others). If the shared parameter is false, a new 01761 * connection will always be created, and the new connection will 01762 * never be returned to other callers. 01763 * 01764 * @param address the address 01765 * @param shared whether the connection is shared or private 01766 * @param error error return 01767 * @returns the connection or #NULL on error 01768 */ 01769 static DBusConnection* 01770 _dbus_connection_open_internal (const char *address, 01771 dbus_bool_t shared, 01772 DBusError *error) 01773 { 01774 DBusConnection *connection; 01775 DBusAddressEntry **entries; 01776 DBusError tmp_error = DBUS_ERROR_INIT; 01777 DBusError first_error = DBUS_ERROR_INIT; 01778 int len, i; 01779 01780 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01781 01782 _dbus_verbose ("opening %s connection to: %s\n", 01783 shared ? "shared" : "private", address); 01784 01785 if (!dbus_parse_address (address, &entries, &len, error)) 01786 return NULL; 01787 01788 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01789 01790 connection = NULL; 01791 01792 for (i = 0; i < len; i++) 01793 { 01794 if (shared) 01795 { 01796 if (!connection_lookup_shared (entries[i], &connection)) 01797 _DBUS_SET_OOM (&tmp_error); 01798 } 01799 01800 if (connection == NULL) 01801 { 01802 connection = connection_try_from_address_entry (entries[i], 01803 &tmp_error); 01804 01805 if (connection != NULL && shared) 01806 { 01807 const char *guid; 01808 01809 connection->shareable = TRUE; 01810 01811 /* guid may be NULL */ 01812 guid = dbus_address_entry_get_value (entries[i], "guid"); 01813 01814 CONNECTION_LOCK (connection); 01815 01816 if (!connection_record_shared_unlocked (connection, guid)) 01817 { 01818 _DBUS_SET_OOM (&tmp_error); 01819 _dbus_connection_close_possibly_shared_and_unlock (connection); 01820 dbus_connection_unref (connection); 01821 connection = NULL; 01822 } 01823 else 01824 CONNECTION_UNLOCK (connection); 01825 } 01826 } 01827 01828 if (connection) 01829 break; 01830 01831 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 01832 01833 if (i == 0) 01834 dbus_move_error (&tmp_error, &first_error); 01835 else 01836 dbus_error_free (&tmp_error); 01837 } 01838 01839 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01840 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 01841 01842 if (connection == NULL) 01843 { 01844 _DBUS_ASSERT_ERROR_IS_SET (&first_error); 01845 dbus_move_error (&first_error, error); 01846 } 01847 else 01848 dbus_error_free (&first_error); 01849 01850 dbus_address_entries_free (entries); 01851 return connection; 01852 } 01853 01862 void 01863 _dbus_connection_close_possibly_shared (DBusConnection *connection) 01864 { 01865 _dbus_assert (connection != NULL); 01866 _dbus_assert (connection->generation == _dbus_current_generation); 01867 01868 CONNECTION_LOCK (connection); 01869 _dbus_connection_close_possibly_shared_and_unlock (connection); 01870 } 01871 01872 static DBusPreallocatedSend* 01873 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection) 01874 { 01875 DBusPreallocatedSend *preallocated; 01876 01877 HAVE_LOCK_CHECK (connection); 01878 01879 _dbus_assert (connection != NULL); 01880 01881 preallocated = dbus_new (DBusPreallocatedSend, 1); 01882 if (preallocated == NULL) 01883 return NULL; 01884 01885 if (connection->link_cache != NULL) 01886 { 01887 preallocated->queue_link = 01888 _dbus_list_pop_first_link (&connection->link_cache); 01889 preallocated->queue_link->data = NULL; 01890 } 01891 else 01892 { 01893 preallocated->queue_link = _dbus_list_alloc_link (NULL); 01894 if (preallocated->queue_link == NULL) 01895 goto failed_0; 01896 } 01897 01898 if (connection->link_cache != NULL) 01899 { 01900 preallocated->counter_link = 01901 _dbus_list_pop_first_link (&connection->link_cache); 01902 preallocated->counter_link->data = connection->outgoing_counter; 01903 } 01904 else 01905 { 01906 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter); 01907 if (preallocated->counter_link == NULL) 01908 goto failed_1; 01909 } 01910 01911 _dbus_counter_ref (preallocated->counter_link->data); 01912 01913 preallocated->connection = connection; 01914 01915 return preallocated; 01916 01917 failed_1: 01918 _dbus_list_free_link (preallocated->queue_link); 01919 failed_0: 01920 dbus_free (preallocated); 01921 01922 return NULL; 01923 } 01924 01925 /* Called with lock held, does not update dispatch status */ 01926 static void 01927 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection, 01928 DBusPreallocatedSend *preallocated, 01929 DBusMessage *message, 01930 dbus_uint32_t *client_serial) 01931 { 01932 dbus_uint32_t serial; 01933 const char *sig; 01934 01935 preallocated->queue_link->data = message; 01936 _dbus_list_prepend_link (&connection->outgoing_messages, 01937 preallocated->queue_link); 01938 01939 _dbus_message_add_size_counter_link (message, 01940 preallocated->counter_link); 01941 01942 dbus_free (preallocated); 01943 preallocated = NULL; 01944 01945 dbus_message_ref (message); 01946 01947 connection->n_outgoing += 1; 01948 01949 sig = dbus_message_get_signature (message); 01950 01951 _dbus_verbose ("Message %p (%d %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n", 01952 message, 01953 dbus_message_get_type (message), 01954 dbus_message_get_path (message) ? 01955 dbus_message_get_path (message) : 01956 "no path", 01957 dbus_message_get_interface (message) ? 01958 dbus_message_get_interface (message) : 01959 "no interface", 01960 dbus_message_get_member (message) ? 01961 dbus_message_get_member (message) : 01962 "no member", 01963 sig, 01964 dbus_message_get_destination (message) ? 01965 dbus_message_get_destination (message) : 01966 "null", 01967 connection, 01968 connection->n_outgoing); 01969 01970 if (dbus_message_get_serial (message) == 0) 01971 { 01972 serial = _dbus_connection_get_next_client_serial (connection); 01973 dbus_message_set_serial (message, serial); 01974 if (client_serial) 01975 *client_serial = serial; 01976 } 01977 else 01978 { 01979 if (client_serial) 01980 *client_serial = dbus_message_get_serial (message); 01981 } 01982 01983 _dbus_verbose ("Message %p serial is %u\n", 01984 message, dbus_message_get_serial (message)); 01985 01986 dbus_message_lock (message); 01987 01988 /* Now we need to run an iteration to hopefully just write the messages 01989 * out immediately, and otherwise get them queued up 01990 */ 01991 _dbus_connection_do_iteration_unlocked (connection, 01992 DBUS_ITERATION_DO_WRITING, 01993 -1); 01994 01995 /* If stuff is still queued up, be sure we wake up the main loop */ 01996 if (connection->n_outgoing > 0) 01997 _dbus_connection_wakeup_mainloop (connection); 01998 } 01999 02000 static void 02001 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection, 02002 DBusPreallocatedSend *preallocated, 02003 DBusMessage *message, 02004 dbus_uint32_t *client_serial) 02005 { 02006 DBusDispatchStatus status; 02007 02008 HAVE_LOCK_CHECK (connection); 02009 02010 _dbus_connection_send_preallocated_unlocked_no_update (connection, 02011 preallocated, 02012 message, client_serial); 02013 02014 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME); 02015 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02016 02017 /* this calls out to user code */ 02018 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02019 } 02020 02030 dbus_bool_t 02031 _dbus_connection_send_and_unlock (DBusConnection *connection, 02032 DBusMessage *message, 02033 dbus_uint32_t *client_serial) 02034 { 02035 DBusPreallocatedSend *preallocated; 02036 02037 _dbus_assert (connection != NULL); 02038 _dbus_assert (message != NULL); 02039 02040 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 02041 if (preallocated == NULL) 02042 { 02043 CONNECTION_UNLOCK (connection); 02044 return FALSE; 02045 } 02046 02047 _dbus_connection_send_preallocated_and_unlock (connection, 02048 preallocated, 02049 message, 02050 client_serial); 02051 return TRUE; 02052 } 02053 02078 void 02079 _dbus_connection_close_if_only_one_ref (DBusConnection *connection) 02080 { 02081 CONNECTION_LOCK (connection); 02082 02083 _dbus_assert (connection->refcount.value > 0); 02084 02085 if (connection->refcount.value == 1) 02086 _dbus_connection_close_possibly_shared_and_unlock (connection); 02087 else 02088 CONNECTION_UNLOCK (connection); 02089 } 02090 02091 02101 static void 02102 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds) 02103 { 02104 if (timeout_milliseconds == -1) 02105 _dbus_sleep_milliseconds (1000); 02106 else if (timeout_milliseconds < 100) 02107 ; /* just busy loop */ 02108 else if (timeout_milliseconds <= 1000) 02109 _dbus_sleep_milliseconds (timeout_milliseconds / 3); 02110 else 02111 _dbus_sleep_milliseconds (1000); 02112 } 02113 02114 static DBusMessage * 02115 generate_local_error_message (dbus_uint32_t serial, 02116 char *error_name, 02117 char *error_msg) 02118 { 02119 DBusMessage *message; 02120 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR); 02121 if (!message) 02122 goto out; 02123 02124 if (!dbus_message_set_error_name (message, error_name)) 02125 { 02126 dbus_message_unref (message); 02127 message = NULL; 02128 goto out; 02129 } 02130 02131 dbus_message_set_no_reply (message, TRUE); 02132 02133 if (!dbus_message_set_reply_serial (message, 02134 serial)) 02135 { 02136 dbus_message_unref (message); 02137 message = NULL; 02138 goto out; 02139 } 02140 02141 if (error_msg != NULL) 02142 { 02143 DBusMessageIter iter; 02144 02145 dbus_message_iter_init_append (message, &iter); 02146 if (!dbus_message_iter_append_basic (&iter, 02147 DBUS_TYPE_STRING, 02148 &error_msg)) 02149 { 02150 dbus_message_unref (message); 02151 message = NULL; 02152 goto out; 02153 } 02154 } 02155 02156 out: 02157 return message; 02158 } 02159 02160 02161 /* This is slightly strange since we can pop a message here without 02162 * the dispatch lock. 02163 */ 02164 static DBusMessage* 02165 check_for_reply_unlocked (DBusConnection *connection, 02166 dbus_uint32_t client_serial) 02167 { 02168 DBusList *link; 02169 02170 HAVE_LOCK_CHECK (connection); 02171 02172 link = _dbus_list_get_first_link (&connection->incoming_messages); 02173 02174 while (link != NULL) 02175 { 02176 DBusMessage *reply = link->data; 02177 02178 if (dbus_message_get_reply_serial (reply) == client_serial) 02179 { 02180 _dbus_list_remove_link (&connection->incoming_messages, link); 02181 connection->n_incoming -= 1; 02182 return reply; 02183 } 02184 link = _dbus_list_get_next_link (&connection->incoming_messages, link); 02185 } 02186 02187 return NULL; 02188 } 02189 02190 static void 02191 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection) 02192 { 02193 /* We can't iterate over the hash in the normal way since we'll be 02194 * dropping the lock for each item. So we restart the 02195 * iter each time as we drain the hash table. 02196 */ 02197 02198 while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0) 02199 { 02200 DBusPendingCall *pending; 02201 DBusHashIter iter; 02202 02203 _dbus_hash_iter_init (connection->pending_replies, &iter); 02204 _dbus_hash_iter_next (&iter); 02205 02206 pending = _dbus_hash_iter_get_value (&iter); 02207 _dbus_pending_call_ref_unlocked (pending); 02208 02209 _dbus_pending_call_queue_timeout_error_unlocked (pending, 02210 connection); 02211 02212 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 02213 _dbus_connection_remove_timeout_unlocked (connection, 02214 _dbus_pending_call_get_timeout_unlocked (pending)); 02215 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 02216 _dbus_hash_iter_remove_entry (&iter); 02217 02218 _dbus_pending_call_unref_and_unlock (pending); 02219 CONNECTION_LOCK (connection); 02220 } 02221 HAVE_LOCK_CHECK (connection); 02222 } 02223 02224 static void 02225 complete_pending_call_and_unlock (DBusConnection *connection, 02226 DBusPendingCall *pending, 02227 DBusMessage *message) 02228 { 02229 _dbus_pending_call_set_reply_unlocked (pending, message); 02230 _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */ 02231 _dbus_connection_detach_pending_call_and_unlock (connection, pending); 02232 02233 /* Must be called unlocked since it invokes app callback */ 02234 _dbus_pending_call_complete (pending); 02235 dbus_pending_call_unref (pending); 02236 } 02237 02238 static dbus_bool_t 02239 check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection, 02240 DBusPendingCall *pending) 02241 { 02242 DBusMessage *reply; 02243 DBusDispatchStatus status; 02244 02245 reply = check_for_reply_unlocked (connection, 02246 _dbus_pending_call_get_reply_serial_unlocked (pending)); 02247 if (reply != NULL) 02248 { 02249 _dbus_verbose ("%s checked for reply\n", _DBUS_FUNCTION_NAME); 02250 02251 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n"); 02252 02253 complete_pending_call_and_unlock (connection, pending, reply); 02254 dbus_message_unref (reply); 02255 02256 CONNECTION_LOCK (connection); 02257 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02258 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02259 dbus_pending_call_unref (pending); 02260 02261 return TRUE; 02262 } 02263 02264 return FALSE; 02265 } 02266 02281 void 02282 _dbus_connection_block_pending_call (DBusPendingCall *pending) 02283 { 02284 long start_tv_sec, start_tv_usec; 02285 long tv_sec, tv_usec; 02286 DBusDispatchStatus status; 02287 DBusConnection *connection; 02288 dbus_uint32_t client_serial; 02289 DBusTimeout *timeout; 02290 int timeout_milliseconds, elapsed_milliseconds; 02291 02292 _dbus_assert (pending != NULL); 02293 02294 if (dbus_pending_call_get_completed (pending)) 02295 return; 02296 02297 dbus_pending_call_ref (pending); /* necessary because the call could be canceled */ 02298 02299 connection = _dbus_pending_call_get_connection_and_lock (pending); 02300 02301 /* Flush message queue - note, can affect dispatch status */ 02302 _dbus_connection_flush_unlocked (connection); 02303 02304 client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending); 02305 02306 /* note that timeout_milliseconds is limited to a smallish value 02307 * in _dbus_pending_call_new() so overflows aren't possible 02308 * below 02309 */ 02310 timeout = _dbus_pending_call_get_timeout_unlocked (pending); 02311 if (timeout) 02312 { 02313 timeout_milliseconds = dbus_timeout_get_interval (timeout); 02314 _dbus_get_current_time (&start_tv_sec, &start_tv_usec); 02315 02316 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n", 02317 timeout_milliseconds, 02318 client_serial, 02319 start_tv_sec, start_tv_usec); 02320 } 02321 else 02322 { 02323 timeout_milliseconds = -1; 02324 02325 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial); 02326 } 02327 02328 /* check to see if we already got the data off the socket */ 02329 /* from another blocked pending call */ 02330 if (check_for_reply_and_update_dispatch_unlocked (connection, pending)) 02331 return; 02332 02333 /* Now we wait... */ 02334 /* always block at least once as we know we don't have the reply yet */ 02335 _dbus_connection_do_iteration_unlocked (connection, 02336 DBUS_ITERATION_DO_READING | 02337 DBUS_ITERATION_BLOCK, 02338 timeout_milliseconds); 02339 02340 recheck_status: 02341 02342 _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME); 02343 02344 HAVE_LOCK_CHECK (connection); 02345 02346 /* queue messages and get status */ 02347 02348 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02349 02350 /* the get_completed() is in case a dispatch() while we were blocking 02351 * got the reply instead of us. 02352 */ 02353 if (_dbus_pending_call_get_completed_unlocked (pending)) 02354 { 02355 _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME); 02356 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02357 dbus_pending_call_unref (pending); 02358 return; 02359 } 02360 02361 if (status == DBUS_DISPATCH_DATA_REMAINS) 02362 { 02363 if (check_for_reply_and_update_dispatch_unlocked (connection, pending)) 02364 return; 02365 } 02366 02367 _dbus_get_current_time (&tv_sec, &tv_usec); 02368 elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 + 02369 (tv_usec - start_tv_usec) / 1000; 02370 02371 if (!_dbus_connection_get_is_connected_unlocked (connection)) 02372 { 02373 DBusMessage *error_msg; 02374 02375 error_msg = generate_local_error_message (client_serial, 02376 DBUS_ERROR_DISCONNECTED, 02377 "Connection was disconnected before a reply was received"); 02378 02379 /* on OOM error_msg is set to NULL */ 02380 complete_pending_call_and_unlock (connection, pending, error_msg); 02381 dbus_pending_call_unref (pending); 02382 return; 02383 } 02384 else if (connection->disconnect_message_link == NULL) 02385 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n"); 02386 else if (timeout == NULL) 02387 { 02388 if (status == DBUS_DISPATCH_NEED_MEMORY) 02389 { 02390 /* Try sleeping a bit, as we aren't sure we need to block for reading, 02391 * we may already have a reply in the buffer and just can't process 02392 * it. 02393 */ 02394 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n"); 02395 02396 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds); 02397 } 02398 else 02399 { 02400 /* block again, we don't have the reply buffered yet. */ 02401 _dbus_connection_do_iteration_unlocked (connection, 02402 DBUS_ITERATION_DO_READING | 02403 DBUS_ITERATION_BLOCK, 02404 timeout_milliseconds - elapsed_milliseconds); 02405 } 02406 02407 goto recheck_status; 02408 } 02409 else if (tv_sec < start_tv_sec) 02410 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n"); 02411 else if (elapsed_milliseconds < timeout_milliseconds) 02412 { 02413 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds); 02414 02415 if (status == DBUS_DISPATCH_NEED_MEMORY) 02416 { 02417 /* Try sleeping a bit, as we aren't sure we need to block for reading, 02418 * we may already have a reply in the buffer and just can't process 02419 * it. 02420 */ 02421 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n"); 02422 02423 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds); 02424 } 02425 else 02426 { 02427 /* block again, we don't have the reply buffered yet. */ 02428 _dbus_connection_do_iteration_unlocked (connection, 02429 DBUS_ITERATION_DO_READING | 02430 DBUS_ITERATION_BLOCK, 02431 timeout_milliseconds - elapsed_milliseconds); 02432 } 02433 02434 goto recheck_status; 02435 } 02436 02437 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n", 02438 elapsed_milliseconds); 02439 02440 _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending)); 02441 02442 /* unlock and call user code */ 02443 complete_pending_call_and_unlock (connection, pending, NULL); 02444 02445 /* update user code on dispatch status */ 02446 CONNECTION_LOCK (connection); 02447 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02448 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02449 dbus_pending_call_unref (pending); 02450 } 02451 02488 DBusConnection* 02489 dbus_connection_open (const char *address, 02490 DBusError *error) 02491 { 02492 DBusConnection *connection; 02493 02494 _dbus_return_val_if_fail (address != NULL, NULL); 02495 _dbus_return_val_if_error_is_set (error, NULL); 02496 02497 connection = _dbus_connection_open_internal (address, 02498 TRUE, 02499 error); 02500 02501 return connection; 02502 } 02503 02531 DBusConnection* 02532 dbus_connection_open_private (const char *address, 02533 DBusError *error) 02534 { 02535 DBusConnection *connection; 02536 02537 _dbus_return_val_if_fail (address != NULL, NULL); 02538 _dbus_return_val_if_error_is_set (error, NULL); 02539 02540 connection = _dbus_connection_open_internal (address, 02541 FALSE, 02542 error); 02543 02544 return connection; 02545 } 02546 02553 DBusConnection * 02554 dbus_connection_ref (DBusConnection *connection) 02555 { 02556 _dbus_return_val_if_fail (connection != NULL, NULL); 02557 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL); 02558 02559 /* The connection lock is better than the global 02560 * lock in the atomic increment fallback 02561 */ 02562 02563 #ifdef DBUS_HAVE_ATOMIC_INT 02564 _dbus_atomic_inc (&connection->refcount); 02565 #else 02566 CONNECTION_LOCK (connection); 02567 _dbus_assert (connection->refcount.value > 0); 02568 02569 connection->refcount.value += 1; 02570 CONNECTION_UNLOCK (connection); 02571 #endif 02572 02573 return connection; 02574 } 02575 02576 static void 02577 free_outgoing_message (void *element, 02578 void *data) 02579 { 02580 DBusMessage *message = element; 02581 DBusConnection *connection = data; 02582 02583 _dbus_message_remove_size_counter (message, 02584 connection->outgoing_counter, 02585 NULL); 02586 dbus_message_unref (message); 02587 } 02588 02589 /* This is run without the mutex held, but after the last reference 02590 * to the connection has been dropped we should have no thread-related 02591 * problems 02592 */ 02593 static void 02594 _dbus_connection_last_unref (DBusConnection *connection) 02595 { 02596 DBusList *link; 02597 02598 _dbus_verbose ("Finalizing connection %p\n", connection); 02599 02600 _dbus_assert (connection->refcount.value == 0); 02601 02602 /* You have to disconnect the connection before unref:ing it. Otherwise 02603 * you won't get the disconnected message. 02604 */ 02605 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport)); 02606 _dbus_assert (connection->server_guid == NULL); 02607 02608 /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */ 02609 _dbus_object_tree_free_all_unlocked (connection->objects); 02610 02611 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL); 02612 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL); 02613 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL); 02614 02615 _dbus_watch_list_free (connection->watches); 02616 connection->watches = NULL; 02617 02618 _dbus_timeout_list_free (connection->timeouts); 02619 connection->timeouts = NULL; 02620 02621 _dbus_data_slot_list_free (&connection->slot_list); 02622 02623 link = _dbus_list_get_first_link (&connection->filter_list); 02624 while (link != NULL) 02625 { 02626 DBusMessageFilter *filter = link->data; 02627 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link); 02628 02629 filter->function = NULL; 02630 _dbus_message_filter_unref (filter); /* calls app callback */ 02631 link->data = NULL; 02632 02633 link = next; 02634 } 02635 _dbus_list_clear (&connection->filter_list); 02636 02637 /* ---- Done with stuff that invokes application callbacks */ 02638 02639 _dbus_object_tree_unref (connection->objects); 02640 02641 _dbus_hash_table_unref (connection->pending_replies); 02642 connection->pending_replies = NULL; 02643 02644 _dbus_list_clear (&connection->filter_list); 02645 02646 _dbus_list_foreach (&connection->outgoing_messages, 02647 free_outgoing_message, 02648 connection); 02649 _dbus_list_clear (&connection->outgoing_messages); 02650 02651 _dbus_list_foreach (&connection->incoming_messages, 02652 (DBusForeachFunction) dbus_message_unref, 02653 NULL); 02654 _dbus_list_clear (&connection->incoming_messages); 02655 02656 _dbus_counter_unref (connection->outgoing_counter); 02657 02658 _dbus_transport_unref (connection->transport); 02659 02660 if (connection->disconnect_message_link) 02661 { 02662 DBusMessage *message = connection->disconnect_message_link->data; 02663 dbus_message_unref (message); 02664 _dbus_list_free_link (connection->disconnect_message_link); 02665 } 02666 02667 _dbus_list_clear (&connection->link_cache); 02668 02669 _dbus_condvar_free_at_location (&connection->dispatch_cond); 02670 _dbus_condvar_free_at_location (&connection->io_path_cond); 02671 02672 _dbus_mutex_free_at_location (&connection->io_path_mutex); 02673 _dbus_mutex_free_at_location (&connection->dispatch_mutex); 02674 02675 _dbus_mutex_free_at_location (&connection->mutex); 02676 02677 dbus_free (connection); 02678 } 02679 02699 void 02700 dbus_connection_unref (DBusConnection *connection) 02701 { 02702 dbus_bool_t last_unref; 02703 02704 _dbus_return_if_fail (connection != NULL); 02705 _dbus_return_if_fail (connection->generation == _dbus_current_generation); 02706 02707 /* The connection lock is better than the global 02708 * lock in the atomic increment fallback 02709 */ 02710 02711 #ifdef DBUS_HAVE_ATOMIC_INT 02712 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1); 02713 #else 02714 CONNECTION_LOCK (connection); 02715 02716 _dbus_assert (connection->refcount.value > 0); 02717 02718 connection->refcount.value -= 1; 02719 last_unref = (connection->refcount.value == 0); 02720 02721 #if 0 02722 printf ("unref() connection %p count = %d\n", connection, connection->refcount.value); 02723 #endif 02724 02725 CONNECTION_UNLOCK (connection); 02726 #endif 02727 02728 if (last_unref) 02729 { 02730 #ifndef DBUS_DISABLE_CHECKS 02731 if (_dbus_transport_get_is_connected (connection->transport)) 02732 { 02733 _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", 02734 connection->shareable ? 02735 "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" : 02736 "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n"); 02737 return; 02738 } 02739 #endif 02740 _dbus_connection_last_unref (connection); 02741 } 02742 } 02743 02744 /* 02745 * Note that the transport can disconnect itself (other end drops us) 02746 * and in that case this function never runs. So this function must 02747 * not do anything more than disconnect the transport and update the 02748 * dispatch status. 02749 * 02750 * If the transport self-disconnects, then we assume someone will 02751 * dispatch the connection to cause the dispatch status update. 02752 */ 02753 static void 02754 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection) 02755 { 02756 DBusDispatchStatus status; 02757 02758 HAVE_LOCK_CHECK (connection); 02759 02760 _dbus_verbose ("Disconnecting %p\n", connection); 02761 02762 /* We need to ref because update_dispatch_status_and_unlock will unref 02763 * the connection if it was shared and libdbus was the only remaining 02764 * refcount holder. 02765 */ 02766 _dbus_connection_ref_unlocked (connection); 02767 02768 _dbus_transport_disconnect (connection->transport); 02769 02770 /* This has the side effect of queuing the disconnect message link 02771 * (unless we don't have enough memory, possibly, so don't assert it). 02772 * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open 02773 * should never again return the newly-disconnected connection. 02774 * 02775 * However, we only unref the shared connection and exit_on_disconnect when 02776 * the disconnect message reaches the head of the message queue, 02777 * NOT when it's first queued. 02778 */ 02779 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02780 02781 /* This calls out to user code */ 02782 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02783 02784 /* Could also call out to user code */ 02785 dbus_connection_unref (connection); 02786 } 02787 02830 void 02831 dbus_connection_close (DBusConnection *connection) 02832 { 02833 _dbus_return_if_fail (connection != NULL); 02834 _dbus_return_if_fail (connection->generation == _dbus_current_generation); 02835 02836 CONNECTION_LOCK (connection); 02837 02838 #ifndef DBUS_DISABLE_CHECKS 02839 if (connection->shareable) 02840 { 02841 CONNECTION_UNLOCK (connection); 02842 02843 _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n"); 02844 return; 02845 } 02846 #endif 02847 02848 _dbus_connection_close_possibly_shared_and_unlock (connection); 02849 } 02850 02851 static dbus_bool_t 02852 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection) 02853 { 02854 HAVE_LOCK_CHECK (connection); 02855 return _dbus_transport_get_is_connected (connection->transport); 02856 } 02857 02871 dbus_bool_t 02872 dbus_connection_get_is_connected (DBusConnection *connection) 02873 { 02874 dbus_bool_t res; 02875 02876 _dbus_return_val_if_fail (connection != NULL, FALSE); 02877 02878 CONNECTION_LOCK (connection); 02879 res = _dbus_connection_get_is_connected_unlocked (connection); 02880 CONNECTION_UNLOCK (connection); 02881 02882 return res; 02883 } 02884 02893 dbus_bool_t 02894 dbus_connection_get_is_authenticated (DBusConnection *connection) 02895 { 02896 dbus_bool_t res; 02897 02898 _dbus_return_val_if_fail (connection != NULL, FALSE); 02899 02900 CONNECTION_LOCK (connection); 02901 res = _dbus_transport_get_is_authenticated (connection->transport); 02902 CONNECTION_UNLOCK (connection); 02903 02904 return res; 02905 } 02906 02927 dbus_bool_t 02928 dbus_connection_get_is_anonymous (DBusConnection *connection) 02929 { 02930 dbus_bool_t res; 02931 02932 _dbus_return_val_if_fail (connection != NULL, FALSE); 02933 02934 CONNECTION_LOCK (connection); 02935 res = _dbus_transport_get_is_anonymous (connection->transport); 02936 CONNECTION_UNLOCK (connection); 02937 02938 return res; 02939 } 02940 02972 char* 02973 dbus_connection_get_server_id (DBusConnection *connection) 02974 { 02975 char *id; 02976 02977 _dbus_return_val_if_fail (connection != NULL, NULL); 02978 02979 CONNECTION_LOCK (connection); 02980 id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport)); 02981 CONNECTION_UNLOCK (connection); 02982 02983 return id; 02984 } 02985 02999 void 03000 dbus_connection_set_exit_on_disconnect (DBusConnection *connection, 03001 dbus_bool_t exit_on_disconnect) 03002 { 03003 _dbus_return_if_fail (connection != NULL); 03004 03005 CONNECTION_LOCK (connection); 03006 connection->exit_on_disconnect = exit_on_disconnect != FALSE; 03007 CONNECTION_UNLOCK (connection); 03008 } 03009 03019 DBusPreallocatedSend* 03020 dbus_connection_preallocate_send (DBusConnection *connection) 03021 { 03022 DBusPreallocatedSend *preallocated; 03023 03024 _dbus_return_val_if_fail (connection != NULL, NULL); 03025 03026 CONNECTION_LOCK (connection); 03027 03028 preallocated = 03029 _dbus_connection_preallocate_send_unlocked (connection); 03030 03031 CONNECTION_UNLOCK (connection); 03032 03033 return preallocated; 03034 } 03035 03045 void 03046 dbus_connection_free_preallocated_send (DBusConnection *connection, 03047 DBusPreallocatedSend *preallocated) 03048 { 03049 _dbus_return_if_fail (connection != NULL); 03050 _dbus_return_if_fail (preallocated != NULL); 03051 _dbus_return_if_fail (connection == preallocated->connection); 03052 03053 _dbus_list_free_link (preallocated->queue_link); 03054 _dbus_counter_unref (preallocated->counter_link->data); 03055 _dbus_list_free_link (preallocated->counter_link); 03056 dbus_free (preallocated); 03057 } 03058 03071 void 03072 dbus_connection_send_preallocated (DBusConnection *connection, 03073 DBusPreallocatedSend *preallocated, 03074 DBusMessage *message, 03075 dbus_uint32_t *client_serial) 03076 { 03077 _dbus_return_if_fail (connection != NULL); 03078 _dbus_return_if_fail (preallocated != NULL); 03079 _dbus_return_if_fail (message != NULL); 03080 _dbus_return_if_fail (preallocated->connection == connection); 03081 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL || 03082 dbus_message_get_member (message) != NULL); 03083 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL || 03084 (dbus_message_get_interface (message) != NULL && 03085 dbus_message_get_member (message) != NULL)); 03086 03087 CONNECTION_LOCK (connection); 03088 _dbus_connection_send_preallocated_and_unlock (connection, 03089 preallocated, 03090 message, client_serial); 03091 } 03092 03093 static dbus_bool_t 03094 _dbus_connection_send_unlocked_no_update (DBusConnection *connection, 03095 DBusMessage *message, 03096 dbus_uint32_t *client_serial) 03097 { 03098 DBusPreallocatedSend *preallocated; 03099 03100 _dbus_assert (connection != NULL); 03101 _dbus_assert (message != NULL); 03102 03103 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 03104 if (preallocated == NULL) 03105 return FALSE; 03106 03107 _dbus_connection_send_preallocated_unlocked_no_update (connection, 03108 preallocated, 03109 message, 03110 client_serial); 03111 return TRUE; 03112 } 03113 03141 dbus_bool_t 03142 dbus_connection_send (DBusConnection *connection, 03143 DBusMessage *message, 03144 dbus_uint32_t *serial) 03145 { 03146 _dbus_return_val_if_fail (connection != NULL, FALSE); 03147 _dbus_return_val_if_fail (message != NULL, FALSE); 03148 03149 CONNECTION_LOCK (connection); 03150 03151 return _dbus_connection_send_and_unlock (connection, 03152 message, 03153 serial); 03154 } 03155 03156 static dbus_bool_t 03157 reply_handler_timeout (void *data) 03158 { 03159 DBusConnection *connection; 03160 DBusDispatchStatus status; 03161 DBusPendingCall *pending = data; 03162 03163 connection = _dbus_pending_call_get_connection_and_lock (pending); 03164 03165 _dbus_pending_call_queue_timeout_error_unlocked (pending, 03166 connection); 03167 _dbus_connection_remove_timeout_unlocked (connection, 03168 _dbus_pending_call_get_timeout_unlocked (pending)); 03169 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 03170 03171 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME); 03172 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03173 03174 /* Unlocks, and calls out to user code */ 03175 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03176 03177 return TRUE; 03178 } 03179 03215 dbus_bool_t 03216 dbus_connection_send_with_reply (DBusConnection *connection, 03217 DBusMessage *message, 03218 DBusPendingCall **pending_return, 03219 int timeout_milliseconds) 03220 { 03221 DBusPendingCall *pending; 03222 dbus_int32_t serial = -1; 03223 DBusDispatchStatus status; 03224 03225 _dbus_return_val_if_fail (connection != NULL, FALSE); 03226 _dbus_return_val_if_fail (message != NULL, FALSE); 03227 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03228 03229 if (pending_return) 03230 *pending_return = NULL; 03231 03232 CONNECTION_LOCK (connection); 03233 03234 if (!_dbus_connection_get_is_connected_unlocked (connection)) 03235 { 03236 CONNECTION_UNLOCK (connection); 03237 03238 return TRUE; 03239 } 03240 03241 pending = _dbus_pending_call_new_unlocked (connection, 03242 timeout_milliseconds, 03243 reply_handler_timeout); 03244 03245 if (pending == NULL) 03246 { 03247 CONNECTION_UNLOCK (connection); 03248 return FALSE; 03249 } 03250 03251 /* Assign a serial to the message */ 03252 serial = dbus_message_get_serial (message); 03253 if (serial == 0) 03254 { 03255 serial = _dbus_connection_get_next_client_serial (connection); 03256 dbus_message_set_serial (message, serial); 03257 } 03258 03259 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial)) 03260 goto error; 03261 03262 /* Insert the serial in the pending replies hash; 03263 * hash takes a refcount on DBusPendingCall. 03264 * Also, add the timeout. 03265 */ 03266 if (!_dbus_connection_attach_pending_call_unlocked (connection, 03267 pending)) 03268 goto error; 03269 03270 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL)) 03271 { 03272 _dbus_connection_detach_pending_call_and_unlock (connection, 03273 pending); 03274 goto error_unlocked; 03275 } 03276 03277 if (pending_return) 03278 *pending_return = pending; /* hand off refcount */ 03279 else 03280 { 03281 _dbus_connection_detach_pending_call_unlocked (connection, pending); 03282 /* we still have a ref to the pending call in this case, we unref 03283 * after unlocking, below 03284 */ 03285 } 03286 03287 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03288 03289 /* this calls out to user code */ 03290 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03291 03292 if (pending_return == NULL) 03293 dbus_pending_call_unref (pending); 03294 03295 return TRUE; 03296 03297 error: 03298 CONNECTION_UNLOCK (connection); 03299 error_unlocked: 03300 dbus_pending_call_unref (pending); 03301 return FALSE; 03302 } 03303 03334 DBusMessage* 03335 dbus_connection_send_with_reply_and_block (DBusConnection *connection, 03336 DBusMessage *message, 03337 int timeout_milliseconds, 03338 DBusError *error) 03339 { 03340 DBusMessage *reply; 03341 DBusPendingCall *pending; 03342 03343 _dbus_return_val_if_fail (connection != NULL, NULL); 03344 _dbus_return_val_if_fail (message != NULL, NULL); 03345 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL); 03346 _dbus_return_val_if_error_is_set (error, NULL); 03347 03348 if (!dbus_connection_send_with_reply (connection, message, 03349 &pending, timeout_milliseconds)) 03350 { 03351 _DBUS_SET_OOM (error); 03352 return NULL; 03353 } 03354 03355 if (pending == NULL) 03356 { 03357 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed"); 03358 return NULL; 03359 } 03360 03361 dbus_pending_call_block (pending); 03362 03363 reply = dbus_pending_call_steal_reply (pending); 03364 dbus_pending_call_unref (pending); 03365 03366 /* call_complete_and_unlock() called from pending_call_block() should 03367 * always fill this in. 03368 */ 03369 _dbus_assert (reply != NULL); 03370 03371 if (dbus_set_error_from_message (error, reply)) 03372 { 03373 dbus_message_unref (reply); 03374 return NULL; 03375 } 03376 else 03377 return reply; 03378 } 03379 03388 static DBusDispatchStatus 03389 _dbus_connection_flush_unlocked (DBusConnection *connection) 03390 { 03391 /* We have to specify DBUS_ITERATION_DO_READING here because 03392 * otherwise we could have two apps deadlock if they are both doing 03393 * a flush(), and the kernel buffers fill up. This could change the 03394 * dispatch status. 03395 */ 03396 DBusDispatchStatus status; 03397 03398 HAVE_LOCK_CHECK (connection); 03399 03400 while (connection->n_outgoing > 0 && 03401 _dbus_connection_get_is_connected_unlocked (connection)) 03402 { 03403 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME); 03404 HAVE_LOCK_CHECK (connection); 03405 _dbus_connection_do_iteration_unlocked (connection, 03406 DBUS_ITERATION_DO_READING | 03407 DBUS_ITERATION_DO_WRITING | 03408 DBUS_ITERATION_BLOCK, 03409 -1); 03410 } 03411 03412 HAVE_LOCK_CHECK (connection); 03413 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME); 03414 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03415 03416 HAVE_LOCK_CHECK (connection); 03417 return status; 03418 } 03419 03425 void 03426 dbus_connection_flush (DBusConnection *connection) 03427 { 03428 /* We have to specify DBUS_ITERATION_DO_READING here because 03429 * otherwise we could have two apps deadlock if they are both doing 03430 * a flush(), and the kernel buffers fill up. This could change the 03431 * dispatch status. 03432 */ 03433 DBusDispatchStatus status; 03434 03435 _dbus_return_if_fail (connection != NULL); 03436 03437 CONNECTION_LOCK (connection); 03438 03439 status = _dbus_connection_flush_unlocked (connection); 03440 03441 HAVE_LOCK_CHECK (connection); 03442 /* Unlocks and calls out to user code */ 03443 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03444 03445 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME); 03446 } 03447 03458 static dbus_bool_t 03459 _dbus_connection_read_write_dispatch (DBusConnection *connection, 03460 int timeout_milliseconds, 03461 dbus_bool_t dispatch) 03462 { 03463 DBusDispatchStatus dstatus; 03464 dbus_bool_t progress_possible; 03465 03466 /* Need to grab a ref here in case we're a private connection and 03467 * the user drops the last ref in a handler we call; see bug 03468 * https://bugs.freedesktop.org/show_bug.cgi?id=15635 03469 */ 03470 dbus_connection_ref (connection); 03471 dstatus = dbus_connection_get_dispatch_status (connection); 03472 03473 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS) 03474 { 03475 _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME); 03476 dbus_connection_dispatch (connection); 03477 CONNECTION_LOCK (connection); 03478 } 03479 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY) 03480 { 03481 _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME); 03482 _dbus_memory_pause_based_on_timeout (timeout_milliseconds); 03483 CONNECTION_LOCK (connection); 03484 } 03485 else 03486 { 03487 CONNECTION_LOCK (connection); 03488 if (_dbus_connection_get_is_connected_unlocked (connection)) 03489 { 03490 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME); 03491 _dbus_connection_do_iteration_unlocked (connection, 03492 DBUS_ITERATION_DO_READING | 03493 DBUS_ITERATION_DO_WRITING | 03494 DBUS_ITERATION_BLOCK, 03495 timeout_milliseconds); 03496 } 03497 } 03498 03499 HAVE_LOCK_CHECK (connection); 03500 /* If we can dispatch, we can make progress until the Disconnected message 03501 * has been processed; if we can only read/write, we can make progress 03502 * as long as the transport is open. 03503 */ 03504 if (dispatch) 03505 progress_possible = connection->n_incoming != 0 || 03506 connection->disconnect_message_link != NULL; 03507 else 03508 progress_possible = _dbus_connection_get_is_connected_unlocked (connection); 03509 03510 CONNECTION_UNLOCK (connection); 03511 03512 dbus_connection_unref (connection); 03513 03514 return progress_possible; /* TRUE if we can make more progress */ 03515 } 03516 03517 03552 dbus_bool_t 03553 dbus_connection_read_write_dispatch (DBusConnection *connection, 03554 int timeout_milliseconds) 03555 { 03556 _dbus_return_val_if_fail (connection != NULL, FALSE); 03557 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03558 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE); 03559 } 03560 03584 dbus_bool_t 03585 dbus_connection_read_write (DBusConnection *connection, 03586 int timeout_milliseconds) 03587 { 03588 _dbus_return_val_if_fail (connection != NULL, FALSE); 03589 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03590 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE); 03591 } 03592 03593 /* We need to call this anytime we pop the head of the queue, and then 03594 * update_dispatch_status_and_unlock needs to be called afterward 03595 * which will "process" the disconnected message and set 03596 * disconnected_message_processed. 03597 */ 03598 static void 03599 check_disconnected_message_arrived_unlocked (DBusConnection *connection, 03600 DBusMessage *head_of_queue) 03601 { 03602 HAVE_LOCK_CHECK (connection); 03603 03604 /* checking that the link is NULL is an optimization to avoid the is_signal call */ 03605 if (connection->disconnect_message_link == NULL && 03606 dbus_message_is_signal (head_of_queue, 03607 DBUS_INTERFACE_LOCAL, 03608 "Disconnected")) 03609 { 03610 connection->disconnected_message_arrived = TRUE; 03611 } 03612 } 03613 03633 DBusMessage* 03634 dbus_connection_borrow_message (DBusConnection *connection) 03635 { 03636 DBusDispatchStatus status; 03637 DBusMessage *message; 03638 03639 _dbus_return_val_if_fail (connection != NULL, NULL); 03640 03641 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME); 03642 03643 /* this is called for the side effect that it queues 03644 * up any messages from the transport 03645 */ 03646 status = dbus_connection_get_dispatch_status (connection); 03647 if (status != DBUS_DISPATCH_DATA_REMAINS) 03648 return NULL; 03649 03650 CONNECTION_LOCK (connection); 03651 03652 _dbus_connection_acquire_dispatch (connection); 03653 03654 /* While a message is outstanding, the dispatch lock is held */ 03655 _dbus_assert (connection->message_borrowed == NULL); 03656 03657 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages); 03658 03659 message = connection->message_borrowed; 03660 03661 check_disconnected_message_arrived_unlocked (connection, message); 03662 03663 /* Note that we KEEP the dispatch lock until the message is returned */ 03664 if (message == NULL) 03665 _dbus_connection_release_dispatch (connection); 03666 03667 CONNECTION_UNLOCK (connection); 03668 03669 /* We don't update dispatch status until it's returned or stolen */ 03670 03671 return message; 03672 } 03673 03682 void 03683 dbus_connection_return_message (DBusConnection *connection, 03684 DBusMessage *message) 03685 { 03686 DBusDispatchStatus status; 03687 03688 _dbus_return_if_fail (connection != NULL); 03689 _dbus_return_if_fail (message != NULL); 03690 _dbus_return_if_fail (message == connection->message_borrowed); 03691 _dbus_return_if_fail (connection->dispatch_acquired); 03692 03693 CONNECTION_LOCK (connection); 03694 03695 _dbus_assert (message == connection->message_borrowed); 03696 03697 connection->message_borrowed = NULL; 03698 03699 _dbus_connection_release_dispatch (connection); 03700 03701 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03702 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03703 } 03704 03714 void 03715 dbus_connection_steal_borrowed_message (DBusConnection *connection, 03716 DBusMessage *message) 03717 { 03718 DBusMessage *pop_message; 03719 DBusDispatchStatus status; 03720 03721 _dbus_return_if_fail (connection != NULL); 03722 _dbus_return_if_fail (message != NULL); 03723 _dbus_return_if_fail (message == connection->message_borrowed); 03724 _dbus_return_if_fail (connection->dispatch_acquired); 03725 03726 CONNECTION_LOCK (connection); 03727 03728 _dbus_assert (message == connection->message_borrowed); 03729 03730 pop_message = _dbus_list_pop_first (&connection->incoming_messages); 03731 _dbus_assert (message == pop_message); 03732 03733 connection->n_incoming -= 1; 03734 03735 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n", 03736 message, connection->n_incoming); 03737 03738 connection->message_borrowed = NULL; 03739 03740 _dbus_connection_release_dispatch (connection); 03741 03742 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03743 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03744 } 03745 03746 /* See dbus_connection_pop_message, but requires the caller to own 03747 * the lock before calling. May drop the lock while running. 03748 */ 03749 static DBusList* 03750 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection) 03751 { 03752 HAVE_LOCK_CHECK (connection); 03753 03754 _dbus_assert (connection->message_borrowed == NULL); 03755 03756 if (connection->n_incoming > 0) 03757 { 03758 DBusList *link; 03759 03760 link = _dbus_list_pop_first_link (&connection->incoming_messages); 03761 connection->n_incoming -= 1; 03762 03763 _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n", 03764 link->data, 03765 dbus_message_get_type (link->data), 03766 dbus_message_get_path (link->data) ? 03767 dbus_message_get_path (link->data) : 03768 "no path", 03769 dbus_message_get_interface (link->data) ? 03770 dbus_message_get_interface (link->data) : 03771 "no interface", 03772 dbus_message_get_member (link->data) ? 03773 dbus_message_get_member (link->data) : 03774 "no member", 03775 dbus_message_get_signature (link->data), 03776 connection, connection->n_incoming); 03777 03778 check_disconnected_message_arrived_unlocked (connection, link->data); 03779 03780 return link; 03781 } 03782 else 03783 return NULL; 03784 } 03785 03786 /* See dbus_connection_pop_message, but requires the caller to own 03787 * the lock before calling. May drop the lock while running. 03788 */ 03789 static DBusMessage* 03790 _dbus_connection_pop_message_unlocked (DBusConnection *connection) 03791 { 03792 DBusList *link; 03793 03794 HAVE_LOCK_CHECK (connection); 03795 03796 link = _dbus_connection_pop_message_link_unlocked (connection); 03797 03798 if (link != NULL) 03799 { 03800 DBusMessage *message; 03801 03802 message = link->data; 03803 03804 _dbus_list_free_link (link); 03805 03806 return message; 03807 } 03808 else 03809 return NULL; 03810 } 03811 03812 static void 03813 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection, 03814 DBusList *message_link) 03815 { 03816 HAVE_LOCK_CHECK (connection); 03817 03818 _dbus_assert (message_link != NULL); 03819 /* You can't borrow a message while a link is outstanding */ 03820 _dbus_assert (connection->message_borrowed == NULL); 03821 /* We had to have the dispatch lock across the pop/putback */ 03822 _dbus_assert (connection->dispatch_acquired); 03823 03824 _dbus_list_prepend_link (&connection->incoming_messages, 03825 message_link); 03826 connection->n_incoming += 1; 03827 03828 _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n", 03829 message_link->data, 03830 dbus_message_get_type (message_link->data), 03831 dbus_message_get_interface (message_link->data) ? 03832 dbus_message_get_interface (message_link->data) : 03833 "no interface", 03834 dbus_message_get_member (message_link->data) ? 03835 dbus_message_get_member (message_link->data) : 03836 "no member", 03837 dbus_message_get_signature (message_link->data), 03838 connection, connection->n_incoming); 03839 } 03840 03860 DBusMessage* 03861 dbus_connection_pop_message (DBusConnection *connection) 03862 { 03863 DBusMessage *message; 03864 DBusDispatchStatus status; 03865 03866 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME); 03867 03868 /* this is called for the side effect that it queues 03869 * up any messages from the transport 03870 */ 03871 status = dbus_connection_get_dispatch_status (connection); 03872 if (status != DBUS_DISPATCH_DATA_REMAINS) 03873 return NULL; 03874 03875 CONNECTION_LOCK (connection); 03876 _dbus_connection_acquire_dispatch (connection); 03877 HAVE_LOCK_CHECK (connection); 03878 03879 message = _dbus_connection_pop_message_unlocked (connection); 03880 03881 _dbus_verbose ("Returning popped message %p\n", message); 03882 03883 _dbus_connection_release_dispatch (connection); 03884 03885 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03886 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03887 03888 return message; 03889 } 03890 03898 static void 03899 _dbus_connection_acquire_dispatch (DBusConnection *connection) 03900 { 03901 HAVE_LOCK_CHECK (connection); 03902 03903 _dbus_connection_ref_unlocked (connection); 03904 CONNECTION_UNLOCK (connection); 03905 03906 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME); 03907 _dbus_mutex_lock (connection->dispatch_mutex); 03908 03909 while (connection->dispatch_acquired) 03910 { 03911 _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME); 03912 _dbus_condvar_wait (connection->dispatch_cond, 03913 connection->dispatch_mutex); 03914 } 03915 03916 _dbus_assert (!connection->dispatch_acquired); 03917 03918 connection->dispatch_acquired = TRUE; 03919 03920 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME); 03921 _dbus_mutex_unlock (connection->dispatch_mutex); 03922 03923 CONNECTION_LOCK (connection); 03924 _dbus_connection_unref_unlocked (connection); 03925 } 03926 03934 static void 03935 _dbus_connection_release_dispatch (DBusConnection *connection) 03936 { 03937 HAVE_LOCK_CHECK (connection); 03938 03939 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME); 03940 _dbus_mutex_lock (connection->dispatch_mutex); 03941 03942 _dbus_assert (connection->dispatch_acquired); 03943 03944 connection->dispatch_acquired = FALSE; 03945 _dbus_condvar_wake_one (connection->dispatch_cond); 03946 03947 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME); 03948 _dbus_mutex_unlock (connection->dispatch_mutex); 03949 } 03950 03951 static void 03952 _dbus_connection_failed_pop (DBusConnection *connection, 03953 DBusList *message_link) 03954 { 03955 _dbus_list_prepend_link (&connection->incoming_messages, 03956 message_link); 03957 connection->n_incoming += 1; 03958 } 03959 03960 /* Note this may be called multiple times since we don't track whether we already did it */ 03961 static void 03962 notify_disconnected_unlocked (DBusConnection *connection) 03963 { 03964 HAVE_LOCK_CHECK (connection); 03965 03966 /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected 03967 * connection from dbus_bus_get(). We make the same guarantee for 03968 * dbus_connection_open() but in a different way since we don't want to 03969 * unref right here; we instead check for connectedness before returning 03970 * the connection from the hash. 03971 */ 03972 _dbus_bus_notify_shared_connection_disconnected_unlocked (connection); 03973 03974 /* Dump the outgoing queue, we aren't going to be able to 03975 * send it now, and we'd like accessors like 03976 * dbus_connection_get_outgoing_size() to be accurate. 03977 */ 03978 if (connection->n_outgoing > 0) 03979 { 03980 DBusList *link; 03981 03982 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n", 03983 connection->n_outgoing); 03984 03985 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages))) 03986 { 03987 _dbus_connection_message_sent (connection, link->data); 03988 } 03989 } 03990 } 03991 03992 /* Note this may be called multiple times since we don't track whether we already did it */ 03993 static DBusDispatchStatus 03994 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection) 03995 { 03996 HAVE_LOCK_CHECK (connection); 03997 03998 if (connection->disconnect_message_link != NULL) 03999 { 04000 _dbus_verbose ("Sending disconnect message from %s\n", 04001 _DBUS_FUNCTION_NAME); 04002 04003 /* If we have pending calls, queue their timeouts - we want the Disconnected 04004 * to be the last message, after these timeouts. 04005 */ 04006 connection_timeout_and_complete_all_pending_calls_unlocked (connection); 04007 04008 /* We haven't sent the disconnect message already, 04009 * and all real messages have been queued up. 04010 */ 04011 _dbus_connection_queue_synthesized_message_link (connection, 04012 connection->disconnect_message_link); 04013 connection->disconnect_message_link = NULL; 04014 04015 return DBUS_DISPATCH_DATA_REMAINS; 04016 } 04017 04018 return DBUS_DISPATCH_COMPLETE; 04019 } 04020 04021 static DBusDispatchStatus 04022 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection) 04023 { 04024 HAVE_LOCK_CHECK (connection); 04025 04026 if (connection->n_incoming > 0) 04027 return DBUS_DISPATCH_DATA_REMAINS; 04028 else if (!_dbus_transport_queue_messages (connection->transport)) 04029 return DBUS_DISPATCH_NEED_MEMORY; 04030 else 04031 { 04032 DBusDispatchStatus status; 04033 dbus_bool_t is_connected; 04034 04035 status = _dbus_transport_get_dispatch_status (connection->transport); 04036 is_connected = _dbus_transport_get_is_connected (connection->transport); 04037 04038 _dbus_verbose ("dispatch status = %s is_connected = %d\n", 04039 DISPATCH_STATUS_NAME (status), is_connected); 04040 04041 if (!is_connected) 04042 { 04043 /* It's possible this would be better done by having an explicit 04044 * notification from _dbus_transport_disconnect() that would 04045 * synchronously do this, instead of waiting for the next dispatch 04046 * status check. However, probably not good to change until it causes 04047 * a problem. 04048 */ 04049 notify_disconnected_unlocked (connection); 04050 04051 /* I'm not sure this is needed; the idea is that we want to 04052 * queue the Disconnected only after we've read all the 04053 * messages, but if we're disconnected maybe we are guaranteed 04054 * to have read them all ? 04055 */ 04056 if (status == DBUS_DISPATCH_COMPLETE) 04057 status = notify_disconnected_and_dispatch_complete_unlocked (connection); 04058 } 04059 04060 if (status != DBUS_DISPATCH_COMPLETE) 04061 return status; 04062 else if (connection->n_incoming > 0) 04063 return DBUS_DISPATCH_DATA_REMAINS; 04064 else 04065 return DBUS_DISPATCH_COMPLETE; 04066 } 04067 } 04068 04069 static void 04070 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection, 04071 DBusDispatchStatus new_status) 04072 { 04073 dbus_bool_t changed; 04074 DBusDispatchStatusFunction function; 04075 void *data; 04076 04077 HAVE_LOCK_CHECK (connection); 04078 04079 _dbus_connection_ref_unlocked (connection); 04080 04081 changed = new_status != connection->last_dispatch_status; 04082 04083 connection->last_dispatch_status = new_status; 04084 04085 function = connection->dispatch_status_function; 04086 data = connection->dispatch_status_data; 04087 04088 if (connection->disconnected_message_arrived && 04089 !connection->disconnected_message_processed) 04090 { 04091 connection->disconnected_message_processed = TRUE; 04092 04093 /* this does an unref, but we have a ref 04094 * so we should not run the finalizer here 04095 * inside the lock. 04096 */ 04097 connection_forget_shared_unlocked (connection); 04098 04099 if (connection->exit_on_disconnect) 04100 { 04101 CONNECTION_UNLOCK (connection); 04102 04103 _dbus_verbose ("Exiting on Disconnected signal\n"); 04104 _dbus_exit (1); 04105 _dbus_assert_not_reached ("Call to exit() returned"); 04106 } 04107 } 04108 04109 /* We drop the lock */ 04110 CONNECTION_UNLOCK (connection); 04111 04112 if (changed && function) 04113 { 04114 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n", 04115 connection, new_status, 04116 DISPATCH_STATUS_NAME (new_status)); 04117 (* function) (connection, new_status, data); 04118 } 04119 04120 dbus_connection_unref (connection); 04121 } 04122 04148 DBusDispatchStatus 04149 dbus_connection_get_dispatch_status (DBusConnection *connection) 04150 { 04151 DBusDispatchStatus status; 04152 04153 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE); 04154 04155 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME); 04156 04157 CONNECTION_LOCK (connection); 04158 04159 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04160 04161 CONNECTION_UNLOCK (connection); 04162 04163 return status; 04164 } 04165 04169 static DBusHandlerResult 04170 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection, 04171 DBusMessage *message) 04172 { 04173 if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL) 04174 { 04175 /* This means we're letting the bus route this message */ 04176 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04177 } 04178 else if (dbus_message_is_method_call (message, 04179 DBUS_INTERFACE_PEER, 04180 "Ping")) 04181 { 04182 DBusMessage *ret; 04183 dbus_bool_t sent; 04184 04185 ret = dbus_message_new_method_return (message); 04186 if (ret == NULL) 04187 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04188 04189 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04190 04191 dbus_message_unref (ret); 04192 04193 if (!sent) 04194 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04195 04196 return DBUS_HANDLER_RESULT_HANDLED; 04197 } 04198 else if (dbus_message_is_method_call (message, 04199 DBUS_INTERFACE_PEER, 04200 "GetMachineId")) 04201 { 04202 DBusMessage *ret; 04203 dbus_bool_t sent; 04204 DBusString uuid; 04205 04206 ret = dbus_message_new_method_return (message); 04207 if (ret == NULL) 04208 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04209 04210 sent = FALSE; 04211 _dbus_string_init (&uuid); 04212 if (_dbus_get_local_machine_uuid_encoded (&uuid)) 04213 { 04214 const char *v_STRING = _dbus_string_get_const_data (&uuid); 04215 if (dbus_message_append_args (ret, 04216 DBUS_TYPE_STRING, &v_STRING, 04217 DBUS_TYPE_INVALID)) 04218 { 04219 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04220 } 04221 } 04222 _dbus_string_free (&uuid); 04223 04224 dbus_message_unref (ret); 04225 04226 if (!sent) 04227 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04228 04229 return DBUS_HANDLER_RESULT_HANDLED; 04230 } 04231 else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER)) 04232 { 04233 /* We need to bounce anything else with this interface, otherwise apps 04234 * could start extending the interface and when we added extensions 04235 * here to DBusConnection we'd break those apps. 04236 */ 04237 04238 DBusMessage *ret; 04239 dbus_bool_t sent; 04240 04241 ret = dbus_message_new_error (message, 04242 DBUS_ERROR_UNKNOWN_METHOD, 04243 "Unknown method invoked on org.freedesktop.DBus.Peer interface"); 04244 if (ret == NULL) 04245 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04246 04247 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04248 04249 dbus_message_unref (ret); 04250 04251 if (!sent) 04252 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04253 04254 return DBUS_HANDLER_RESULT_HANDLED; 04255 } 04256 else 04257 { 04258 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04259 } 04260 } 04261 04268 static DBusHandlerResult 04269 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection, 04270 DBusMessage *message) 04271 { 04272 /* We just run one filter for now but have the option to run more 04273 if the spec calls for it in the future */ 04274 04275 return _dbus_connection_peer_filter_unlocked_no_update (connection, message); 04276 } 04277 04320 DBusDispatchStatus 04321 dbus_connection_dispatch (DBusConnection *connection) 04322 { 04323 DBusMessage *message; 04324 DBusList *link, *filter_list_copy, *message_link; 04325 DBusHandlerResult result; 04326 DBusPendingCall *pending; 04327 dbus_int32_t reply_serial; 04328 DBusDispatchStatus status; 04329 04330 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE); 04331 04332 _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME); 04333 04334 CONNECTION_LOCK (connection); 04335 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04336 if (status != DBUS_DISPATCH_DATA_REMAINS) 04337 { 04338 /* unlocks and calls out to user code */ 04339 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04340 return status; 04341 } 04342 04343 /* We need to ref the connection since the callback could potentially 04344 * drop the last ref to it 04345 */ 04346 _dbus_connection_ref_unlocked (connection); 04347 04348 _dbus_connection_acquire_dispatch (connection); 04349 HAVE_LOCK_CHECK (connection); 04350 04351 message_link = _dbus_connection_pop_message_link_unlocked (connection); 04352 if (message_link == NULL) 04353 { 04354 /* another thread dispatched our stuff */ 04355 04356 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n"); 04357 04358 _dbus_connection_release_dispatch (connection); 04359 04360 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04361 04362 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04363 04364 dbus_connection_unref (connection); 04365 04366 return status; 04367 } 04368 04369 message = message_link->data; 04370 04371 _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n", 04372 message, 04373 dbus_message_get_type (message), 04374 dbus_message_get_interface (message) ? 04375 dbus_message_get_interface (message) : 04376 "no interface", 04377 dbus_message_get_member (message) ? 04378 dbus_message_get_member (message) : 04379 "no member", 04380 dbus_message_get_signature (message)); 04381 04382 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04383 04384 /* Pending call handling must be first, because if you do 04385 * dbus_connection_send_with_reply_and_block() or 04386 * dbus_pending_call_block() then no handlers/filters will be run on 04387 * the reply. We want consistent semantics in the case where we 04388 * dbus_connection_dispatch() the reply. 04389 */ 04390 04391 reply_serial = dbus_message_get_reply_serial (message); 04392 pending = _dbus_hash_table_lookup_int (connection->pending_replies, 04393 reply_serial); 04394 if (pending) 04395 { 04396 _dbus_verbose ("Dispatching a pending reply\n"); 04397 complete_pending_call_and_unlock (connection, pending, message); 04398 pending = NULL; /* it's probably unref'd */ 04399 04400 CONNECTION_LOCK (connection); 04401 _dbus_verbose ("pending call completed in dispatch\n"); 04402 result = DBUS_HANDLER_RESULT_HANDLED; 04403 goto out; 04404 } 04405 04406 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message); 04407 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04408 goto out; 04409 04410 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy)) 04411 { 04412 _dbus_connection_release_dispatch (connection); 04413 HAVE_LOCK_CHECK (connection); 04414 04415 _dbus_connection_failed_pop (connection, message_link); 04416 04417 /* unlocks and calls user code */ 04418 _dbus_connection_update_dispatch_status_and_unlock (connection, 04419 DBUS_DISPATCH_NEED_MEMORY); 04420 04421 if (pending) 04422 dbus_pending_call_unref (pending); 04423 dbus_connection_unref (connection); 04424 04425 return DBUS_DISPATCH_NEED_MEMORY; 04426 } 04427 04428 _dbus_list_foreach (&filter_list_copy, 04429 (DBusForeachFunction)_dbus_message_filter_ref, 04430 NULL); 04431 04432 /* We're still protected from dispatch() reentrancy here 04433 * since we acquired the dispatcher 04434 */ 04435 CONNECTION_UNLOCK (connection); 04436 04437 link = _dbus_list_get_first_link (&filter_list_copy); 04438 while (link != NULL) 04439 { 04440 DBusMessageFilter *filter = link->data; 04441 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link); 04442 04443 if (filter->function == NULL) 04444 { 04445 _dbus_verbose (" filter was removed in a callback function\n"); 04446 link = next; 04447 continue; 04448 } 04449 04450 _dbus_verbose (" running filter on message %p\n", message); 04451 result = (* filter->function) (connection, message, filter->user_data); 04452 04453 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04454 break; 04455 04456 link = next; 04457 } 04458 04459 _dbus_list_foreach (&filter_list_copy, 04460 (DBusForeachFunction)_dbus_message_filter_unref, 04461 NULL); 04462 _dbus_list_clear (&filter_list_copy); 04463 04464 CONNECTION_LOCK (connection); 04465 04466 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) 04467 { 04468 _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME); 04469 goto out; 04470 } 04471 else if (result == DBUS_HANDLER_RESULT_HANDLED) 04472 { 04473 _dbus_verbose ("filter handled message in dispatch\n"); 04474 goto out; 04475 } 04476 04477 /* We're still protected from dispatch() reentrancy here 04478 * since we acquired the dispatcher 04479 */ 04480 _dbus_verbose (" running object path dispatch on message %p (%d %s %s '%s')\n", 04481 message, 04482 dbus_message_get_type (message), 04483 dbus_message_get_interface (message) ? 04484 dbus_message_get_interface (message) : 04485 "no interface", 04486 dbus_message_get_member (message) ? 04487 dbus_message_get_member (message) : 04488 "no member", 04489 dbus_message_get_signature (message)); 04490 04491 HAVE_LOCK_CHECK (connection); 04492 result = _dbus_object_tree_dispatch_and_unlock (connection->objects, 04493 message); 04494 04495 CONNECTION_LOCK (connection); 04496 04497 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04498 { 04499 _dbus_verbose ("object tree handled message in dispatch\n"); 04500 goto out; 04501 } 04502 04503 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL) 04504 { 04505 DBusMessage *reply; 04506 DBusString str; 04507 DBusPreallocatedSend *preallocated; 04508 04509 _dbus_verbose (" sending error %s\n", 04510 DBUS_ERROR_UNKNOWN_METHOD); 04511 04512 if (!_dbus_string_init (&str)) 04513 { 04514 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04515 _dbus_verbose ("no memory for error string in dispatch\n"); 04516 goto out; 04517 } 04518 04519 if (!_dbus_string_append_printf (&str, 04520 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n", 04521 dbus_message_get_member (message), 04522 dbus_message_get_signature (message), 04523 dbus_message_get_interface (message))) 04524 { 04525 _dbus_string_free (&str); 04526 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04527 _dbus_verbose ("no memory for error string in dispatch\n"); 04528 goto out; 04529 } 04530 04531 reply = dbus_message_new_error (message, 04532 DBUS_ERROR_UNKNOWN_METHOD, 04533 _dbus_string_get_const_data (&str)); 04534 _dbus_string_free (&str); 04535 04536 if (reply == NULL) 04537 { 04538 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04539 _dbus_verbose ("no memory for error reply in dispatch\n"); 04540 goto out; 04541 } 04542 04543 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 04544 04545 if (preallocated == NULL) 04546 { 04547 dbus_message_unref (reply); 04548 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04549 _dbus_verbose ("no memory for error send in dispatch\n"); 04550 goto out; 04551 } 04552 04553 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated, 04554 reply, NULL); 04555 04556 dbus_message_unref (reply); 04557 04558 result = DBUS_HANDLER_RESULT_HANDLED; 04559 } 04560 04561 _dbus_verbose (" done dispatching %p (%d %s %s '%s') on connection %p\n", message, 04562 dbus_message_get_type (message), 04563 dbus_message_get_interface (message) ? 04564 dbus_message_get_interface (message) : 04565 "no interface", 04566 dbus_message_get_member (message) ? 04567 dbus_message_get_member (message) : 04568 "no member", 04569 dbus_message_get_signature (message), 04570 connection); 04571 04572 out: 04573 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) 04574 { 04575 _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME); 04576 04577 /* Put message back, and we'll start over. 04578 * Yes this means handlers must be idempotent if they 04579 * don't return HANDLED; c'est la vie. 04580 */ 04581 _dbus_connection_putback_message_link_unlocked (connection, 04582 message_link); 04583 } 04584 else 04585 { 04586 _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME); 04587 04588 _dbus_list_free_link (message_link); 04589 dbus_message_unref (message); /* don't want the message to count in max message limits 04590 * in computing dispatch status below 04591 */ 04592 } 04593 04594 _dbus_connection_release_dispatch (connection); 04595 HAVE_LOCK_CHECK (connection); 04596 04597 _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME); 04598 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04599 04600 /* unlocks and calls user code */ 04601 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04602 04603 dbus_connection_unref (connection); 04604 04605 return status; 04606 } 04607 04667 dbus_bool_t 04668 dbus_connection_set_watch_functions (DBusConnection *connection, 04669 DBusAddWatchFunction add_function, 04670 DBusRemoveWatchFunction remove_function, 04671 DBusWatchToggledFunction toggled_function, 04672 void *data, 04673 DBusFreeFunction free_data_function) 04674 { 04675 dbus_bool_t retval; 04676 DBusWatchList *watches; 04677 04678 _dbus_return_val_if_fail (connection != NULL, FALSE); 04679 04680 CONNECTION_LOCK (connection); 04681 04682 #ifndef DBUS_DISABLE_CHECKS 04683 if (connection->watches == NULL) 04684 { 04685 _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n", 04686 _DBUS_FUNCTION_NAME); 04687 return FALSE; 04688 } 04689 #endif 04690 04691 /* ref connection for slightly better reentrancy */ 04692 _dbus_connection_ref_unlocked (connection); 04693 04694 /* This can call back into user code, and we need to drop the 04695 * connection lock when it does. This is kind of a lame 04696 * way to do it. 04697 */ 04698 watches = connection->watches; 04699 connection->watches = NULL; 04700 CONNECTION_UNLOCK (connection); 04701 04702 retval = _dbus_watch_list_set_functions (watches, 04703 add_function, remove_function, 04704 toggled_function, 04705 data, free_data_function); 04706 CONNECTION_LOCK (connection); 04707 connection->watches = watches; 04708 04709 CONNECTION_UNLOCK (connection); 04710 /* drop our paranoid refcount */ 04711 dbus_connection_unref (connection); 04712 04713 return retval; 04714 } 04715 04749 dbus_bool_t 04750 dbus_connection_set_timeout_functions (DBusConnection *connection, 04751 DBusAddTimeoutFunction add_function, 04752 DBusRemoveTimeoutFunction remove_function, 04753 DBusTimeoutToggledFunction toggled_function, 04754 void *data, 04755 DBusFreeFunction free_data_function) 04756 { 04757 dbus_bool_t retval; 04758 DBusTimeoutList *timeouts; 04759 04760 _dbus_return_val_if_fail (connection != NULL, FALSE); 04761 04762 CONNECTION_LOCK (connection); 04763 04764 #ifndef DBUS_DISABLE_CHECKS 04765 if (connection->timeouts == NULL) 04766 { 04767 _dbus_warn_check_failed ("Re-entrant call to %s is not allowed\n", 04768 _DBUS_FUNCTION_NAME); 04769 return FALSE; 04770 } 04771 #endif 04772 04773 /* ref connection for slightly better reentrancy */ 04774 _dbus_connection_ref_unlocked (connection); 04775 04776 timeouts = connection->timeouts; 04777 connection->timeouts = NULL; 04778 CONNECTION_UNLOCK (connection); 04779 04780 retval = _dbus_timeout_list_set_functions (timeouts, 04781 add_function, remove_function, 04782 toggled_function, 04783 data, free_data_function); 04784 CONNECTION_LOCK (connection); 04785 connection->timeouts = timeouts; 04786 04787 CONNECTION_UNLOCK (connection); 04788 /* drop our paranoid refcount */ 04789 dbus_connection_unref (connection); 04790 04791 return retval; 04792 } 04793 04808 void 04809 dbus_connection_set_wakeup_main_function (DBusConnection *connection, 04810 DBusWakeupMainFunction wakeup_main_function, 04811 void *data, 04812 DBusFreeFunction free_data_function) 04813 { 04814 void *old_data; 04815 DBusFreeFunction old_free_data; 04816 04817 _dbus_return_if_fail (connection != NULL); 04818 04819 CONNECTION_LOCK (connection); 04820 old_data = connection->wakeup_main_data; 04821 old_free_data = connection->free_wakeup_main_data; 04822 04823 connection->wakeup_main_function = wakeup_main_function; 04824 connection->wakeup_main_data = data; 04825 connection->free_wakeup_main_data = free_data_function; 04826 04827 CONNECTION_UNLOCK (connection); 04828 04829 /* Callback outside the lock */ 04830 if (old_free_data) 04831 (*old_free_data) (old_data); 04832 } 04833 04854 void 04855 dbus_connection_set_dispatch_status_function (DBusConnection *connection, 04856 DBusDispatchStatusFunction function, 04857 void *data, 04858 DBusFreeFunction free_data_function) 04859 { 04860 void *old_data; 04861 DBusFreeFunction old_free_data; 04862 04863 _dbus_return_if_fail (connection != NULL); 04864 04865 CONNECTION_LOCK (connection); 04866 old_data = connection->dispatch_status_data; 04867 old_free_data = connection->free_dispatch_status_data; 04868 04869 connection->dispatch_status_function = function; 04870 connection->dispatch_status_data = data; 04871 connection->free_dispatch_status_data = free_data_function; 04872 04873 CONNECTION_UNLOCK (connection); 04874 04875 /* Callback outside the lock */ 04876 if (old_free_data) 04877 (*old_free_data) (old_data); 04878 } 04879 04899 dbus_bool_t 04900 dbus_connection_get_unix_fd (DBusConnection *connection, 04901 int *fd) 04902 { 04903 _dbus_return_val_if_fail (connection != NULL, FALSE); 04904 _dbus_return_val_if_fail (connection->transport != NULL, FALSE); 04905 04906 #ifdef DBUS_WIN 04907 /* FIXME do this on a lower level */ 04908 return FALSE; 04909 #endif 04910 04911 return dbus_connection_get_socket(connection, fd); 04912 } 04913 04929 dbus_bool_t 04930 dbus_connection_get_socket(DBusConnection *connection, 04931 int *fd) 04932 { 04933 dbus_bool_t retval; 04934 04935 _dbus_return_val_if_fail (connection != NULL, FALSE); 04936 _dbus_return_val_if_fail (connection->transport != NULL, FALSE); 04937 04938 CONNECTION_LOCK (connection); 04939 04940 retval = _dbus_transport_get_socket_fd (connection->transport, 04941 fd); 04942 04943 CONNECTION_UNLOCK (connection); 04944 04945 return retval; 04946 } 04947 04948 04971 dbus_bool_t 04972 dbus_connection_get_unix_user (DBusConnection *connection, 04973 unsigned long *uid) 04974 { 04975 dbus_bool_t result; 04976 04977 _dbus_return_val_if_fail (connection != NULL, FALSE); 04978 _dbus_return_val_if_fail (uid != NULL, FALSE); 04979 04980 CONNECTION_LOCK (connection); 04981 04982 if (!_dbus_transport_get_is_authenticated (connection->transport)) 04983 result = FALSE; 04984 else 04985 result = _dbus_transport_get_unix_user (connection->transport, 04986 uid); 04987 04988 #ifdef DBUS_WIN 04989 _dbus_assert (!result); 04990 #endif 04991 04992 CONNECTION_UNLOCK (connection); 04993 04994 return result; 04995 } 04996 05007 dbus_bool_t 05008 dbus_connection_get_unix_process_id (DBusConnection *connection, 05009 unsigned long *pid) 05010 { 05011 dbus_bool_t result; 05012 05013 _dbus_return_val_if_fail (connection != NULL, FALSE); 05014 _dbus_return_val_if_fail (pid != NULL, FALSE); 05015 05016 CONNECTION_LOCK (connection); 05017 05018 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05019 result = FALSE; 05020 else 05021 result = _dbus_transport_get_unix_process_id (connection->transport, 05022 pid); 05023 #ifdef DBUS_WIN 05024 _dbus_assert (!result); 05025 #endif 05026 05027 CONNECTION_UNLOCK (connection); 05028 05029 return result; 05030 } 05031 05042 dbus_bool_t 05043 dbus_connection_get_adt_audit_session_data (DBusConnection *connection, 05044 void **data, 05045 dbus_int32_t *data_size) 05046 { 05047 dbus_bool_t result; 05048 05049 _dbus_return_val_if_fail (connection != NULL, FALSE); 05050 _dbus_return_val_if_fail (data != NULL, FALSE); 05051 _dbus_return_val_if_fail (data_size != NULL, FALSE); 05052 05053 CONNECTION_LOCK (connection); 05054 05055 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05056 result = FALSE; 05057 else 05058 result = _dbus_transport_get_adt_audit_session_data (connection->transport, 05059 data, 05060 data_size); 05061 CONNECTION_UNLOCK (connection); 05062 05063 return result; 05064 } 05065 05088 void 05089 dbus_connection_set_unix_user_function (DBusConnection *connection, 05090 DBusAllowUnixUserFunction function, 05091 void *data, 05092 DBusFreeFunction free_data_function) 05093 { 05094 void *old_data = NULL; 05095 DBusFreeFunction old_free_function = NULL; 05096 05097 _dbus_return_if_fail (connection != NULL); 05098 05099 CONNECTION_LOCK (connection); 05100 _dbus_transport_set_unix_user_function (connection->transport, 05101 function, data, free_data_function, 05102 &old_data, &old_free_function); 05103 CONNECTION_UNLOCK (connection); 05104 05105 if (old_free_function != NULL) 05106 (* old_free_function) (old_data); 05107 } 05108 05140 dbus_bool_t 05141 dbus_connection_get_windows_user (DBusConnection *connection, 05142 char **windows_sid_p) 05143 { 05144 dbus_bool_t result; 05145 05146 _dbus_return_val_if_fail (connection != NULL, FALSE); 05147 _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE); 05148 05149 CONNECTION_LOCK (connection); 05150 05151 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05152 result = FALSE; 05153 else 05154 result = _dbus_transport_get_windows_user (connection->transport, 05155 windows_sid_p); 05156 05157 #ifdef DBUS_UNIX 05158 _dbus_assert (!result); 05159 #endif 05160 05161 CONNECTION_UNLOCK (connection); 05162 05163 return result; 05164 } 05165 05187 void 05188 dbus_connection_set_windows_user_function (DBusConnection *connection, 05189 DBusAllowWindowsUserFunction function, 05190 void *data, 05191 DBusFreeFunction free_data_function) 05192 { 05193 void *old_data = NULL; 05194 DBusFreeFunction old_free_function = NULL; 05195 05196 _dbus_return_if_fail (connection != NULL); 05197 05198 CONNECTION_LOCK (connection); 05199 _dbus_transport_set_windows_user_function (connection->transport, 05200 function, data, free_data_function, 05201 &old_data, &old_free_function); 05202 CONNECTION_UNLOCK (connection); 05203 05204 if (old_free_function != NULL) 05205 (* old_free_function) (old_data); 05206 } 05207 05234 void 05235 dbus_connection_set_allow_anonymous (DBusConnection *connection, 05236 dbus_bool_t value) 05237 { 05238 _dbus_return_if_fail (connection != NULL); 05239 05240 CONNECTION_LOCK (connection); 05241 _dbus_transport_set_allow_anonymous (connection->transport, value); 05242 CONNECTION_UNLOCK (connection); 05243 } 05244 05262 void 05263 dbus_connection_set_route_peer_messages (DBusConnection *connection, 05264 dbus_bool_t value) 05265 { 05266 _dbus_return_if_fail (connection != NULL); 05267 05268 CONNECTION_LOCK (connection); 05269 connection->route_peer_messages = TRUE; 05270 CONNECTION_UNLOCK (connection); 05271 } 05272 05294 dbus_bool_t 05295 dbus_connection_add_filter (DBusConnection *connection, 05296 DBusHandleMessageFunction function, 05297 void *user_data, 05298 DBusFreeFunction free_data_function) 05299 { 05300 DBusMessageFilter *filter; 05301 05302 _dbus_return_val_if_fail (connection != NULL, FALSE); 05303 _dbus_return_val_if_fail (function != NULL, FALSE); 05304 05305 filter = dbus_new0 (DBusMessageFilter, 1); 05306 if (filter == NULL) 05307 return FALSE; 05308 05309 filter->refcount.value = 1; 05310 05311 CONNECTION_LOCK (connection); 05312 05313 if (!_dbus_list_append (&connection->filter_list, 05314 filter)) 05315 { 05316 _dbus_message_filter_unref (filter); 05317 CONNECTION_UNLOCK (connection); 05318 return FALSE; 05319 } 05320 05321 /* Fill in filter after all memory allocated, 05322 * so we don't run the free_user_data_function 05323 * if the add_filter() fails 05324 */ 05325 05326 filter->function = function; 05327 filter->user_data = user_data; 05328 filter->free_user_data_function = free_data_function; 05329 05330 CONNECTION_UNLOCK (connection); 05331 return TRUE; 05332 } 05333 05346 void 05347 dbus_connection_remove_filter (DBusConnection *connection, 05348 DBusHandleMessageFunction function, 05349 void *user_data) 05350 { 05351 DBusList *link; 05352 DBusMessageFilter *filter; 05353 05354 _dbus_return_if_fail (connection != NULL); 05355 _dbus_return_if_fail (function != NULL); 05356 05357 CONNECTION_LOCK (connection); 05358 05359 filter = NULL; 05360 05361 link = _dbus_list_get_last_link (&connection->filter_list); 05362 while (link != NULL) 05363 { 05364 filter = link->data; 05365 05366 if (filter->function == function && 05367 filter->user_data == user_data) 05368 { 05369 _dbus_list_remove_link (&connection->filter_list, link); 05370 filter->function = NULL; 05371 05372 break; 05373 } 05374 05375 link = _dbus_list_get_prev_link (&connection->filter_list, link); 05376 filter = NULL; 05377 } 05378 05379 CONNECTION_UNLOCK (connection); 05380 05381 #ifndef DBUS_DISABLE_CHECKS 05382 if (filter == NULL) 05383 { 05384 _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n", 05385 function, user_data); 05386 return; 05387 } 05388 #endif 05389 05390 /* Call application code */ 05391 if (filter->free_user_data_function) 05392 (* filter->free_user_data_function) (filter->user_data); 05393 05394 filter->free_user_data_function = NULL; 05395 filter->user_data = NULL; 05396 05397 _dbus_message_filter_unref (filter); 05398 } 05399 05412 dbus_bool_t 05413 dbus_connection_try_register_object_path (DBusConnection *connection, 05414 const char *path, 05415 const DBusObjectPathVTable *vtable, 05416 void *user_data, 05417 DBusError *error) 05418 { 05419 char **decomposed_path; 05420 dbus_bool_t retval; 05421 05422 _dbus_return_val_if_fail (connection != NULL, FALSE); 05423 _dbus_return_val_if_fail (path != NULL, FALSE); 05424 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05425 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05426 05427 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05428 return FALSE; 05429 05430 CONNECTION_LOCK (connection); 05431 05432 retval = _dbus_object_tree_register (connection->objects, 05433 FALSE, 05434 (const char **) decomposed_path, vtable, 05435 user_data, error); 05436 05437 CONNECTION_UNLOCK (connection); 05438 05439 dbus_free_string_array (decomposed_path); 05440 05441 return retval; 05442 } 05443 05458 dbus_bool_t 05459 dbus_connection_register_object_path (DBusConnection *connection, 05460 const char *path, 05461 const DBusObjectPathVTable *vtable, 05462 void *user_data) 05463 { 05464 char **decomposed_path; 05465 dbus_bool_t retval; 05466 DBusError error = DBUS_ERROR_INIT; 05467 05468 _dbus_return_val_if_fail (connection != NULL, FALSE); 05469 _dbus_return_val_if_fail (path != NULL, FALSE); 05470 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05471 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05472 05473 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05474 return FALSE; 05475 05476 CONNECTION_LOCK (connection); 05477 05478 retval = _dbus_object_tree_register (connection->objects, 05479 FALSE, 05480 (const char **) decomposed_path, vtable, 05481 user_data, &error); 05482 05483 CONNECTION_UNLOCK (connection); 05484 05485 dbus_free_string_array (decomposed_path); 05486 05487 if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE)) 05488 { 05489 _dbus_warn ("%s\n", error.message); 05490 dbus_error_free (&error); 05491 return FALSE; 05492 } 05493 05494 return retval; 05495 } 05496 05511 dbus_bool_t 05512 dbus_connection_try_register_fallback (DBusConnection *connection, 05513 const char *path, 05514 const DBusObjectPathVTable *vtable, 05515 void *user_data, 05516 DBusError *error) 05517 { 05518 char **decomposed_path; 05519 dbus_bool_t retval; 05520 05521 _dbus_return_val_if_fail (connection != NULL, FALSE); 05522 _dbus_return_val_if_fail (path != NULL, FALSE); 05523 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05524 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05525 05526 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05527 return FALSE; 05528 05529 CONNECTION_LOCK (connection); 05530 05531 retval = _dbus_object_tree_register (connection->objects, 05532 TRUE, 05533 (const char **) decomposed_path, vtable, 05534 user_data, error); 05535 05536 CONNECTION_UNLOCK (connection); 05537 05538 dbus_free_string_array (decomposed_path); 05539 05540 return retval; 05541 } 05542 05559 dbus_bool_t 05560 dbus_connection_register_fallback (DBusConnection *connection, 05561 const char *path, 05562 const DBusObjectPathVTable *vtable, 05563 void *user_data) 05564 { 05565 char **decomposed_path; 05566 dbus_bool_t retval; 05567 DBusError error = DBUS_ERROR_INIT; 05568 05569 _dbus_return_val_if_fail (connection != NULL, FALSE); 05570 _dbus_return_val_if_fail (path != NULL, FALSE); 05571 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05572 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05573 05574 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05575 return FALSE; 05576 05577 CONNECTION_LOCK (connection); 05578 05579 retval = _dbus_object_tree_register (connection->objects, 05580 TRUE, 05581 (const char **) decomposed_path, vtable, 05582 user_data, &error); 05583 05584 CONNECTION_UNLOCK (connection); 05585 05586 dbus_free_string_array (decomposed_path); 05587 05588 if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE)) 05589 { 05590 _dbus_warn ("%s\n", error.message); 05591 dbus_error_free (&error); 05592 return FALSE; 05593 } 05594 05595 return retval; 05596 } 05597 05607 dbus_bool_t 05608 dbus_connection_unregister_object_path (DBusConnection *connection, 05609 const char *path) 05610 { 05611 char **decomposed_path; 05612 05613 _dbus_return_val_if_fail (connection != NULL, FALSE); 05614 _dbus_return_val_if_fail (path != NULL, FALSE); 05615 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05616 05617 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05618 return FALSE; 05619 05620 CONNECTION_LOCK (connection); 05621 05622 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path); 05623 05624 dbus_free_string_array (decomposed_path); 05625 05626 return TRUE; 05627 } 05628 05639 dbus_bool_t 05640 dbus_connection_get_object_path_data (DBusConnection *connection, 05641 const char *path, 05642 void **data_p) 05643 { 05644 char **decomposed_path; 05645 05646 _dbus_return_val_if_fail (connection != NULL, FALSE); 05647 _dbus_return_val_if_fail (path != NULL, FALSE); 05648 _dbus_return_val_if_fail (data_p != NULL, FALSE); 05649 05650 *data_p = NULL; 05651 05652 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05653 return FALSE; 05654 05655 CONNECTION_LOCK (connection); 05656 05657 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path); 05658 05659 CONNECTION_UNLOCK (connection); 05660 05661 dbus_free_string_array (decomposed_path); 05662 05663 return TRUE; 05664 } 05665 05676 dbus_bool_t 05677 dbus_connection_list_registered (DBusConnection *connection, 05678 const char *parent_path, 05679 char ***child_entries) 05680 { 05681 char **decomposed_path; 05682 dbus_bool_t retval; 05683 _dbus_return_val_if_fail (connection != NULL, FALSE); 05684 _dbus_return_val_if_fail (parent_path != NULL, FALSE); 05685 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE); 05686 _dbus_return_val_if_fail (child_entries != NULL, FALSE); 05687 05688 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL)) 05689 return FALSE; 05690 05691 CONNECTION_LOCK (connection); 05692 05693 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects, 05694 (const char **) decomposed_path, 05695 child_entries); 05696 dbus_free_string_array (decomposed_path); 05697 05698 return retval; 05699 } 05700 05701 static DBusDataSlotAllocator slot_allocator; 05702 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots); 05703 05718 dbus_bool_t 05719 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p) 05720 { 05721 return _dbus_data_slot_allocator_alloc (&slot_allocator, 05722 &_DBUS_LOCK_NAME (connection_slots), 05723 slot_p); 05724 } 05725 05737 void 05738 dbus_connection_free_data_slot (dbus_int32_t *slot_p) 05739 { 05740 _dbus_return_if_fail (*slot_p >= 0); 05741 05742 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 05743 } 05744 05758 dbus_bool_t 05759 dbus_connection_set_data (DBusConnection *connection, 05760 dbus_int32_t slot, 05761 void *data, 05762 DBusFreeFunction free_data_func) 05763 { 05764 DBusFreeFunction old_free_func; 05765 void *old_data; 05766 dbus_bool_t retval; 05767 05768 _dbus_return_val_if_fail (connection != NULL, FALSE); 05769 _dbus_return_val_if_fail (slot >= 0, FALSE); 05770 05771 CONNECTION_LOCK (connection); 05772 05773 retval = _dbus_data_slot_list_set (&slot_allocator, 05774 &connection->slot_list, 05775 slot, data, free_data_func, 05776 &old_free_func, &old_data); 05777 05778 CONNECTION_UNLOCK (connection); 05779 05780 if (retval) 05781 { 05782 /* Do the actual free outside the connection lock */ 05783 if (old_free_func) 05784 (* old_free_func) (old_data); 05785 } 05786 05787 return retval; 05788 } 05789 05798 void* 05799 dbus_connection_get_data (DBusConnection *connection, 05800 dbus_int32_t slot) 05801 { 05802 void *res; 05803 05804 _dbus_return_val_if_fail (connection != NULL, NULL); 05805 05806 CONNECTION_LOCK (connection); 05807 05808 res = _dbus_data_slot_list_get (&slot_allocator, 05809 &connection->slot_list, 05810 slot); 05811 05812 CONNECTION_UNLOCK (connection); 05813 05814 return res; 05815 } 05816 05823 void 05824 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe) 05825 { 05826 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE; 05827 } 05828 05837 void 05838 dbus_connection_set_max_message_size (DBusConnection *connection, 05839 long size) 05840 { 05841 _dbus_return_if_fail (connection != NULL); 05842 05843 CONNECTION_LOCK (connection); 05844 _dbus_transport_set_max_message_size (connection->transport, 05845 size); 05846 CONNECTION_UNLOCK (connection); 05847 } 05848 05855 long 05856 dbus_connection_get_max_message_size (DBusConnection *connection) 05857 { 05858 long res; 05859 05860 _dbus_return_val_if_fail (connection != NULL, 0); 05861 05862 CONNECTION_LOCK (connection); 05863 res = _dbus_transport_get_max_message_size (connection->transport); 05864 CONNECTION_UNLOCK (connection); 05865 return res; 05866 } 05867 05893 void 05894 dbus_connection_set_max_received_size (DBusConnection *connection, 05895 long size) 05896 { 05897 _dbus_return_if_fail (connection != NULL); 05898 05899 CONNECTION_LOCK (connection); 05900 _dbus_transport_set_max_received_size (connection->transport, 05901 size); 05902 CONNECTION_UNLOCK (connection); 05903 } 05904 05911 long 05912 dbus_connection_get_max_received_size (DBusConnection *connection) 05913 { 05914 long res; 05915 05916 _dbus_return_val_if_fail (connection != NULL, 0); 05917 05918 CONNECTION_LOCK (connection); 05919 res = _dbus_transport_get_max_received_size (connection->transport); 05920 CONNECTION_UNLOCK (connection); 05921 return res; 05922 } 05923 05934 long 05935 dbus_connection_get_outgoing_size (DBusConnection *connection) 05936 { 05937 long res; 05938 05939 _dbus_return_val_if_fail (connection != NULL, 0); 05940 05941 CONNECTION_LOCK (connection); 05942 res = _dbus_counter_get_value (connection->outgoing_counter); 05943 CONNECTION_UNLOCK (connection); 05944 return res; 05945 } 05946