D-Bus 1.6.12
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-connection.c DBusConnection object 00003 * 00004 * Copyright (C) 2002-2006 Red Hat Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 * 00022 */ 00023 00024 #include <config.h> 00025 #include "dbus-shared.h" 00026 #include "dbus-connection.h" 00027 #include "dbus-list.h" 00028 #include "dbus-timeout.h" 00029 #include "dbus-transport.h" 00030 #include "dbus-watch.h" 00031 #include "dbus-connection-internal.h" 00032 #include "dbus-pending-call-internal.h" 00033 #include "dbus-list.h" 00034 #include "dbus-hash.h" 00035 #include "dbus-message-internal.h" 00036 #include "dbus-message-private.h" 00037 #include "dbus-threads.h" 00038 #include "dbus-protocol.h" 00039 #include "dbus-dataslot.h" 00040 #include "dbus-string.h" 00041 #include "dbus-signature.h" 00042 #include "dbus-pending-call.h" 00043 #include "dbus-object-tree.h" 00044 #include "dbus-threads-internal.h" 00045 #include "dbus-bus.h" 00046 #include "dbus-marshal-basic.h" 00047 00048 #ifdef DBUS_DISABLE_CHECKS 00049 #define TOOK_LOCK_CHECK(connection) 00050 #define RELEASING_LOCK_CHECK(connection) 00051 #define HAVE_LOCK_CHECK(connection) 00052 #else 00053 #define TOOK_LOCK_CHECK(connection) do { \ 00054 _dbus_assert (!(connection)->have_connection_lock); \ 00055 (connection)->have_connection_lock = TRUE; \ 00056 } while (0) 00057 #define RELEASING_LOCK_CHECK(connection) do { \ 00058 _dbus_assert ((connection)->have_connection_lock); \ 00059 (connection)->have_connection_lock = FALSE; \ 00060 } while (0) 00061 #define HAVE_LOCK_CHECK(connection) _dbus_assert ((connection)->have_connection_lock) 00062 /* A "DO_NOT_HAVE_LOCK_CHECK" is impossible since we need the lock to check the flag */ 00063 #endif 00064 00065 #define TRACE_LOCKS 1 00066 00067 #define CONNECTION_LOCK(connection) do { \ 00068 if (TRACE_LOCKS) { _dbus_verbose ("LOCK\n"); } \ 00069 _dbus_rmutex_lock ((connection)->mutex); \ 00070 TOOK_LOCK_CHECK (connection); \ 00071 } while (0) 00072 00073 #define CONNECTION_UNLOCK(connection) _dbus_connection_unlock (connection) 00074 00075 #define SLOTS_LOCK(connection) do { \ 00076 _dbus_rmutex_lock ((connection)->slot_mutex); \ 00077 } while (0) 00078 00079 #define SLOTS_UNLOCK(connection) do { \ 00080 _dbus_rmutex_unlock ((connection)->slot_mutex); \ 00081 } while (0) 00082 00083 #define DISPATCH_STATUS_NAME(s) \ 00084 ((s) == DBUS_DISPATCH_COMPLETE ? "complete" : \ 00085 (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \ 00086 (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" : \ 00087 "???") 00088 00206 #ifdef DBUS_ENABLE_VERBOSE_MODE 00207 static void 00208 _dbus_connection_trace_ref (DBusConnection *connection, 00209 int old_refcount, 00210 int new_refcount, 00211 const char *why) 00212 { 00213 static int enabled = -1; 00214 00215 _dbus_trace_ref ("DBusConnection", connection, old_refcount, new_refcount, 00216 why, "DBUS_CONNECTION_TRACE", &enabled); 00217 } 00218 #else 00219 #define _dbus_connection_trace_ref(c,o,n,w) \ 00220 do \ 00221 {\ 00222 (void) (o); \ 00223 (void) (n); \ 00224 } while (0) 00225 #endif 00226 00230 typedef struct DBusMessageFilter DBusMessageFilter; 00231 00235 struct DBusMessageFilter 00236 { 00237 DBusAtomic refcount; 00238 DBusHandleMessageFunction function; 00239 void *user_data; 00240 DBusFreeFunction free_user_data_function; 00241 }; 00242 00243 00247 struct DBusPreallocatedSend 00248 { 00249 DBusConnection *connection; 00250 DBusList *queue_link; 00251 DBusList *counter_link; 00252 }; 00253 00254 #if HAVE_DECL_MSG_NOSIGNAL 00255 static dbus_bool_t _dbus_modify_sigpipe = FALSE; 00256 #else 00257 static dbus_bool_t _dbus_modify_sigpipe = TRUE; 00258 #endif 00259 00263 struct DBusConnection 00264 { 00265 DBusAtomic refcount; 00267 DBusRMutex *mutex; 00269 DBusCMutex *dispatch_mutex; 00270 DBusCondVar *dispatch_cond; 00271 DBusCMutex *io_path_mutex; 00272 DBusCondVar *io_path_cond; 00274 DBusList *outgoing_messages; 00275 DBusList *incoming_messages; 00276 DBusList *expired_messages; 00278 DBusMessage *message_borrowed; 00282 int n_outgoing; 00283 int n_incoming; 00285 DBusCounter *outgoing_counter; 00287 DBusTransport *transport; 00288 DBusWatchList *watches; 00289 DBusTimeoutList *timeouts; 00291 DBusList *filter_list; 00293 DBusRMutex *slot_mutex; 00294 DBusDataSlotList slot_list; 00296 DBusHashTable *pending_replies; 00298 dbus_uint32_t client_serial; 00299 DBusList *disconnect_message_link; 00301 DBusWakeupMainFunction wakeup_main_function; 00302 void *wakeup_main_data; 00303 DBusFreeFunction free_wakeup_main_data; 00305 DBusDispatchStatusFunction dispatch_status_function; 00306 void *dispatch_status_data; 00307 DBusFreeFunction free_dispatch_status_data; 00309 DBusDispatchStatus last_dispatch_status; 00311 DBusObjectTree *objects; 00313 char *server_guid; 00315 /* These two MUST be bools and not bitfields, because they are protected by a separate lock 00316 * from connection->mutex and all bitfields in a word have to be read/written together. 00317 * So you can't have a different lock for different bitfields in the same word. 00318 */ 00319 dbus_bool_t dispatch_acquired; 00320 dbus_bool_t io_path_acquired; 00322 unsigned int shareable : 1; 00324 unsigned int exit_on_disconnect : 1; 00326 unsigned int route_peer_messages : 1; 00328 unsigned int disconnected_message_arrived : 1; 00332 unsigned int disconnected_message_processed : 1; 00336 #ifndef DBUS_DISABLE_CHECKS 00337 unsigned int have_connection_lock : 1; 00338 #endif 00339 00340 #ifndef DBUS_DISABLE_CHECKS 00341 int generation; 00342 #endif 00343 }; 00344 00345 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection); 00346 static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection, 00347 DBusDispatchStatus new_status); 00348 static void _dbus_connection_last_unref (DBusConnection *connection); 00349 static void _dbus_connection_acquire_dispatch (DBusConnection *connection); 00350 static void _dbus_connection_release_dispatch (DBusConnection *connection); 00351 static DBusDispatchStatus _dbus_connection_flush_unlocked (DBusConnection *connection); 00352 static void _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection); 00353 static dbus_bool_t _dbus_connection_get_is_connected_unlocked (DBusConnection *connection); 00354 static dbus_bool_t _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection, 00355 dbus_uint32_t client_serial); 00356 00357 static DBusMessageFilter * 00358 _dbus_message_filter_ref (DBusMessageFilter *filter) 00359 { 00360 #ifdef DBUS_DISABLE_ASSERT 00361 _dbus_atomic_inc (&filter->refcount); 00362 #else 00363 dbus_int32_t old_value; 00364 00365 old_value = _dbus_atomic_inc (&filter->refcount); 00366 _dbus_assert (old_value > 0); 00367 #endif 00368 00369 return filter; 00370 } 00371 00372 static void 00373 _dbus_message_filter_unref (DBusMessageFilter *filter) 00374 { 00375 dbus_int32_t old_value; 00376 00377 old_value = _dbus_atomic_dec (&filter->refcount); 00378 _dbus_assert (old_value > 0); 00379 00380 if (old_value == 1) 00381 { 00382 if (filter->free_user_data_function) 00383 (* filter->free_user_data_function) (filter->user_data); 00384 00385 dbus_free (filter); 00386 } 00387 } 00388 00394 void 00395 _dbus_connection_lock (DBusConnection *connection) 00396 { 00397 CONNECTION_LOCK (connection); 00398 } 00399 00405 void 00406 _dbus_connection_unlock (DBusConnection *connection) 00407 { 00408 DBusList *expired_messages; 00409 DBusList *iter; 00410 00411 if (TRACE_LOCKS) 00412 { 00413 _dbus_verbose ("UNLOCK\n"); 00414 } 00415 00416 /* If we had messages that expired (fell off the incoming or outgoing 00417 * queues) while we were locked, actually release them now */ 00418 expired_messages = connection->expired_messages; 00419 connection->expired_messages = NULL; 00420 00421 RELEASING_LOCK_CHECK (connection); 00422 _dbus_rmutex_unlock (connection->mutex); 00423 00424 for (iter = _dbus_list_pop_first_link (&expired_messages); 00425 iter != NULL; 00426 iter = _dbus_list_pop_first_link (&expired_messages)) 00427 { 00428 DBusMessage *message = iter->data; 00429 00430 dbus_message_unref (message); 00431 _dbus_list_free_link (iter); 00432 } 00433 } 00434 00442 static void 00443 _dbus_connection_wakeup_mainloop (DBusConnection *connection) 00444 { 00445 if (connection->wakeup_main_function) 00446 (*connection->wakeup_main_function) (connection->wakeup_main_data); 00447 } 00448 00449 #ifdef DBUS_BUILD_TESTS 00450 00462 void 00463 _dbus_connection_test_get_locks (DBusConnection *connection, 00464 DBusMutex **mutex_loc, 00465 DBusMutex **dispatch_mutex_loc, 00466 DBusMutex **io_path_mutex_loc, 00467 DBusCondVar **dispatch_cond_loc, 00468 DBusCondVar **io_path_cond_loc) 00469 { 00470 *mutex_loc = (DBusMutex *) connection->mutex; 00471 *dispatch_mutex_loc = (DBusMutex *) connection->dispatch_mutex; 00472 *io_path_mutex_loc = (DBusMutex *) connection->io_path_mutex; 00473 *dispatch_cond_loc = connection->dispatch_cond; 00474 *io_path_cond_loc = connection->io_path_cond; 00475 } 00476 #endif 00477 00486 void 00487 _dbus_connection_queue_received_message_link (DBusConnection *connection, 00488 DBusList *link) 00489 { 00490 DBusPendingCall *pending; 00491 dbus_uint32_t reply_serial; 00492 DBusMessage *message; 00493 00494 _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport)); 00495 00496 _dbus_list_append_link (&connection->incoming_messages, 00497 link); 00498 message = link->data; 00499 00500 /* If this is a reply we're waiting on, remove timeout for it */ 00501 reply_serial = dbus_message_get_reply_serial (message); 00502 if (reply_serial != 0) 00503 { 00504 pending = _dbus_hash_table_lookup_int (connection->pending_replies, 00505 reply_serial); 00506 if (pending != NULL) 00507 { 00508 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 00509 _dbus_connection_remove_timeout_unlocked (connection, 00510 _dbus_pending_call_get_timeout_unlocked (pending)); 00511 00512 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 00513 } 00514 } 00515 00516 00517 00518 connection->n_incoming += 1; 00519 00520 _dbus_connection_wakeup_mainloop (connection); 00521 00522 _dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n", 00523 message, 00524 dbus_message_type_to_string (dbus_message_get_type (message)), 00525 dbus_message_get_path (message) ? 00526 dbus_message_get_path (message) : 00527 "no path", 00528 dbus_message_get_interface (message) ? 00529 dbus_message_get_interface (message) : 00530 "no interface", 00531 dbus_message_get_member (message) ? 00532 dbus_message_get_member (message) : 00533 "no member", 00534 dbus_message_get_signature (message), 00535 dbus_message_get_reply_serial (message), 00536 connection, 00537 connection->n_incoming); 00538 00539 _dbus_message_trace_ref (message, -1, -1, 00540 "_dbus_conection_queue_received_message_link"); 00541 } 00542 00551 void 00552 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection, 00553 DBusList *link) 00554 { 00555 HAVE_LOCK_CHECK (connection); 00556 00557 _dbus_list_append_link (&connection->incoming_messages, link); 00558 00559 connection->n_incoming += 1; 00560 00561 _dbus_connection_wakeup_mainloop (connection); 00562 00563 _dbus_message_trace_ref (link->data, -1, -1, 00564 "_dbus_connection_queue_synthesized_message_link"); 00565 00566 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n", 00567 link->data, connection, connection->n_incoming); 00568 } 00569 00570 00578 dbus_bool_t 00579 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection) 00580 { 00581 HAVE_LOCK_CHECK (connection); 00582 return connection->outgoing_messages != NULL; 00583 } 00584 00594 dbus_bool_t 00595 dbus_connection_has_messages_to_send (DBusConnection *connection) 00596 { 00597 dbus_bool_t v; 00598 00599 _dbus_return_val_if_fail (connection != NULL, FALSE); 00600 00601 CONNECTION_LOCK (connection); 00602 v = _dbus_connection_has_messages_to_send_unlocked (connection); 00603 CONNECTION_UNLOCK (connection); 00604 00605 return v; 00606 } 00607 00615 DBusMessage* 00616 _dbus_connection_get_message_to_send (DBusConnection *connection) 00617 { 00618 HAVE_LOCK_CHECK (connection); 00619 00620 return _dbus_list_get_last (&connection->outgoing_messages); 00621 } 00622 00631 void 00632 _dbus_connection_message_sent_unlocked (DBusConnection *connection, 00633 DBusMessage *message) 00634 { 00635 DBusList *link; 00636 00637 HAVE_LOCK_CHECK (connection); 00638 00639 /* This can be called before we even complete authentication, since 00640 * it's called on disconnect to clean up the outgoing queue. 00641 * It's also called as we successfully send each message. 00642 */ 00643 00644 link = _dbus_list_get_last_link (&connection->outgoing_messages); 00645 _dbus_assert (link != NULL); 00646 _dbus_assert (link->data == message); 00647 00648 _dbus_list_unlink (&connection->outgoing_messages, 00649 link); 00650 _dbus_list_prepend_link (&connection->expired_messages, link); 00651 00652 connection->n_outgoing -= 1; 00653 00654 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n", 00655 message, 00656 dbus_message_type_to_string (dbus_message_get_type (message)), 00657 dbus_message_get_path (message) ? 00658 dbus_message_get_path (message) : 00659 "no path", 00660 dbus_message_get_interface (message) ? 00661 dbus_message_get_interface (message) : 00662 "no interface", 00663 dbus_message_get_member (message) ? 00664 dbus_message_get_member (message) : 00665 "no member", 00666 dbus_message_get_signature (message), 00667 connection, connection->n_outgoing); 00668 00669 /* It's OK that in principle we call the notify function, because for the 00670 * outgoing limit, there isn't one */ 00671 _dbus_message_remove_counter (message, connection->outgoing_counter); 00672 00673 /* The message will actually be unreffed when we unlock */ 00674 } 00675 00677 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list, 00678 DBusWatch *watch); 00680 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list, 00681 DBusWatch *watch); 00683 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list, 00684 DBusWatch *watch, 00685 dbus_bool_t enabled); 00686 00687 static dbus_bool_t 00688 protected_change_watch (DBusConnection *connection, 00689 DBusWatch *watch, 00690 DBusWatchAddFunction add_function, 00691 DBusWatchRemoveFunction remove_function, 00692 DBusWatchToggleFunction toggle_function, 00693 dbus_bool_t enabled) 00694 { 00695 dbus_bool_t retval; 00696 00697 HAVE_LOCK_CHECK (connection); 00698 00699 /* The original purpose of protected_change_watch() was to hold a 00700 * ref on the connection while dropping the connection lock, then 00701 * calling out to the app. This was a broken hack that did not 00702 * work, since the connection was in a hosed state (no WatchList 00703 * field) while calling out. 00704 * 00705 * So for now we'll just keep the lock while calling out. This means 00706 * apps are not allowed to call DBusConnection methods inside a 00707 * watch function or they will deadlock. 00708 * 00709 * The "real fix" is to use the _and_unlock() pattern found 00710 * elsewhere in the code, to defer calling out to the app until 00711 * we're about to drop locks and return flow of control to the app 00712 * anyway. 00713 * 00714 * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144 00715 */ 00716 00717 if (connection->watches) 00718 { 00719 if (add_function) 00720 retval = (* add_function) (connection->watches, watch); 00721 else if (remove_function) 00722 { 00723 retval = TRUE; 00724 (* remove_function) (connection->watches, watch); 00725 } 00726 else 00727 { 00728 retval = TRUE; 00729 (* toggle_function) (connection->watches, watch, enabled); 00730 } 00731 return retval; 00732 } 00733 else 00734 return FALSE; 00735 } 00736 00737 00749 dbus_bool_t 00750 _dbus_connection_add_watch_unlocked (DBusConnection *connection, 00751 DBusWatch *watch) 00752 { 00753 return protected_change_watch (connection, watch, 00754 _dbus_watch_list_add_watch, 00755 NULL, NULL, FALSE); 00756 } 00757 00767 void 00768 _dbus_connection_remove_watch_unlocked (DBusConnection *connection, 00769 DBusWatch *watch) 00770 { 00771 protected_change_watch (connection, watch, 00772 NULL, 00773 _dbus_watch_list_remove_watch, 00774 NULL, FALSE); 00775 } 00776 00787 void 00788 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection, 00789 DBusWatch *watch, 00790 dbus_bool_t enabled) 00791 { 00792 _dbus_assert (watch != NULL); 00793 00794 protected_change_watch (connection, watch, 00795 NULL, NULL, 00796 _dbus_watch_list_toggle_watch, 00797 enabled); 00798 } 00799 00801 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list, 00802 DBusTimeout *timeout); 00804 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list, 00805 DBusTimeout *timeout); 00807 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list, 00808 DBusTimeout *timeout, 00809 dbus_bool_t enabled); 00810 00811 static dbus_bool_t 00812 protected_change_timeout (DBusConnection *connection, 00813 DBusTimeout *timeout, 00814 DBusTimeoutAddFunction add_function, 00815 DBusTimeoutRemoveFunction remove_function, 00816 DBusTimeoutToggleFunction toggle_function, 00817 dbus_bool_t enabled) 00818 { 00819 dbus_bool_t retval; 00820 00821 HAVE_LOCK_CHECK (connection); 00822 00823 /* The original purpose of protected_change_timeout() was to hold a 00824 * ref on the connection while dropping the connection lock, then 00825 * calling out to the app. This was a broken hack that did not 00826 * work, since the connection was in a hosed state (no TimeoutList 00827 * field) while calling out. 00828 * 00829 * So for now we'll just keep the lock while calling out. This means 00830 * apps are not allowed to call DBusConnection methods inside a 00831 * timeout function or they will deadlock. 00832 * 00833 * The "real fix" is to use the _and_unlock() pattern found 00834 * elsewhere in the code, to defer calling out to the app until 00835 * we're about to drop locks and return flow of control to the app 00836 * anyway. 00837 * 00838 * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144 00839 */ 00840 00841 if (connection->timeouts) 00842 { 00843 if (add_function) 00844 retval = (* add_function) (connection->timeouts, timeout); 00845 else if (remove_function) 00846 { 00847 retval = TRUE; 00848 (* remove_function) (connection->timeouts, timeout); 00849 } 00850 else 00851 { 00852 retval = TRUE; 00853 (* toggle_function) (connection->timeouts, timeout, enabled); 00854 } 00855 return retval; 00856 } 00857 else 00858 return FALSE; 00859 } 00860 00873 dbus_bool_t 00874 _dbus_connection_add_timeout_unlocked (DBusConnection *connection, 00875 DBusTimeout *timeout) 00876 { 00877 return protected_change_timeout (connection, timeout, 00878 _dbus_timeout_list_add_timeout, 00879 NULL, NULL, FALSE); 00880 } 00881 00891 void 00892 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection, 00893 DBusTimeout *timeout) 00894 { 00895 protected_change_timeout (connection, timeout, 00896 NULL, 00897 _dbus_timeout_list_remove_timeout, 00898 NULL, FALSE); 00899 } 00900 00911 void 00912 _dbus_connection_toggle_timeout_unlocked (DBusConnection *connection, 00913 DBusTimeout *timeout, 00914 dbus_bool_t enabled) 00915 { 00916 protected_change_timeout (connection, timeout, 00917 NULL, NULL, 00918 _dbus_timeout_list_toggle_timeout, 00919 enabled); 00920 } 00921 00922 static dbus_bool_t 00923 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection, 00924 DBusPendingCall *pending) 00925 { 00926 dbus_uint32_t reply_serial; 00927 DBusTimeout *timeout; 00928 00929 HAVE_LOCK_CHECK (connection); 00930 00931 reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending); 00932 00933 _dbus_assert (reply_serial != 0); 00934 00935 timeout = _dbus_pending_call_get_timeout_unlocked (pending); 00936 00937 if (timeout) 00938 { 00939 if (!_dbus_connection_add_timeout_unlocked (connection, timeout)) 00940 return FALSE; 00941 00942 if (!_dbus_hash_table_insert_int (connection->pending_replies, 00943 reply_serial, 00944 pending)) 00945 { 00946 _dbus_connection_remove_timeout_unlocked (connection, timeout); 00947 00948 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 00949 HAVE_LOCK_CHECK (connection); 00950 return FALSE; 00951 } 00952 00953 _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE); 00954 } 00955 else 00956 { 00957 if (!_dbus_hash_table_insert_int (connection->pending_replies, 00958 reply_serial, 00959 pending)) 00960 { 00961 HAVE_LOCK_CHECK (connection); 00962 return FALSE; 00963 } 00964 } 00965 00966 _dbus_pending_call_ref_unlocked (pending); 00967 00968 HAVE_LOCK_CHECK (connection); 00969 00970 return TRUE; 00971 } 00972 00973 static void 00974 free_pending_call_on_hash_removal (void *data) 00975 { 00976 DBusPendingCall *pending; 00977 DBusConnection *connection; 00978 00979 if (data == NULL) 00980 return; 00981 00982 pending = data; 00983 00984 connection = _dbus_pending_call_get_connection_unlocked (pending); 00985 00986 HAVE_LOCK_CHECK (connection); 00987 00988 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 00989 { 00990 _dbus_connection_remove_timeout_unlocked (connection, 00991 _dbus_pending_call_get_timeout_unlocked (pending)); 00992 00993 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 00994 } 00995 00996 /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock 00997 * here, but the pending call finalizer could in principle call out to 00998 * application code so we pretty much have to... some larger code reorg 00999 * might be needed. 01000 */ 01001 _dbus_connection_ref_unlocked (connection); 01002 _dbus_pending_call_unref_and_unlock (pending); 01003 CONNECTION_LOCK (connection); 01004 _dbus_connection_unref_unlocked (connection); 01005 } 01006 01007 static void 01008 _dbus_connection_detach_pending_call_unlocked (DBusConnection *connection, 01009 DBusPendingCall *pending) 01010 { 01011 /* This ends up unlocking to call the pending call finalizer, which is unexpected to 01012 * say the least. 01013 */ 01014 _dbus_hash_table_remove_int (connection->pending_replies, 01015 _dbus_pending_call_get_reply_serial_unlocked (pending)); 01016 } 01017 01018 static void 01019 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection, 01020 DBusPendingCall *pending) 01021 { 01022 /* The idea here is to avoid finalizing the pending call 01023 * with the lock held, since there's a destroy notifier 01024 * in pending call that goes out to application code. 01025 * 01026 * There's an extra unlock inside the hash table 01027 * "free pending call" function FIXME... 01028 */ 01029 _dbus_pending_call_ref_unlocked (pending); 01030 _dbus_hash_table_remove_int (connection->pending_replies, 01031 _dbus_pending_call_get_reply_serial_unlocked (pending)); 01032 01033 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 01034 _dbus_connection_remove_timeout_unlocked (connection, 01035 _dbus_pending_call_get_timeout_unlocked (pending)); 01036 01037 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 01038 01039 _dbus_pending_call_unref_and_unlock (pending); 01040 } 01041 01050 void 01051 _dbus_connection_remove_pending_call (DBusConnection *connection, 01052 DBusPendingCall *pending) 01053 { 01054 CONNECTION_LOCK (connection); 01055 _dbus_connection_detach_pending_call_and_unlock (connection, pending); 01056 } 01057 01067 static dbus_bool_t 01068 _dbus_connection_acquire_io_path (DBusConnection *connection, 01069 int timeout_milliseconds) 01070 { 01071 dbus_bool_t we_acquired; 01072 01073 HAVE_LOCK_CHECK (connection); 01074 01075 /* We don't want the connection to vanish */ 01076 _dbus_connection_ref_unlocked (connection); 01077 01078 /* We will only touch io_path_acquired which is protected by our mutex */ 01079 CONNECTION_UNLOCK (connection); 01080 01081 _dbus_verbose ("locking io_path_mutex\n"); 01082 _dbus_cmutex_lock (connection->io_path_mutex); 01083 01084 _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n", 01085 connection->io_path_acquired, timeout_milliseconds); 01086 01087 we_acquired = FALSE; 01088 01089 if (connection->io_path_acquired) 01090 { 01091 if (timeout_milliseconds != -1) 01092 { 01093 _dbus_verbose ("waiting %d for IO path to be acquirable\n", 01094 timeout_milliseconds); 01095 01096 if (!_dbus_condvar_wait_timeout (connection->io_path_cond, 01097 connection->io_path_mutex, 01098 timeout_milliseconds)) 01099 { 01100 /* We timed out before anyone signaled. */ 01101 /* (writing the loop to handle the !timedout case by 01102 * waiting longer if needed is a pain since dbus 01103 * wraps pthread_cond_timedwait to take a relative 01104 * time instead of absolute, something kind of stupid 01105 * on our part. for now it doesn't matter, we will just 01106 * end up back here eventually.) 01107 */ 01108 } 01109 } 01110 else 01111 { 01112 while (connection->io_path_acquired) 01113 { 01114 _dbus_verbose ("waiting for IO path to be acquirable\n"); 01115 _dbus_condvar_wait (connection->io_path_cond, 01116 connection->io_path_mutex); 01117 } 01118 } 01119 } 01120 01121 if (!connection->io_path_acquired) 01122 { 01123 we_acquired = TRUE; 01124 connection->io_path_acquired = TRUE; 01125 } 01126 01127 _dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n", 01128 connection->io_path_acquired, we_acquired); 01129 01130 _dbus_verbose ("unlocking io_path_mutex\n"); 01131 _dbus_cmutex_unlock (connection->io_path_mutex); 01132 01133 CONNECTION_LOCK (connection); 01134 01135 HAVE_LOCK_CHECK (connection); 01136 01137 _dbus_connection_unref_unlocked (connection); 01138 01139 return we_acquired; 01140 } 01141 01149 static void 01150 _dbus_connection_release_io_path (DBusConnection *connection) 01151 { 01152 HAVE_LOCK_CHECK (connection); 01153 01154 _dbus_verbose ("locking io_path_mutex\n"); 01155 _dbus_cmutex_lock (connection->io_path_mutex); 01156 01157 _dbus_assert (connection->io_path_acquired); 01158 01159 _dbus_verbose ("start connection->io_path_acquired = %d\n", 01160 connection->io_path_acquired); 01161 01162 connection->io_path_acquired = FALSE; 01163 _dbus_condvar_wake_one (connection->io_path_cond); 01164 01165 _dbus_verbose ("unlocking io_path_mutex\n"); 01166 _dbus_cmutex_unlock (connection->io_path_mutex); 01167 } 01168 01204 void 01205 _dbus_connection_do_iteration_unlocked (DBusConnection *connection, 01206 DBusPendingCall *pending, 01207 unsigned int flags, 01208 int timeout_milliseconds) 01209 { 01210 _dbus_verbose ("start\n"); 01211 01212 HAVE_LOCK_CHECK (connection); 01213 01214 if (connection->n_outgoing == 0) 01215 flags &= ~DBUS_ITERATION_DO_WRITING; 01216 01217 if (_dbus_connection_acquire_io_path (connection, 01218 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0)) 01219 { 01220 HAVE_LOCK_CHECK (connection); 01221 01222 if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending)) 01223 { 01224 _dbus_verbose ("pending call completed while acquiring I/O path"); 01225 } 01226 else if ( (pending != NULL) && 01227 _dbus_connection_peek_for_reply_unlocked (connection, 01228 _dbus_pending_call_get_reply_serial_unlocked (pending))) 01229 { 01230 _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)"); 01231 } 01232 else 01233 { 01234 _dbus_transport_do_iteration (connection->transport, 01235 flags, timeout_milliseconds); 01236 } 01237 01238 _dbus_connection_release_io_path (connection); 01239 } 01240 01241 HAVE_LOCK_CHECK (connection); 01242 01243 _dbus_verbose ("end\n"); 01244 } 01245 01255 DBusConnection* 01256 _dbus_connection_new_for_transport (DBusTransport *transport) 01257 { 01258 DBusConnection *connection; 01259 DBusWatchList *watch_list; 01260 DBusTimeoutList *timeout_list; 01261 DBusHashTable *pending_replies; 01262 DBusList *disconnect_link; 01263 DBusMessage *disconnect_message; 01264 DBusCounter *outgoing_counter; 01265 DBusObjectTree *objects; 01266 01267 watch_list = NULL; 01268 connection = NULL; 01269 pending_replies = NULL; 01270 timeout_list = NULL; 01271 disconnect_link = NULL; 01272 disconnect_message = NULL; 01273 outgoing_counter = NULL; 01274 objects = NULL; 01275 01276 watch_list = _dbus_watch_list_new (); 01277 if (watch_list == NULL) 01278 goto error; 01279 01280 timeout_list = _dbus_timeout_list_new (); 01281 if (timeout_list == NULL) 01282 goto error; 01283 01284 pending_replies = 01285 _dbus_hash_table_new (DBUS_HASH_INT, 01286 NULL, 01287 (DBusFreeFunction)free_pending_call_on_hash_removal); 01288 if (pending_replies == NULL) 01289 goto error; 01290 01291 connection = dbus_new0 (DBusConnection, 1); 01292 if (connection == NULL) 01293 goto error; 01294 01295 _dbus_rmutex_new_at_location (&connection->mutex); 01296 if (connection->mutex == NULL) 01297 goto error; 01298 01299 _dbus_cmutex_new_at_location (&connection->io_path_mutex); 01300 if (connection->io_path_mutex == NULL) 01301 goto error; 01302 01303 _dbus_cmutex_new_at_location (&connection->dispatch_mutex); 01304 if (connection->dispatch_mutex == NULL) 01305 goto error; 01306 01307 _dbus_condvar_new_at_location (&connection->dispatch_cond); 01308 if (connection->dispatch_cond == NULL) 01309 goto error; 01310 01311 _dbus_condvar_new_at_location (&connection->io_path_cond); 01312 if (connection->io_path_cond == NULL) 01313 goto error; 01314 01315 _dbus_rmutex_new_at_location (&connection->slot_mutex); 01316 if (connection->slot_mutex == NULL) 01317 goto error; 01318 01319 disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL, 01320 DBUS_INTERFACE_LOCAL, 01321 "Disconnected"); 01322 01323 if (disconnect_message == NULL) 01324 goto error; 01325 01326 disconnect_link = _dbus_list_alloc_link (disconnect_message); 01327 if (disconnect_link == NULL) 01328 goto error; 01329 01330 outgoing_counter = _dbus_counter_new (); 01331 if (outgoing_counter == NULL) 01332 goto error; 01333 01334 objects = _dbus_object_tree_new (connection); 01335 if (objects == NULL) 01336 goto error; 01337 01338 if (_dbus_modify_sigpipe) 01339 _dbus_disable_sigpipe (); 01340 01341 /* initialized to 0: use atomic op to avoid mixing atomic and non-atomic */ 01342 _dbus_atomic_inc (&connection->refcount); 01343 connection->transport = transport; 01344 connection->watches = watch_list; 01345 connection->timeouts = timeout_list; 01346 connection->pending_replies = pending_replies; 01347 connection->outgoing_counter = outgoing_counter; 01348 connection->filter_list = NULL; 01349 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */ 01350 connection->objects = objects; 01351 connection->exit_on_disconnect = FALSE; 01352 connection->shareable = FALSE; 01353 connection->route_peer_messages = FALSE; 01354 connection->disconnected_message_arrived = FALSE; 01355 connection->disconnected_message_processed = FALSE; 01356 01357 #ifndef DBUS_DISABLE_CHECKS 01358 connection->generation = _dbus_current_generation; 01359 #endif 01360 01361 _dbus_data_slot_list_init (&connection->slot_list); 01362 01363 connection->client_serial = 1; 01364 01365 connection->disconnect_message_link = disconnect_link; 01366 01367 CONNECTION_LOCK (connection); 01368 01369 if (!_dbus_transport_set_connection (transport, connection)) 01370 { 01371 CONNECTION_UNLOCK (connection); 01372 01373 goto error; 01374 } 01375 01376 _dbus_transport_ref (transport); 01377 01378 CONNECTION_UNLOCK (connection); 01379 01380 _dbus_connection_trace_ref (connection, 0, 1, "new_for_transport"); 01381 return connection; 01382 01383 error: 01384 if (disconnect_message != NULL) 01385 dbus_message_unref (disconnect_message); 01386 01387 if (disconnect_link != NULL) 01388 _dbus_list_free_link (disconnect_link); 01389 01390 if (connection != NULL) 01391 { 01392 _dbus_condvar_free_at_location (&connection->io_path_cond); 01393 _dbus_condvar_free_at_location (&connection->dispatch_cond); 01394 _dbus_rmutex_free_at_location (&connection->mutex); 01395 _dbus_cmutex_free_at_location (&connection->io_path_mutex); 01396 _dbus_cmutex_free_at_location (&connection->dispatch_mutex); 01397 _dbus_rmutex_free_at_location (&connection->slot_mutex); 01398 dbus_free (connection); 01399 } 01400 if (pending_replies) 01401 _dbus_hash_table_unref (pending_replies); 01402 01403 if (watch_list) 01404 _dbus_watch_list_free (watch_list); 01405 01406 if (timeout_list) 01407 _dbus_timeout_list_free (timeout_list); 01408 01409 if (outgoing_counter) 01410 _dbus_counter_unref (outgoing_counter); 01411 01412 if (objects) 01413 _dbus_object_tree_unref (objects); 01414 01415 return NULL; 01416 } 01417 01425 DBusConnection * 01426 _dbus_connection_ref_unlocked (DBusConnection *connection) 01427 { 01428 dbus_int32_t old_refcount; 01429 01430 _dbus_assert (connection != NULL); 01431 _dbus_assert (connection->generation == _dbus_current_generation); 01432 01433 HAVE_LOCK_CHECK (connection); 01434 01435 old_refcount = _dbus_atomic_inc (&connection->refcount); 01436 _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1, 01437 "ref_unlocked"); 01438 01439 return connection; 01440 } 01441 01448 void 01449 _dbus_connection_unref_unlocked (DBusConnection *connection) 01450 { 01451 dbus_int32_t old_refcount; 01452 01453 HAVE_LOCK_CHECK (connection); 01454 01455 _dbus_assert (connection != NULL); 01456 01457 old_refcount = _dbus_atomic_dec (&connection->refcount); 01458 01459 _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1, 01460 "unref_unlocked"); 01461 01462 if (old_refcount == 1) 01463 _dbus_connection_last_unref (connection); 01464 } 01465 01466 static dbus_uint32_t 01467 _dbus_connection_get_next_client_serial (DBusConnection *connection) 01468 { 01469 dbus_uint32_t serial; 01470 01471 serial = connection->client_serial++; 01472 01473 if (connection->client_serial == 0) 01474 connection->client_serial = 1; 01475 01476 return serial; 01477 } 01478 01492 dbus_bool_t 01493 _dbus_connection_handle_watch (DBusWatch *watch, 01494 unsigned int condition, 01495 void *data) 01496 { 01497 DBusConnection *connection; 01498 dbus_bool_t retval; 01499 DBusDispatchStatus status; 01500 01501 connection = data; 01502 01503 _dbus_verbose ("start\n"); 01504 01505 CONNECTION_LOCK (connection); 01506 01507 if (!_dbus_connection_acquire_io_path (connection, 1)) 01508 { 01509 /* another thread is handling the message */ 01510 CONNECTION_UNLOCK (connection); 01511 return TRUE; 01512 } 01513 01514 HAVE_LOCK_CHECK (connection); 01515 retval = _dbus_transport_handle_watch (connection->transport, 01516 watch, condition); 01517 01518 _dbus_connection_release_io_path (connection); 01519 01520 HAVE_LOCK_CHECK (connection); 01521 01522 _dbus_verbose ("middle\n"); 01523 01524 status = _dbus_connection_get_dispatch_status_unlocked (connection); 01525 01526 /* this calls out to user code */ 01527 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 01528 01529 _dbus_verbose ("end\n"); 01530 01531 return retval; 01532 } 01533 01534 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections); 01535 static DBusHashTable *shared_connections = NULL; 01536 static DBusList *shared_connections_no_guid = NULL; 01537 01538 static void 01539 close_connection_on_shutdown (DBusConnection *connection) 01540 { 01541 DBusMessage *message; 01542 01543 dbus_connection_ref (connection); 01544 _dbus_connection_close_possibly_shared (connection); 01545 01546 /* Churn through to the Disconnected message */ 01547 while ((message = dbus_connection_pop_message (connection))) 01548 { 01549 dbus_message_unref (message); 01550 } 01551 dbus_connection_unref (connection); 01552 } 01553 01554 static void 01555 shared_connections_shutdown (void *data) 01556 { 01557 int n_entries; 01558 01559 _DBUS_LOCK (shared_connections); 01560 01561 /* This is a little bit unpleasant... better ideas? */ 01562 while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0) 01563 { 01564 DBusConnection *connection; 01565 DBusHashIter iter; 01566 01567 _dbus_hash_iter_init (shared_connections, &iter); 01568 _dbus_hash_iter_next (&iter); 01569 01570 connection = _dbus_hash_iter_get_value (&iter); 01571 01572 _DBUS_UNLOCK (shared_connections); 01573 close_connection_on_shutdown (connection); 01574 _DBUS_LOCK (shared_connections); 01575 01576 /* The connection should now be dead and not in our hash ... */ 01577 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries); 01578 } 01579 01580 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0); 01581 01582 _dbus_hash_table_unref (shared_connections); 01583 shared_connections = NULL; 01584 01585 if (shared_connections_no_guid != NULL) 01586 { 01587 DBusConnection *connection; 01588 connection = _dbus_list_pop_first (&shared_connections_no_guid); 01589 while (connection != NULL) 01590 { 01591 _DBUS_UNLOCK (shared_connections); 01592 close_connection_on_shutdown (connection); 01593 _DBUS_LOCK (shared_connections); 01594 connection = _dbus_list_pop_first (&shared_connections_no_guid); 01595 } 01596 } 01597 01598 shared_connections_no_guid = NULL; 01599 01600 _DBUS_UNLOCK (shared_connections); 01601 } 01602 01603 static dbus_bool_t 01604 connection_lookup_shared (DBusAddressEntry *entry, 01605 DBusConnection **result) 01606 { 01607 _dbus_verbose ("checking for existing connection\n"); 01608 01609 *result = NULL; 01610 01611 _DBUS_LOCK (shared_connections); 01612 01613 if (shared_connections == NULL) 01614 { 01615 _dbus_verbose ("creating shared_connections hash table\n"); 01616 01617 shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING, 01618 dbus_free, 01619 NULL); 01620 if (shared_connections == NULL) 01621 { 01622 _DBUS_UNLOCK (shared_connections); 01623 return FALSE; 01624 } 01625 01626 if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL)) 01627 { 01628 _dbus_hash_table_unref (shared_connections); 01629 shared_connections = NULL; 01630 _DBUS_UNLOCK (shared_connections); 01631 return FALSE; 01632 } 01633 01634 _dbus_verbose (" successfully created shared_connections\n"); 01635 01636 _DBUS_UNLOCK (shared_connections); 01637 return TRUE; /* no point looking up in the hash we just made */ 01638 } 01639 else 01640 { 01641 const char *guid; 01642 01643 guid = dbus_address_entry_get_value (entry, "guid"); 01644 01645 if (guid != NULL) 01646 { 01647 DBusConnection *connection; 01648 01649 connection = _dbus_hash_table_lookup_string (shared_connections, 01650 guid); 01651 01652 if (connection) 01653 { 01654 /* The DBusConnection can't be finalized without taking 01655 * the shared_connections lock to remove it from the 01656 * hash. So it's safe to ref the connection here. 01657 * However, it may be disconnected if the Disconnected 01658 * message hasn't been processed yet, in which case we 01659 * want to pretend it isn't in the hash and avoid 01660 * returning it. 01661 * 01662 * The idea is to avoid ever returning a disconnected connection 01663 * from dbus_connection_open(). We could just synchronously 01664 * drop our shared ref to the connection on connection disconnect, 01665 * and then assert here that the connection is connected, but 01666 * that causes reentrancy headaches. 01667 */ 01668 CONNECTION_LOCK (connection); 01669 if (_dbus_connection_get_is_connected_unlocked (connection)) 01670 { 01671 _dbus_connection_ref_unlocked (connection); 01672 *result = connection; 01673 _dbus_verbose ("looked up existing connection to server guid %s\n", 01674 guid); 01675 } 01676 else 01677 { 01678 _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n", 01679 guid); 01680 } 01681 CONNECTION_UNLOCK (connection); 01682 } 01683 } 01684 01685 _DBUS_UNLOCK (shared_connections); 01686 return TRUE; 01687 } 01688 } 01689 01690 static dbus_bool_t 01691 connection_record_shared_unlocked (DBusConnection *connection, 01692 const char *guid) 01693 { 01694 char *guid_key; 01695 char *guid_in_connection; 01696 01697 HAVE_LOCK_CHECK (connection); 01698 _dbus_assert (connection->server_guid == NULL); 01699 _dbus_assert (connection->shareable); 01700 01701 /* get a hard ref on this connection, even if 01702 * we won't in fact store it in the hash, we still 01703 * need to hold a ref on it until it's disconnected. 01704 */ 01705 _dbus_connection_ref_unlocked (connection); 01706 01707 if (guid == NULL) 01708 { 01709 _DBUS_LOCK (shared_connections); 01710 01711 if (!_dbus_list_prepend (&shared_connections_no_guid, connection)) 01712 { 01713 _DBUS_UNLOCK (shared_connections); 01714 return FALSE; 01715 } 01716 01717 _DBUS_UNLOCK (shared_connections); 01718 return TRUE; /* don't store in the hash */ 01719 } 01720 01721 /* A separate copy of the key is required in the hash table, because 01722 * we don't have a lock on the connection when we are doing a hash 01723 * lookup. 01724 */ 01725 01726 guid_key = _dbus_strdup (guid); 01727 if (guid_key == NULL) 01728 return FALSE; 01729 01730 guid_in_connection = _dbus_strdup (guid); 01731 if (guid_in_connection == NULL) 01732 { 01733 dbus_free (guid_key); 01734 return FALSE; 01735 } 01736 01737 _DBUS_LOCK (shared_connections); 01738 _dbus_assert (shared_connections != NULL); 01739 01740 if (!_dbus_hash_table_insert_string (shared_connections, 01741 guid_key, connection)) 01742 { 01743 dbus_free (guid_key); 01744 dbus_free (guid_in_connection); 01745 _DBUS_UNLOCK (shared_connections); 01746 return FALSE; 01747 } 01748 01749 connection->server_guid = guid_in_connection; 01750 01751 _dbus_verbose ("stored connection to %s to be shared\n", 01752 connection->server_guid); 01753 01754 _DBUS_UNLOCK (shared_connections); 01755 01756 _dbus_assert (connection->server_guid != NULL); 01757 01758 return TRUE; 01759 } 01760 01761 static void 01762 connection_forget_shared_unlocked (DBusConnection *connection) 01763 { 01764 HAVE_LOCK_CHECK (connection); 01765 01766 if (!connection->shareable) 01767 return; 01768 01769 _DBUS_LOCK (shared_connections); 01770 01771 if (connection->server_guid != NULL) 01772 { 01773 _dbus_verbose ("dropping connection to %s out of the shared table\n", 01774 connection->server_guid); 01775 01776 if (!_dbus_hash_table_remove_string (shared_connections, 01777 connection->server_guid)) 01778 _dbus_assert_not_reached ("connection was not in the shared table"); 01779 01780 dbus_free (connection->server_guid); 01781 connection->server_guid = NULL; 01782 } 01783 else 01784 { 01785 _dbus_list_remove (&shared_connections_no_guid, connection); 01786 } 01787 01788 _DBUS_UNLOCK (shared_connections); 01789 01790 /* remove our reference held on all shareable connections */ 01791 _dbus_connection_unref_unlocked (connection); 01792 } 01793 01794 static DBusConnection* 01795 connection_try_from_address_entry (DBusAddressEntry *entry, 01796 DBusError *error) 01797 { 01798 DBusTransport *transport; 01799 DBusConnection *connection; 01800 01801 transport = _dbus_transport_open (entry, error); 01802 01803 if (transport == NULL) 01804 { 01805 _DBUS_ASSERT_ERROR_IS_SET (error); 01806 return NULL; 01807 } 01808 01809 connection = _dbus_connection_new_for_transport (transport); 01810 01811 _dbus_transport_unref (transport); 01812 01813 if (connection == NULL) 01814 { 01815 _DBUS_SET_OOM (error); 01816 return NULL; 01817 } 01818 01819 #ifndef DBUS_DISABLE_CHECKS 01820 _dbus_assert (!connection->have_connection_lock); 01821 #endif 01822 return connection; 01823 } 01824 01825 /* 01826 * If the shared parameter is true, then any existing connection will 01827 * be used (and if a new connection is created, it will be available 01828 * for use by others). If the shared parameter is false, a new 01829 * connection will always be created, and the new connection will 01830 * never be returned to other callers. 01831 * 01832 * @param address the address 01833 * @param shared whether the connection is shared or private 01834 * @param error error return 01835 * @returns the connection or #NULL on error 01836 */ 01837 static DBusConnection* 01838 _dbus_connection_open_internal (const char *address, 01839 dbus_bool_t shared, 01840 DBusError *error) 01841 { 01842 DBusConnection *connection; 01843 DBusAddressEntry **entries; 01844 DBusError tmp_error = DBUS_ERROR_INIT; 01845 DBusError first_error = DBUS_ERROR_INIT; 01846 int len, i; 01847 01848 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01849 01850 _dbus_verbose ("opening %s connection to: %s\n", 01851 shared ? "shared" : "private", address); 01852 01853 if (!dbus_parse_address (address, &entries, &len, error)) 01854 return NULL; 01855 01856 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01857 01858 connection = NULL; 01859 01860 for (i = 0; i < len; i++) 01861 { 01862 if (shared) 01863 { 01864 if (!connection_lookup_shared (entries[i], &connection)) 01865 _DBUS_SET_OOM (&tmp_error); 01866 } 01867 01868 if (connection == NULL) 01869 { 01870 connection = connection_try_from_address_entry (entries[i], 01871 &tmp_error); 01872 01873 if (connection != NULL && shared) 01874 { 01875 const char *guid; 01876 01877 connection->shareable = TRUE; 01878 01879 /* guid may be NULL */ 01880 guid = dbus_address_entry_get_value (entries[i], "guid"); 01881 01882 CONNECTION_LOCK (connection); 01883 01884 if (!connection_record_shared_unlocked (connection, guid)) 01885 { 01886 _DBUS_SET_OOM (&tmp_error); 01887 _dbus_connection_close_possibly_shared_and_unlock (connection); 01888 dbus_connection_unref (connection); 01889 connection = NULL; 01890 } 01891 else 01892 CONNECTION_UNLOCK (connection); 01893 } 01894 } 01895 01896 if (connection) 01897 break; 01898 01899 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 01900 01901 if (i == 0) 01902 dbus_move_error (&tmp_error, &first_error); 01903 else 01904 dbus_error_free (&tmp_error); 01905 } 01906 01907 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01908 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 01909 01910 if (connection == NULL) 01911 { 01912 _DBUS_ASSERT_ERROR_IS_SET (&first_error); 01913 dbus_move_error (&first_error, error); 01914 } 01915 else 01916 dbus_error_free (&first_error); 01917 01918 dbus_address_entries_free (entries); 01919 return connection; 01920 } 01921 01930 void 01931 _dbus_connection_close_possibly_shared (DBusConnection *connection) 01932 { 01933 _dbus_assert (connection != NULL); 01934 _dbus_assert (connection->generation == _dbus_current_generation); 01935 01936 CONNECTION_LOCK (connection); 01937 _dbus_connection_close_possibly_shared_and_unlock (connection); 01938 } 01939 01940 static DBusPreallocatedSend* 01941 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection) 01942 { 01943 DBusPreallocatedSend *preallocated; 01944 01945 HAVE_LOCK_CHECK (connection); 01946 01947 _dbus_assert (connection != NULL); 01948 01949 preallocated = dbus_new (DBusPreallocatedSend, 1); 01950 if (preallocated == NULL) 01951 return NULL; 01952 01953 preallocated->queue_link = _dbus_list_alloc_link (NULL); 01954 if (preallocated->queue_link == NULL) 01955 goto failed_0; 01956 01957 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter); 01958 if (preallocated->counter_link == NULL) 01959 goto failed_1; 01960 01961 _dbus_counter_ref (preallocated->counter_link->data); 01962 01963 preallocated->connection = connection; 01964 01965 return preallocated; 01966 01967 failed_1: 01968 _dbus_list_free_link (preallocated->queue_link); 01969 failed_0: 01970 dbus_free (preallocated); 01971 01972 return NULL; 01973 } 01974 01975 /* Called with lock held, does not update dispatch status */ 01976 static void 01977 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection, 01978 DBusPreallocatedSend *preallocated, 01979 DBusMessage *message, 01980 dbus_uint32_t *client_serial) 01981 { 01982 dbus_uint32_t serial; 01983 01984 preallocated->queue_link->data = message; 01985 _dbus_list_prepend_link (&connection->outgoing_messages, 01986 preallocated->queue_link); 01987 01988 /* It's OK that we'll never call the notify function, because for the 01989 * outgoing limit, there isn't one */ 01990 _dbus_message_add_counter_link (message, 01991 preallocated->counter_link); 01992 01993 dbus_free (preallocated); 01994 preallocated = NULL; 01995 01996 dbus_message_ref (message); 01997 01998 connection->n_outgoing += 1; 01999 02000 _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n", 02001 message, 02002 dbus_message_type_to_string (dbus_message_get_type (message)), 02003 dbus_message_get_path (message) ? 02004 dbus_message_get_path (message) : 02005 "no path", 02006 dbus_message_get_interface (message) ? 02007 dbus_message_get_interface (message) : 02008 "no interface", 02009 dbus_message_get_member (message) ? 02010 dbus_message_get_member (message) : 02011 "no member", 02012 dbus_message_get_signature (message), 02013 dbus_message_get_destination (message) ? 02014 dbus_message_get_destination (message) : 02015 "null", 02016 connection, 02017 connection->n_outgoing); 02018 02019 if (dbus_message_get_serial (message) == 0) 02020 { 02021 serial = _dbus_connection_get_next_client_serial (connection); 02022 dbus_message_set_serial (message, serial); 02023 if (client_serial) 02024 *client_serial = serial; 02025 } 02026 else 02027 { 02028 if (client_serial) 02029 *client_serial = dbus_message_get_serial (message); 02030 } 02031 02032 _dbus_verbose ("Message %p serial is %u\n", 02033 message, dbus_message_get_serial (message)); 02034 02035 dbus_message_lock (message); 02036 02037 /* Now we need to run an iteration to hopefully just write the messages 02038 * out immediately, and otherwise get them queued up 02039 */ 02040 _dbus_connection_do_iteration_unlocked (connection, 02041 NULL, 02042 DBUS_ITERATION_DO_WRITING, 02043 -1); 02044 02045 /* If stuff is still queued up, be sure we wake up the main loop */ 02046 if (connection->n_outgoing > 0) 02047 _dbus_connection_wakeup_mainloop (connection); 02048 } 02049 02050 static void 02051 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection, 02052 DBusPreallocatedSend *preallocated, 02053 DBusMessage *message, 02054 dbus_uint32_t *client_serial) 02055 { 02056 DBusDispatchStatus status; 02057 02058 HAVE_LOCK_CHECK (connection); 02059 02060 _dbus_connection_send_preallocated_unlocked_no_update (connection, 02061 preallocated, 02062 message, client_serial); 02063 02064 _dbus_verbose ("middle\n"); 02065 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02066 02067 /* this calls out to user code */ 02068 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02069 } 02070 02080 dbus_bool_t 02081 _dbus_connection_send_and_unlock (DBusConnection *connection, 02082 DBusMessage *message, 02083 dbus_uint32_t *client_serial) 02084 { 02085 DBusPreallocatedSend *preallocated; 02086 02087 _dbus_assert (connection != NULL); 02088 _dbus_assert (message != NULL); 02089 02090 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 02091 if (preallocated == NULL) 02092 { 02093 CONNECTION_UNLOCK (connection); 02094 return FALSE; 02095 } 02096 02097 _dbus_connection_send_preallocated_and_unlock (connection, 02098 preallocated, 02099 message, 02100 client_serial); 02101 return TRUE; 02102 } 02103 02128 void 02129 _dbus_connection_close_if_only_one_ref (DBusConnection *connection) 02130 { 02131 dbus_int32_t refcount; 02132 02133 CONNECTION_LOCK (connection); 02134 02135 refcount = _dbus_atomic_get (&connection->refcount); 02136 /* The caller should have at least one ref */ 02137 _dbus_assert (refcount >= 1); 02138 02139 if (refcount == 1) 02140 _dbus_connection_close_possibly_shared_and_unlock (connection); 02141 else 02142 CONNECTION_UNLOCK (connection); 02143 } 02144 02145 02155 static void 02156 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds) 02157 { 02158 if (timeout_milliseconds == -1) 02159 _dbus_sleep_milliseconds (1000); 02160 else if (timeout_milliseconds < 100) 02161 ; /* just busy loop */ 02162 else if (timeout_milliseconds <= 1000) 02163 _dbus_sleep_milliseconds (timeout_milliseconds / 3); 02164 else 02165 _dbus_sleep_milliseconds (1000); 02166 } 02167 02168 static DBusMessage * 02169 generate_local_error_message (dbus_uint32_t serial, 02170 char *error_name, 02171 char *error_msg) 02172 { 02173 DBusMessage *message; 02174 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR); 02175 if (!message) 02176 goto out; 02177 02178 if (!dbus_message_set_error_name (message, error_name)) 02179 { 02180 dbus_message_unref (message); 02181 message = NULL; 02182 goto out; 02183 } 02184 02185 dbus_message_set_no_reply (message, TRUE); 02186 02187 if (!dbus_message_set_reply_serial (message, 02188 serial)) 02189 { 02190 dbus_message_unref (message); 02191 message = NULL; 02192 goto out; 02193 } 02194 02195 if (error_msg != NULL) 02196 { 02197 DBusMessageIter iter; 02198 02199 dbus_message_iter_init_append (message, &iter); 02200 if (!dbus_message_iter_append_basic (&iter, 02201 DBUS_TYPE_STRING, 02202 &error_msg)) 02203 { 02204 dbus_message_unref (message); 02205 message = NULL; 02206 goto out; 02207 } 02208 } 02209 02210 out: 02211 return message; 02212 } 02213 02214 /* 02215 * Peek the incoming queue to see if we got reply for a specific serial 02216 */ 02217 static dbus_bool_t 02218 _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection, 02219 dbus_uint32_t client_serial) 02220 { 02221 DBusList *link; 02222 HAVE_LOCK_CHECK (connection); 02223 02224 link = _dbus_list_get_first_link (&connection->incoming_messages); 02225 02226 while (link != NULL) 02227 { 02228 DBusMessage *reply = link->data; 02229 02230 if (dbus_message_get_reply_serial (reply) == client_serial) 02231 { 02232 _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial); 02233 return TRUE; 02234 } 02235 link = _dbus_list_get_next_link (&connection->incoming_messages, link); 02236 } 02237 02238 return FALSE; 02239 } 02240 02241 /* This is slightly strange since we can pop a message here without 02242 * the dispatch lock. 02243 */ 02244 static DBusMessage* 02245 check_for_reply_unlocked (DBusConnection *connection, 02246 dbus_uint32_t client_serial) 02247 { 02248 DBusList *link; 02249 02250 HAVE_LOCK_CHECK (connection); 02251 02252 link = _dbus_list_get_first_link (&connection->incoming_messages); 02253 02254 while (link != NULL) 02255 { 02256 DBusMessage *reply = link->data; 02257 02258 if (dbus_message_get_reply_serial (reply) == client_serial) 02259 { 02260 _dbus_list_remove_link (&connection->incoming_messages, link); 02261 connection->n_incoming -= 1; 02262 return reply; 02263 } 02264 link = _dbus_list_get_next_link (&connection->incoming_messages, link); 02265 } 02266 02267 return NULL; 02268 } 02269 02270 static void 02271 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection) 02272 { 02273 /* We can't iterate over the hash in the normal way since we'll be 02274 * dropping the lock for each item. So we restart the 02275 * iter each time as we drain the hash table. 02276 */ 02277 02278 while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0) 02279 { 02280 DBusPendingCall *pending; 02281 DBusHashIter iter; 02282 02283 _dbus_hash_iter_init (connection->pending_replies, &iter); 02284 _dbus_hash_iter_next (&iter); 02285 02286 pending = _dbus_hash_iter_get_value (&iter); 02287 _dbus_pending_call_ref_unlocked (pending); 02288 02289 _dbus_pending_call_queue_timeout_error_unlocked (pending, 02290 connection); 02291 02292 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 02293 _dbus_connection_remove_timeout_unlocked (connection, 02294 _dbus_pending_call_get_timeout_unlocked (pending)); 02295 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 02296 _dbus_hash_iter_remove_entry (&iter); 02297 02298 _dbus_pending_call_unref_and_unlock (pending); 02299 CONNECTION_LOCK (connection); 02300 } 02301 HAVE_LOCK_CHECK (connection); 02302 } 02303 02304 static void 02305 complete_pending_call_and_unlock (DBusConnection *connection, 02306 DBusPendingCall *pending, 02307 DBusMessage *message) 02308 { 02309 _dbus_pending_call_set_reply_unlocked (pending, message); 02310 _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */ 02311 _dbus_connection_detach_pending_call_and_unlock (connection, pending); 02312 02313 /* Must be called unlocked since it invokes app callback */ 02314 _dbus_pending_call_complete (pending); 02315 dbus_pending_call_unref (pending); 02316 } 02317 02318 static dbus_bool_t 02319 check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection, 02320 DBusPendingCall *pending) 02321 { 02322 DBusMessage *reply; 02323 DBusDispatchStatus status; 02324 02325 reply = check_for_reply_unlocked (connection, 02326 _dbus_pending_call_get_reply_serial_unlocked (pending)); 02327 if (reply != NULL) 02328 { 02329 _dbus_verbose ("checked for reply\n"); 02330 02331 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n"); 02332 02333 complete_pending_call_and_unlock (connection, pending, reply); 02334 dbus_message_unref (reply); 02335 02336 CONNECTION_LOCK (connection); 02337 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02338 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02339 dbus_pending_call_unref (pending); 02340 02341 return TRUE; 02342 } 02343 02344 return FALSE; 02345 } 02346 02361 void 02362 _dbus_connection_block_pending_call (DBusPendingCall *pending) 02363 { 02364 long start_tv_sec, start_tv_usec; 02365 long tv_sec, tv_usec; 02366 DBusDispatchStatus status; 02367 DBusConnection *connection; 02368 dbus_uint32_t client_serial; 02369 DBusTimeout *timeout; 02370 int timeout_milliseconds, elapsed_milliseconds; 02371 02372 _dbus_assert (pending != NULL); 02373 02374 if (dbus_pending_call_get_completed (pending)) 02375 return; 02376 02377 dbus_pending_call_ref (pending); /* necessary because the call could be canceled */ 02378 02379 connection = _dbus_pending_call_get_connection_and_lock (pending); 02380 02381 /* Flush message queue - note, can affect dispatch status */ 02382 _dbus_connection_flush_unlocked (connection); 02383 02384 client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending); 02385 02386 /* note that timeout_milliseconds is limited to a smallish value 02387 * in _dbus_pending_call_new() so overflows aren't possible 02388 * below 02389 */ 02390 timeout = _dbus_pending_call_get_timeout_unlocked (pending); 02391 _dbus_get_monotonic_time (&start_tv_sec, &start_tv_usec); 02392 if (timeout) 02393 { 02394 timeout_milliseconds = dbus_timeout_get_interval (timeout); 02395 02396 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n", 02397 timeout_milliseconds, 02398 client_serial, 02399 start_tv_sec, start_tv_usec); 02400 } 02401 else 02402 { 02403 timeout_milliseconds = -1; 02404 02405 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial); 02406 } 02407 02408 /* check to see if we already got the data off the socket */ 02409 /* from another blocked pending call */ 02410 if (check_for_reply_and_update_dispatch_unlocked (connection, pending)) 02411 return; 02412 02413 /* Now we wait... */ 02414 /* always block at least once as we know we don't have the reply yet */ 02415 _dbus_connection_do_iteration_unlocked (connection, 02416 pending, 02417 DBUS_ITERATION_DO_READING | 02418 DBUS_ITERATION_BLOCK, 02419 timeout_milliseconds); 02420 02421 recheck_status: 02422 02423 _dbus_verbose ("top of recheck\n"); 02424 02425 HAVE_LOCK_CHECK (connection); 02426 02427 /* queue messages and get status */ 02428 02429 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02430 02431 /* the get_completed() is in case a dispatch() while we were blocking 02432 * got the reply instead of us. 02433 */ 02434 if (_dbus_pending_call_get_completed_unlocked (pending)) 02435 { 02436 _dbus_verbose ("Pending call completed by dispatch\n"); 02437 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02438 dbus_pending_call_unref (pending); 02439 return; 02440 } 02441 02442 if (status == DBUS_DISPATCH_DATA_REMAINS) 02443 { 02444 if (check_for_reply_and_update_dispatch_unlocked (connection, pending)) 02445 return; 02446 } 02447 02448 _dbus_get_monotonic_time (&tv_sec, &tv_usec); 02449 elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 + 02450 (tv_usec - start_tv_usec) / 1000; 02451 02452 if (!_dbus_connection_get_is_connected_unlocked (connection)) 02453 { 02454 DBusMessage *error_msg; 02455 02456 error_msg = generate_local_error_message (client_serial, 02457 DBUS_ERROR_DISCONNECTED, 02458 "Connection was disconnected before a reply was received"); 02459 02460 /* on OOM error_msg is set to NULL */ 02461 complete_pending_call_and_unlock (connection, pending, error_msg); 02462 dbus_pending_call_unref (pending); 02463 return; 02464 } 02465 else if (connection->disconnect_message_link == NULL) 02466 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n"); 02467 else if (timeout == NULL) 02468 { 02469 if (status == DBUS_DISPATCH_NEED_MEMORY) 02470 { 02471 /* Try sleeping a bit, as we aren't sure we need to block for reading, 02472 * we may already have a reply in the buffer and just can't process 02473 * it. 02474 */ 02475 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n"); 02476 02477 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds); 02478 } 02479 else 02480 { 02481 /* block again, we don't have the reply buffered yet. */ 02482 _dbus_connection_do_iteration_unlocked (connection, 02483 pending, 02484 DBUS_ITERATION_DO_READING | 02485 DBUS_ITERATION_BLOCK, 02486 timeout_milliseconds - elapsed_milliseconds); 02487 } 02488 02489 goto recheck_status; 02490 } 02491 else if (tv_sec < start_tv_sec) 02492 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n"); 02493 else if (elapsed_milliseconds < timeout_milliseconds) 02494 { 02495 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds); 02496 02497 if (status == DBUS_DISPATCH_NEED_MEMORY) 02498 { 02499 /* Try sleeping a bit, as we aren't sure we need to block for reading, 02500 * we may already have a reply in the buffer and just can't process 02501 * it. 02502 */ 02503 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n"); 02504 02505 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds); 02506 } 02507 else 02508 { 02509 /* block again, we don't have the reply buffered yet. */ 02510 _dbus_connection_do_iteration_unlocked (connection, 02511 NULL, 02512 DBUS_ITERATION_DO_READING | 02513 DBUS_ITERATION_BLOCK, 02514 timeout_milliseconds - elapsed_milliseconds); 02515 } 02516 02517 goto recheck_status; 02518 } 02519 02520 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n", 02521 elapsed_milliseconds); 02522 02523 _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending)); 02524 02525 /* unlock and call user code */ 02526 complete_pending_call_and_unlock (connection, pending, NULL); 02527 02528 /* update user code on dispatch status */ 02529 CONNECTION_LOCK (connection); 02530 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02531 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02532 dbus_pending_call_unref (pending); 02533 } 02534 02571 DBusConnection* 02572 dbus_connection_open (const char *address, 02573 DBusError *error) 02574 { 02575 DBusConnection *connection; 02576 02577 _dbus_return_val_if_fail (address != NULL, NULL); 02578 _dbus_return_val_if_error_is_set (error, NULL); 02579 02580 connection = _dbus_connection_open_internal (address, 02581 TRUE, 02582 error); 02583 02584 return connection; 02585 } 02586 02614 DBusConnection* 02615 dbus_connection_open_private (const char *address, 02616 DBusError *error) 02617 { 02618 DBusConnection *connection; 02619 02620 _dbus_return_val_if_fail (address != NULL, NULL); 02621 _dbus_return_val_if_error_is_set (error, NULL); 02622 02623 connection = _dbus_connection_open_internal (address, 02624 FALSE, 02625 error); 02626 02627 return connection; 02628 } 02629 02636 DBusConnection * 02637 dbus_connection_ref (DBusConnection *connection) 02638 { 02639 dbus_int32_t old_refcount; 02640 02641 _dbus_return_val_if_fail (connection != NULL, NULL); 02642 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL); 02643 old_refcount = _dbus_atomic_inc (&connection->refcount); 02644 _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1, 02645 "ref"); 02646 02647 return connection; 02648 } 02649 02650 static void 02651 free_outgoing_message (void *element, 02652 void *data) 02653 { 02654 DBusMessage *message = element; 02655 DBusConnection *connection = data; 02656 02657 _dbus_message_remove_counter (message, connection->outgoing_counter); 02658 dbus_message_unref (message); 02659 } 02660 02661 /* This is run without the mutex held, but after the last reference 02662 * to the connection has been dropped we should have no thread-related 02663 * problems 02664 */ 02665 static void 02666 _dbus_connection_last_unref (DBusConnection *connection) 02667 { 02668 DBusList *link; 02669 02670 _dbus_verbose ("Finalizing connection %p\n", connection); 02671 02672 _dbus_assert (_dbus_atomic_get (&connection->refcount) == 0); 02673 02674 /* You have to disconnect the connection before unref:ing it. Otherwise 02675 * you won't get the disconnected message. 02676 */ 02677 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport)); 02678 _dbus_assert (connection->server_guid == NULL); 02679 02680 /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */ 02681 _dbus_object_tree_free_all_unlocked (connection->objects); 02682 02683 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL); 02684 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL); 02685 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL); 02686 02687 _dbus_watch_list_free (connection->watches); 02688 connection->watches = NULL; 02689 02690 _dbus_timeout_list_free (connection->timeouts); 02691 connection->timeouts = NULL; 02692 02693 _dbus_data_slot_list_free (&connection->slot_list); 02694 02695 link = _dbus_list_get_first_link (&connection->filter_list); 02696 while (link != NULL) 02697 { 02698 DBusMessageFilter *filter = link->data; 02699 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link); 02700 02701 filter->function = NULL; 02702 _dbus_message_filter_unref (filter); /* calls app callback */ 02703 link->data = NULL; 02704 02705 link = next; 02706 } 02707 _dbus_list_clear (&connection->filter_list); 02708 02709 /* ---- Done with stuff that invokes application callbacks */ 02710 02711 _dbus_object_tree_unref (connection->objects); 02712 02713 _dbus_hash_table_unref (connection->pending_replies); 02714 connection->pending_replies = NULL; 02715 02716 _dbus_list_clear (&connection->filter_list); 02717 02718 _dbus_list_foreach (&connection->outgoing_messages, 02719 free_outgoing_message, 02720 connection); 02721 _dbus_list_clear (&connection->outgoing_messages); 02722 02723 _dbus_list_foreach (&connection->incoming_messages, 02724 (DBusForeachFunction) dbus_message_unref, 02725 NULL); 02726 _dbus_list_clear (&connection->incoming_messages); 02727 02728 _dbus_counter_unref (connection->outgoing_counter); 02729 02730 _dbus_transport_unref (connection->transport); 02731 02732 if (connection->disconnect_message_link) 02733 { 02734 DBusMessage *message = connection->disconnect_message_link->data; 02735 dbus_message_unref (message); 02736 _dbus_list_free_link (connection->disconnect_message_link); 02737 } 02738 02739 _dbus_condvar_free_at_location (&connection->dispatch_cond); 02740 _dbus_condvar_free_at_location (&connection->io_path_cond); 02741 02742 _dbus_cmutex_free_at_location (&connection->io_path_mutex); 02743 _dbus_cmutex_free_at_location (&connection->dispatch_mutex); 02744 02745 _dbus_rmutex_free_at_location (&connection->slot_mutex); 02746 02747 _dbus_rmutex_free_at_location (&connection->mutex); 02748 02749 dbus_free (connection); 02750 } 02751 02771 void 02772 dbus_connection_unref (DBusConnection *connection) 02773 { 02774 dbus_int32_t old_refcount; 02775 02776 _dbus_return_if_fail (connection != NULL); 02777 _dbus_return_if_fail (connection->generation == _dbus_current_generation); 02778 02779 old_refcount = _dbus_atomic_dec (&connection->refcount); 02780 02781 _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1, 02782 "unref"); 02783 02784 if (old_refcount == 1) 02785 { 02786 #ifndef DBUS_DISABLE_CHECKS 02787 if (_dbus_transport_get_is_connected (connection->transport)) 02788 { 02789 _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", 02790 connection->shareable ? 02791 "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" : 02792 "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n"); 02793 return; 02794 } 02795 #endif 02796 _dbus_connection_last_unref (connection); 02797 } 02798 } 02799 02800 /* 02801 * Note that the transport can disconnect itself (other end drops us) 02802 * and in that case this function never runs. So this function must 02803 * not do anything more than disconnect the transport and update the 02804 * dispatch status. 02805 * 02806 * If the transport self-disconnects, then we assume someone will 02807 * dispatch the connection to cause the dispatch status update. 02808 */ 02809 static void 02810 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection) 02811 { 02812 DBusDispatchStatus status; 02813 02814 HAVE_LOCK_CHECK (connection); 02815 02816 _dbus_verbose ("Disconnecting %p\n", connection); 02817 02818 /* We need to ref because update_dispatch_status_and_unlock will unref 02819 * the connection if it was shared and libdbus was the only remaining 02820 * refcount holder. 02821 */ 02822 _dbus_connection_ref_unlocked (connection); 02823 02824 _dbus_transport_disconnect (connection->transport); 02825 02826 /* This has the side effect of queuing the disconnect message link 02827 * (unless we don't have enough memory, possibly, so don't assert it). 02828 * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open 02829 * should never again return the newly-disconnected connection. 02830 * 02831 * However, we only unref the shared connection and exit_on_disconnect when 02832 * the disconnect message reaches the head of the message queue, 02833 * NOT when it's first queued. 02834 */ 02835 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02836 02837 /* This calls out to user code */ 02838 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02839 02840 /* Could also call out to user code */ 02841 dbus_connection_unref (connection); 02842 } 02843 02886 void 02887 dbus_connection_close (DBusConnection *connection) 02888 { 02889 _dbus_return_if_fail (connection != NULL); 02890 _dbus_return_if_fail (connection->generation == _dbus_current_generation); 02891 02892 CONNECTION_LOCK (connection); 02893 02894 #ifndef DBUS_DISABLE_CHECKS 02895 if (connection->shareable) 02896 { 02897 CONNECTION_UNLOCK (connection); 02898 02899 _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n"); 02900 return; 02901 } 02902 #endif 02903 02904 _dbus_connection_close_possibly_shared_and_unlock (connection); 02905 } 02906 02907 static dbus_bool_t 02908 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection) 02909 { 02910 HAVE_LOCK_CHECK (connection); 02911 return _dbus_transport_get_is_connected (connection->transport); 02912 } 02913 02927 dbus_bool_t 02928 dbus_connection_get_is_connected (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_connection_get_is_connected_unlocked (connection); 02936 CONNECTION_UNLOCK (connection); 02937 02938 return res; 02939 } 02940 02949 dbus_bool_t 02950 dbus_connection_get_is_authenticated (DBusConnection *connection) 02951 { 02952 dbus_bool_t res; 02953 02954 _dbus_return_val_if_fail (connection != NULL, FALSE); 02955 02956 CONNECTION_LOCK (connection); 02957 res = _dbus_transport_get_is_authenticated (connection->transport); 02958 CONNECTION_UNLOCK (connection); 02959 02960 return res; 02961 } 02962 02983 dbus_bool_t 02984 dbus_connection_get_is_anonymous (DBusConnection *connection) 02985 { 02986 dbus_bool_t res; 02987 02988 _dbus_return_val_if_fail (connection != NULL, FALSE); 02989 02990 CONNECTION_LOCK (connection); 02991 res = _dbus_transport_get_is_anonymous (connection->transport); 02992 CONNECTION_UNLOCK (connection); 02993 02994 return res; 02995 } 02996 03028 char* 03029 dbus_connection_get_server_id (DBusConnection *connection) 03030 { 03031 char *id; 03032 03033 _dbus_return_val_if_fail (connection != NULL, NULL); 03034 03035 CONNECTION_LOCK (connection); 03036 id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport)); 03037 CONNECTION_UNLOCK (connection); 03038 03039 return id; 03040 } 03041 03059 dbus_bool_t 03060 dbus_connection_can_send_type(DBusConnection *connection, 03061 int type) 03062 { 03063 _dbus_return_val_if_fail (connection != NULL, FALSE); 03064 03065 if (!dbus_type_is_valid (type)) 03066 return FALSE; 03067 03068 if (type != DBUS_TYPE_UNIX_FD) 03069 return TRUE; 03070 03071 #ifdef HAVE_UNIX_FD_PASSING 03072 { 03073 dbus_bool_t b; 03074 03075 CONNECTION_LOCK(connection); 03076 b = _dbus_transport_can_pass_unix_fd(connection->transport); 03077 CONNECTION_UNLOCK(connection); 03078 03079 return b; 03080 } 03081 #endif 03082 03083 return FALSE; 03084 } 03085 03099 void 03100 dbus_connection_set_exit_on_disconnect (DBusConnection *connection, 03101 dbus_bool_t exit_on_disconnect) 03102 { 03103 _dbus_return_if_fail (connection != NULL); 03104 03105 CONNECTION_LOCK (connection); 03106 connection->exit_on_disconnect = exit_on_disconnect != FALSE; 03107 CONNECTION_UNLOCK (connection); 03108 } 03109 03119 DBusPreallocatedSend* 03120 dbus_connection_preallocate_send (DBusConnection *connection) 03121 { 03122 DBusPreallocatedSend *preallocated; 03123 03124 _dbus_return_val_if_fail (connection != NULL, NULL); 03125 03126 CONNECTION_LOCK (connection); 03127 03128 preallocated = 03129 _dbus_connection_preallocate_send_unlocked (connection); 03130 03131 CONNECTION_UNLOCK (connection); 03132 03133 return preallocated; 03134 } 03135 03145 void 03146 dbus_connection_free_preallocated_send (DBusConnection *connection, 03147 DBusPreallocatedSend *preallocated) 03148 { 03149 _dbus_return_if_fail (connection != NULL); 03150 _dbus_return_if_fail (preallocated != NULL); 03151 _dbus_return_if_fail (connection == preallocated->connection); 03152 03153 _dbus_list_free_link (preallocated->queue_link); 03154 _dbus_counter_unref (preallocated->counter_link->data); 03155 _dbus_list_free_link (preallocated->counter_link); 03156 dbus_free (preallocated); 03157 } 03158 03171 void 03172 dbus_connection_send_preallocated (DBusConnection *connection, 03173 DBusPreallocatedSend *preallocated, 03174 DBusMessage *message, 03175 dbus_uint32_t *client_serial) 03176 { 03177 _dbus_return_if_fail (connection != NULL); 03178 _dbus_return_if_fail (preallocated != NULL); 03179 _dbus_return_if_fail (message != NULL); 03180 _dbus_return_if_fail (preallocated->connection == connection); 03181 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL || 03182 dbus_message_get_member (message) != NULL); 03183 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL || 03184 (dbus_message_get_interface (message) != NULL && 03185 dbus_message_get_member (message) != NULL)); 03186 03187 CONNECTION_LOCK (connection); 03188 03189 #ifdef HAVE_UNIX_FD_PASSING 03190 03191 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03192 message->n_unix_fds > 0) 03193 { 03194 /* Refuse to send fds on a connection that cannot handle 03195 them. Unfortunately we cannot return a proper error here, so 03196 the best we can is just return. */ 03197 CONNECTION_UNLOCK (connection); 03198 return; 03199 } 03200 03201 #endif 03202 03203 _dbus_connection_send_preallocated_and_unlock (connection, 03204 preallocated, 03205 message, client_serial); 03206 } 03207 03208 static dbus_bool_t 03209 _dbus_connection_send_unlocked_no_update (DBusConnection *connection, 03210 DBusMessage *message, 03211 dbus_uint32_t *client_serial) 03212 { 03213 DBusPreallocatedSend *preallocated; 03214 03215 _dbus_assert (connection != NULL); 03216 _dbus_assert (message != NULL); 03217 03218 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 03219 if (preallocated == NULL) 03220 return FALSE; 03221 03222 _dbus_connection_send_preallocated_unlocked_no_update (connection, 03223 preallocated, 03224 message, 03225 client_serial); 03226 return TRUE; 03227 } 03228 03256 dbus_bool_t 03257 dbus_connection_send (DBusConnection *connection, 03258 DBusMessage *message, 03259 dbus_uint32_t *serial) 03260 { 03261 _dbus_return_val_if_fail (connection != NULL, FALSE); 03262 _dbus_return_val_if_fail (message != NULL, FALSE); 03263 03264 CONNECTION_LOCK (connection); 03265 03266 #ifdef HAVE_UNIX_FD_PASSING 03267 03268 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03269 message->n_unix_fds > 0) 03270 { 03271 /* Refuse to send fds on a connection that cannot handle 03272 them. Unfortunately we cannot return a proper error here, so 03273 the best we can is just return. */ 03274 CONNECTION_UNLOCK (connection); 03275 return FALSE; 03276 } 03277 03278 #endif 03279 03280 return _dbus_connection_send_and_unlock (connection, 03281 message, 03282 serial); 03283 } 03284 03285 static dbus_bool_t 03286 reply_handler_timeout (void *data) 03287 { 03288 DBusConnection *connection; 03289 DBusDispatchStatus status; 03290 DBusPendingCall *pending = data; 03291 03292 connection = _dbus_pending_call_get_connection_and_lock (pending); 03293 _dbus_connection_ref_unlocked (connection); 03294 03295 _dbus_pending_call_queue_timeout_error_unlocked (pending, 03296 connection); 03297 _dbus_connection_remove_timeout_unlocked (connection, 03298 _dbus_pending_call_get_timeout_unlocked (pending)); 03299 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 03300 03301 _dbus_verbose ("middle\n"); 03302 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03303 03304 /* Unlocks, and calls out to user code */ 03305 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03306 dbus_connection_unref (connection); 03307 03308 return TRUE; 03309 } 03310 03353 dbus_bool_t 03354 dbus_connection_send_with_reply (DBusConnection *connection, 03355 DBusMessage *message, 03356 DBusPendingCall **pending_return, 03357 int timeout_milliseconds) 03358 { 03359 DBusPendingCall *pending; 03360 dbus_int32_t serial = -1; 03361 DBusDispatchStatus status; 03362 03363 _dbus_return_val_if_fail (connection != NULL, FALSE); 03364 _dbus_return_val_if_fail (message != NULL, FALSE); 03365 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03366 03367 if (pending_return) 03368 *pending_return = NULL; 03369 03370 CONNECTION_LOCK (connection); 03371 03372 #ifdef HAVE_UNIX_FD_PASSING 03373 03374 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03375 message->n_unix_fds > 0) 03376 { 03377 /* Refuse to send fds on a connection that cannot handle 03378 them. Unfortunately we cannot return a proper error here, so 03379 the best we can do is return TRUE but leave *pending_return 03380 as NULL. */ 03381 CONNECTION_UNLOCK (connection); 03382 return TRUE; 03383 } 03384 03385 #endif 03386 03387 if (!_dbus_connection_get_is_connected_unlocked (connection)) 03388 { 03389 CONNECTION_UNLOCK (connection); 03390 03391 return TRUE; 03392 } 03393 03394 pending = _dbus_pending_call_new_unlocked (connection, 03395 timeout_milliseconds, 03396 reply_handler_timeout); 03397 03398 if (pending == NULL) 03399 { 03400 CONNECTION_UNLOCK (connection); 03401 return FALSE; 03402 } 03403 03404 /* Assign a serial to the message */ 03405 serial = dbus_message_get_serial (message); 03406 if (serial == 0) 03407 { 03408 serial = _dbus_connection_get_next_client_serial (connection); 03409 dbus_message_set_serial (message, serial); 03410 } 03411 03412 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial)) 03413 goto error; 03414 03415 /* Insert the serial in the pending replies hash; 03416 * hash takes a refcount on DBusPendingCall. 03417 * Also, add the timeout. 03418 */ 03419 if (!_dbus_connection_attach_pending_call_unlocked (connection, 03420 pending)) 03421 goto error; 03422 03423 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL)) 03424 { 03425 _dbus_connection_detach_pending_call_and_unlock (connection, 03426 pending); 03427 goto error_unlocked; 03428 } 03429 03430 if (pending_return) 03431 *pending_return = pending; /* hand off refcount */ 03432 else 03433 { 03434 _dbus_connection_detach_pending_call_unlocked (connection, pending); 03435 /* we still have a ref to the pending call in this case, we unref 03436 * after unlocking, below 03437 */ 03438 } 03439 03440 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03441 03442 /* this calls out to user code */ 03443 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03444 03445 if (pending_return == NULL) 03446 dbus_pending_call_unref (pending); 03447 03448 return TRUE; 03449 03450 error: 03451 CONNECTION_UNLOCK (connection); 03452 error_unlocked: 03453 dbus_pending_call_unref (pending); 03454 return FALSE; 03455 } 03456 03489 DBusMessage* 03490 dbus_connection_send_with_reply_and_block (DBusConnection *connection, 03491 DBusMessage *message, 03492 int timeout_milliseconds, 03493 DBusError *error) 03494 { 03495 DBusMessage *reply; 03496 DBusPendingCall *pending; 03497 03498 _dbus_return_val_if_fail (connection != NULL, NULL); 03499 _dbus_return_val_if_fail (message != NULL, NULL); 03500 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL); 03501 _dbus_return_val_if_error_is_set (error, NULL); 03502 03503 #ifdef HAVE_UNIX_FD_PASSING 03504 03505 CONNECTION_LOCK (connection); 03506 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03507 message->n_unix_fds > 0) 03508 { 03509 CONNECTION_UNLOCK (connection); 03510 dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection."); 03511 return NULL; 03512 } 03513 CONNECTION_UNLOCK (connection); 03514 03515 #endif 03516 03517 if (!dbus_connection_send_with_reply (connection, message, 03518 &pending, timeout_milliseconds)) 03519 { 03520 _DBUS_SET_OOM (error); 03521 return NULL; 03522 } 03523 03524 if (pending == NULL) 03525 { 03526 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed"); 03527 return NULL; 03528 } 03529 03530 dbus_pending_call_block (pending); 03531 03532 reply = dbus_pending_call_steal_reply (pending); 03533 dbus_pending_call_unref (pending); 03534 03535 /* call_complete_and_unlock() called from pending_call_block() should 03536 * always fill this in. 03537 */ 03538 _dbus_assert (reply != NULL); 03539 03540 if (dbus_set_error_from_message (error, reply)) 03541 { 03542 dbus_message_unref (reply); 03543 return NULL; 03544 } 03545 else 03546 return reply; 03547 } 03548 03557 static DBusDispatchStatus 03558 _dbus_connection_flush_unlocked (DBusConnection *connection) 03559 { 03560 /* We have to specify DBUS_ITERATION_DO_READING here because 03561 * otherwise we could have two apps deadlock if they are both doing 03562 * a flush(), and the kernel buffers fill up. This could change the 03563 * dispatch status. 03564 */ 03565 DBusDispatchStatus status; 03566 03567 HAVE_LOCK_CHECK (connection); 03568 03569 while (connection->n_outgoing > 0 && 03570 _dbus_connection_get_is_connected_unlocked (connection)) 03571 { 03572 _dbus_verbose ("doing iteration in\n"); 03573 HAVE_LOCK_CHECK (connection); 03574 _dbus_connection_do_iteration_unlocked (connection, 03575 NULL, 03576 DBUS_ITERATION_DO_READING | 03577 DBUS_ITERATION_DO_WRITING | 03578 DBUS_ITERATION_BLOCK, 03579 -1); 03580 } 03581 03582 HAVE_LOCK_CHECK (connection); 03583 _dbus_verbose ("middle\n"); 03584 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03585 03586 HAVE_LOCK_CHECK (connection); 03587 return status; 03588 } 03589 03595 void 03596 dbus_connection_flush (DBusConnection *connection) 03597 { 03598 /* We have to specify DBUS_ITERATION_DO_READING here because 03599 * otherwise we could have two apps deadlock if they are both doing 03600 * a flush(), and the kernel buffers fill up. This could change the 03601 * dispatch status. 03602 */ 03603 DBusDispatchStatus status; 03604 03605 _dbus_return_if_fail (connection != NULL); 03606 03607 CONNECTION_LOCK (connection); 03608 03609 status = _dbus_connection_flush_unlocked (connection); 03610 03611 HAVE_LOCK_CHECK (connection); 03612 /* Unlocks and calls out to user code */ 03613 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03614 03615 _dbus_verbose ("end\n"); 03616 } 03617 03628 static dbus_bool_t 03629 _dbus_connection_read_write_dispatch (DBusConnection *connection, 03630 int timeout_milliseconds, 03631 dbus_bool_t dispatch) 03632 { 03633 DBusDispatchStatus dstatus; 03634 dbus_bool_t progress_possible; 03635 03636 /* Need to grab a ref here in case we're a private connection and 03637 * the user drops the last ref in a handler we call; see bug 03638 * https://bugs.freedesktop.org/show_bug.cgi?id=15635 03639 */ 03640 dbus_connection_ref (connection); 03641 dstatus = dbus_connection_get_dispatch_status (connection); 03642 03643 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS) 03644 { 03645 _dbus_verbose ("doing dispatch\n"); 03646 dbus_connection_dispatch (connection); 03647 CONNECTION_LOCK (connection); 03648 } 03649 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY) 03650 { 03651 _dbus_verbose ("pausing for memory\n"); 03652 _dbus_memory_pause_based_on_timeout (timeout_milliseconds); 03653 CONNECTION_LOCK (connection); 03654 } 03655 else 03656 { 03657 CONNECTION_LOCK (connection); 03658 if (_dbus_connection_get_is_connected_unlocked (connection)) 03659 { 03660 _dbus_verbose ("doing iteration\n"); 03661 _dbus_connection_do_iteration_unlocked (connection, 03662 NULL, 03663 DBUS_ITERATION_DO_READING | 03664 DBUS_ITERATION_DO_WRITING | 03665 DBUS_ITERATION_BLOCK, 03666 timeout_milliseconds); 03667 } 03668 } 03669 03670 HAVE_LOCK_CHECK (connection); 03671 /* If we can dispatch, we can make progress until the Disconnected message 03672 * has been processed; if we can only read/write, we can make progress 03673 * as long as the transport is open. 03674 */ 03675 if (dispatch) 03676 progress_possible = connection->n_incoming != 0 || 03677 connection->disconnect_message_link != NULL; 03678 else 03679 progress_possible = _dbus_connection_get_is_connected_unlocked (connection); 03680 03681 CONNECTION_UNLOCK (connection); 03682 03683 dbus_connection_unref (connection); 03684 03685 return progress_possible; /* TRUE if we can make more progress */ 03686 } 03687 03688 03723 dbus_bool_t 03724 dbus_connection_read_write_dispatch (DBusConnection *connection, 03725 int timeout_milliseconds) 03726 { 03727 _dbus_return_val_if_fail (connection != NULL, FALSE); 03728 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03729 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE); 03730 } 03731 03755 dbus_bool_t 03756 dbus_connection_read_write (DBusConnection *connection, 03757 int timeout_milliseconds) 03758 { 03759 _dbus_return_val_if_fail (connection != NULL, FALSE); 03760 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03761 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE); 03762 } 03763 03764 /* We need to call this anytime we pop the head of the queue, and then 03765 * update_dispatch_status_and_unlock needs to be called afterward 03766 * which will "process" the disconnected message and set 03767 * disconnected_message_processed. 03768 */ 03769 static void 03770 check_disconnected_message_arrived_unlocked (DBusConnection *connection, 03771 DBusMessage *head_of_queue) 03772 { 03773 HAVE_LOCK_CHECK (connection); 03774 03775 /* checking that the link is NULL is an optimization to avoid the is_signal call */ 03776 if (connection->disconnect_message_link == NULL && 03777 dbus_message_is_signal (head_of_queue, 03778 DBUS_INTERFACE_LOCAL, 03779 "Disconnected")) 03780 { 03781 connection->disconnected_message_arrived = TRUE; 03782 } 03783 } 03784 03804 DBusMessage* 03805 dbus_connection_borrow_message (DBusConnection *connection) 03806 { 03807 DBusDispatchStatus status; 03808 DBusMessage *message; 03809 03810 _dbus_return_val_if_fail (connection != NULL, NULL); 03811 03812 _dbus_verbose ("start\n"); 03813 03814 /* this is called for the side effect that it queues 03815 * up any messages from the transport 03816 */ 03817 status = dbus_connection_get_dispatch_status (connection); 03818 if (status != DBUS_DISPATCH_DATA_REMAINS) 03819 return NULL; 03820 03821 CONNECTION_LOCK (connection); 03822 03823 _dbus_connection_acquire_dispatch (connection); 03824 03825 /* While a message is outstanding, the dispatch lock is held */ 03826 _dbus_assert (connection->message_borrowed == NULL); 03827 03828 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages); 03829 03830 message = connection->message_borrowed; 03831 03832 check_disconnected_message_arrived_unlocked (connection, message); 03833 03834 /* Note that we KEEP the dispatch lock until the message is returned */ 03835 if (message == NULL) 03836 _dbus_connection_release_dispatch (connection); 03837 03838 CONNECTION_UNLOCK (connection); 03839 03840 _dbus_message_trace_ref (message, -1, -1, "dbus_connection_borrow_message"); 03841 03842 /* We don't update dispatch status until it's returned or stolen */ 03843 03844 return message; 03845 } 03846 03855 void 03856 dbus_connection_return_message (DBusConnection *connection, 03857 DBusMessage *message) 03858 { 03859 DBusDispatchStatus status; 03860 03861 _dbus_return_if_fail (connection != NULL); 03862 _dbus_return_if_fail (message != NULL); 03863 _dbus_return_if_fail (message == connection->message_borrowed); 03864 _dbus_return_if_fail (connection->dispatch_acquired); 03865 03866 CONNECTION_LOCK (connection); 03867 03868 _dbus_assert (message == connection->message_borrowed); 03869 03870 connection->message_borrowed = NULL; 03871 03872 _dbus_connection_release_dispatch (connection); 03873 03874 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03875 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03876 03877 _dbus_message_trace_ref (message, -1, -1, "dbus_connection_return_message"); 03878 } 03879 03889 void 03890 dbus_connection_steal_borrowed_message (DBusConnection *connection, 03891 DBusMessage *message) 03892 { 03893 DBusMessage *pop_message; 03894 DBusDispatchStatus status; 03895 03896 _dbus_return_if_fail (connection != NULL); 03897 _dbus_return_if_fail (message != NULL); 03898 _dbus_return_if_fail (message == connection->message_borrowed); 03899 _dbus_return_if_fail (connection->dispatch_acquired); 03900 03901 CONNECTION_LOCK (connection); 03902 03903 _dbus_assert (message == connection->message_borrowed); 03904 03905 pop_message = _dbus_list_pop_first (&connection->incoming_messages); 03906 _dbus_assert (message == pop_message); 03907 (void) pop_message; /* unused unless asserting */ 03908 03909 connection->n_incoming -= 1; 03910 03911 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n", 03912 message, connection->n_incoming); 03913 03914 connection->message_borrowed = NULL; 03915 03916 _dbus_connection_release_dispatch (connection); 03917 03918 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03919 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03920 _dbus_message_trace_ref (message, -1, -1, 03921 "dbus_connection_steal_borrowed_message"); 03922 } 03923 03924 /* See dbus_connection_pop_message, but requires the caller to own 03925 * the lock before calling. May drop the lock while running. 03926 */ 03927 static DBusList* 03928 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection) 03929 { 03930 HAVE_LOCK_CHECK (connection); 03931 03932 _dbus_assert (connection->message_borrowed == NULL); 03933 03934 if (connection->n_incoming > 0) 03935 { 03936 DBusList *link; 03937 03938 link = _dbus_list_pop_first_link (&connection->incoming_messages); 03939 connection->n_incoming -= 1; 03940 03941 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from incoming queue %p, %d incoming\n", 03942 link->data, 03943 dbus_message_type_to_string (dbus_message_get_type (link->data)), 03944 dbus_message_get_path (link->data) ? 03945 dbus_message_get_path (link->data) : 03946 "no path", 03947 dbus_message_get_interface (link->data) ? 03948 dbus_message_get_interface (link->data) : 03949 "no interface", 03950 dbus_message_get_member (link->data) ? 03951 dbus_message_get_member (link->data) : 03952 "no member", 03953 dbus_message_get_signature (link->data), 03954 connection, connection->n_incoming); 03955 03956 _dbus_message_trace_ref (link->data, -1, -1, 03957 "_dbus_connection_pop_message_link_unlocked"); 03958 03959 check_disconnected_message_arrived_unlocked (connection, link->data); 03960 03961 return link; 03962 } 03963 else 03964 return NULL; 03965 } 03966 03967 /* See dbus_connection_pop_message, but requires the caller to own 03968 * the lock before calling. May drop the lock while running. 03969 */ 03970 static DBusMessage* 03971 _dbus_connection_pop_message_unlocked (DBusConnection *connection) 03972 { 03973 DBusList *link; 03974 03975 HAVE_LOCK_CHECK (connection); 03976 03977 link = _dbus_connection_pop_message_link_unlocked (connection); 03978 03979 if (link != NULL) 03980 { 03981 DBusMessage *message; 03982 03983 message = link->data; 03984 03985 _dbus_list_free_link (link); 03986 03987 return message; 03988 } 03989 else 03990 return NULL; 03991 } 03992 03993 static void 03994 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection, 03995 DBusList *message_link) 03996 { 03997 HAVE_LOCK_CHECK (connection); 03998 03999 _dbus_assert (message_link != NULL); 04000 /* You can't borrow a message while a link is outstanding */ 04001 _dbus_assert (connection->message_borrowed == NULL); 04002 /* We had to have the dispatch lock across the pop/putback */ 04003 _dbus_assert (connection->dispatch_acquired); 04004 04005 _dbus_list_prepend_link (&connection->incoming_messages, 04006 message_link); 04007 connection->n_incoming += 1; 04008 04009 _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n", 04010 message_link->data, 04011 dbus_message_type_to_string (dbus_message_get_type (message_link->data)), 04012 dbus_message_get_interface (message_link->data) ? 04013 dbus_message_get_interface (message_link->data) : 04014 "no interface", 04015 dbus_message_get_member (message_link->data) ? 04016 dbus_message_get_member (message_link->data) : 04017 "no member", 04018 dbus_message_get_signature (message_link->data), 04019 connection, connection->n_incoming); 04020 04021 _dbus_message_trace_ref (message_link->data, -1, -1, 04022 "_dbus_connection_putback_message_link_unlocked"); 04023 } 04024 04044 DBusMessage* 04045 dbus_connection_pop_message (DBusConnection *connection) 04046 { 04047 DBusMessage *message; 04048 DBusDispatchStatus status; 04049 04050 _dbus_verbose ("start\n"); 04051 04052 /* this is called for the side effect that it queues 04053 * up any messages from the transport 04054 */ 04055 status = dbus_connection_get_dispatch_status (connection); 04056 if (status != DBUS_DISPATCH_DATA_REMAINS) 04057 return NULL; 04058 04059 CONNECTION_LOCK (connection); 04060 _dbus_connection_acquire_dispatch (connection); 04061 HAVE_LOCK_CHECK (connection); 04062 04063 message = _dbus_connection_pop_message_unlocked (connection); 04064 04065 _dbus_verbose ("Returning popped message %p\n", message); 04066 04067 _dbus_connection_release_dispatch (connection); 04068 04069 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04070 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04071 04072 return message; 04073 } 04074 04082 static void 04083 _dbus_connection_acquire_dispatch (DBusConnection *connection) 04084 { 04085 HAVE_LOCK_CHECK (connection); 04086 04087 _dbus_connection_ref_unlocked (connection); 04088 CONNECTION_UNLOCK (connection); 04089 04090 _dbus_verbose ("locking dispatch_mutex\n"); 04091 _dbus_cmutex_lock (connection->dispatch_mutex); 04092 04093 while (connection->dispatch_acquired) 04094 { 04095 _dbus_verbose ("waiting for dispatch to be acquirable\n"); 04096 _dbus_condvar_wait (connection->dispatch_cond, 04097 connection->dispatch_mutex); 04098 } 04099 04100 _dbus_assert (!connection->dispatch_acquired); 04101 04102 connection->dispatch_acquired = TRUE; 04103 04104 _dbus_verbose ("unlocking dispatch_mutex\n"); 04105 _dbus_cmutex_unlock (connection->dispatch_mutex); 04106 04107 CONNECTION_LOCK (connection); 04108 _dbus_connection_unref_unlocked (connection); 04109 } 04110 04118 static void 04119 _dbus_connection_release_dispatch (DBusConnection *connection) 04120 { 04121 HAVE_LOCK_CHECK (connection); 04122 04123 _dbus_verbose ("locking dispatch_mutex\n"); 04124 _dbus_cmutex_lock (connection->dispatch_mutex); 04125 04126 _dbus_assert (connection->dispatch_acquired); 04127 04128 connection->dispatch_acquired = FALSE; 04129 _dbus_condvar_wake_one (connection->dispatch_cond); 04130 04131 _dbus_verbose ("unlocking dispatch_mutex\n"); 04132 _dbus_cmutex_unlock (connection->dispatch_mutex); 04133 } 04134 04135 static void 04136 _dbus_connection_failed_pop (DBusConnection *connection, 04137 DBusList *message_link) 04138 { 04139 _dbus_list_prepend_link (&connection->incoming_messages, 04140 message_link); 04141 connection->n_incoming += 1; 04142 } 04143 04144 /* Note this may be called multiple times since we don't track whether we already did it */ 04145 static void 04146 notify_disconnected_unlocked (DBusConnection *connection) 04147 { 04148 HAVE_LOCK_CHECK (connection); 04149 04150 /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected 04151 * connection from dbus_bus_get(). We make the same guarantee for 04152 * dbus_connection_open() but in a different way since we don't want to 04153 * unref right here; we instead check for connectedness before returning 04154 * the connection from the hash. 04155 */ 04156 _dbus_bus_notify_shared_connection_disconnected_unlocked (connection); 04157 04158 /* Dump the outgoing queue, we aren't going to be able to 04159 * send it now, and we'd like accessors like 04160 * dbus_connection_get_outgoing_size() to be accurate. 04161 */ 04162 if (connection->n_outgoing > 0) 04163 { 04164 DBusList *link; 04165 04166 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n", 04167 connection->n_outgoing); 04168 04169 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages))) 04170 { 04171 _dbus_connection_message_sent_unlocked (connection, link->data); 04172 } 04173 } 04174 } 04175 04176 /* Note this may be called multiple times since we don't track whether we already did it */ 04177 static DBusDispatchStatus 04178 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection) 04179 { 04180 HAVE_LOCK_CHECK (connection); 04181 04182 if (connection->disconnect_message_link != NULL) 04183 { 04184 _dbus_verbose ("Sending disconnect message\n"); 04185 04186 /* If we have pending calls, queue their timeouts - we want the Disconnected 04187 * to be the last message, after these timeouts. 04188 */ 04189 connection_timeout_and_complete_all_pending_calls_unlocked (connection); 04190 04191 /* We haven't sent the disconnect message already, 04192 * and all real messages have been queued up. 04193 */ 04194 _dbus_connection_queue_synthesized_message_link (connection, 04195 connection->disconnect_message_link); 04196 connection->disconnect_message_link = NULL; 04197 04198 return DBUS_DISPATCH_DATA_REMAINS; 04199 } 04200 04201 return DBUS_DISPATCH_COMPLETE; 04202 } 04203 04204 static DBusDispatchStatus 04205 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection) 04206 { 04207 HAVE_LOCK_CHECK (connection); 04208 04209 if (connection->n_incoming > 0) 04210 return DBUS_DISPATCH_DATA_REMAINS; 04211 else if (!_dbus_transport_queue_messages (connection->transport)) 04212 return DBUS_DISPATCH_NEED_MEMORY; 04213 else 04214 { 04215 DBusDispatchStatus status; 04216 dbus_bool_t is_connected; 04217 04218 status = _dbus_transport_get_dispatch_status (connection->transport); 04219 is_connected = _dbus_transport_get_is_connected (connection->transport); 04220 04221 _dbus_verbose ("dispatch status = %s is_connected = %d\n", 04222 DISPATCH_STATUS_NAME (status), is_connected); 04223 04224 if (!is_connected) 04225 { 04226 /* It's possible this would be better done by having an explicit 04227 * notification from _dbus_transport_disconnect() that would 04228 * synchronously do this, instead of waiting for the next dispatch 04229 * status check. However, probably not good to change until it causes 04230 * a problem. 04231 */ 04232 notify_disconnected_unlocked (connection); 04233 04234 /* I'm not sure this is needed; the idea is that we want to 04235 * queue the Disconnected only after we've read all the 04236 * messages, but if we're disconnected maybe we are guaranteed 04237 * to have read them all ? 04238 */ 04239 if (status == DBUS_DISPATCH_COMPLETE) 04240 status = notify_disconnected_and_dispatch_complete_unlocked (connection); 04241 } 04242 04243 if (status != DBUS_DISPATCH_COMPLETE) 04244 return status; 04245 else if (connection->n_incoming > 0) 04246 return DBUS_DISPATCH_DATA_REMAINS; 04247 else 04248 return DBUS_DISPATCH_COMPLETE; 04249 } 04250 } 04251 04252 static void 04253 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection, 04254 DBusDispatchStatus new_status) 04255 { 04256 dbus_bool_t changed; 04257 DBusDispatchStatusFunction function; 04258 void *data; 04259 04260 HAVE_LOCK_CHECK (connection); 04261 04262 _dbus_connection_ref_unlocked (connection); 04263 04264 changed = new_status != connection->last_dispatch_status; 04265 04266 connection->last_dispatch_status = new_status; 04267 04268 function = connection->dispatch_status_function; 04269 data = connection->dispatch_status_data; 04270 04271 if (connection->disconnected_message_arrived && 04272 !connection->disconnected_message_processed) 04273 { 04274 connection->disconnected_message_processed = TRUE; 04275 04276 /* this does an unref, but we have a ref 04277 * so we should not run the finalizer here 04278 * inside the lock. 04279 */ 04280 connection_forget_shared_unlocked (connection); 04281 04282 if (connection->exit_on_disconnect) 04283 { 04284 CONNECTION_UNLOCK (connection); 04285 04286 _dbus_verbose ("Exiting on Disconnected signal\n"); 04287 _dbus_exit (1); 04288 _dbus_assert_not_reached ("Call to exit() returned"); 04289 } 04290 } 04291 04292 /* We drop the lock */ 04293 CONNECTION_UNLOCK (connection); 04294 04295 if (changed && function) 04296 { 04297 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n", 04298 connection, new_status, 04299 DISPATCH_STATUS_NAME (new_status)); 04300 (* function) (connection, new_status, data); 04301 } 04302 04303 dbus_connection_unref (connection); 04304 } 04305 04331 DBusDispatchStatus 04332 dbus_connection_get_dispatch_status (DBusConnection *connection) 04333 { 04334 DBusDispatchStatus status; 04335 04336 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE); 04337 04338 _dbus_verbose ("start\n"); 04339 04340 CONNECTION_LOCK (connection); 04341 04342 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04343 04344 CONNECTION_UNLOCK (connection); 04345 04346 return status; 04347 } 04348 04352 static DBusHandlerResult 04353 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection, 04354 DBusMessage *message) 04355 { 04356 dbus_bool_t sent = FALSE; 04357 DBusMessage *ret = NULL; 04358 DBusList *expire_link; 04359 04360 if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL) 04361 { 04362 /* This means we're letting the bus route this message */ 04363 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04364 } 04365 04366 if (!dbus_message_has_interface (message, DBUS_INTERFACE_PEER)) 04367 { 04368 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04369 } 04370 04371 /* Preallocate a linked-list link, so that if we need to dispose of a 04372 * message, we can attach it to the expired list */ 04373 expire_link = _dbus_list_alloc_link (NULL); 04374 04375 if (!expire_link) 04376 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04377 04378 if (dbus_message_is_method_call (message, 04379 DBUS_INTERFACE_PEER, 04380 "Ping")) 04381 { 04382 ret = dbus_message_new_method_return (message); 04383 if (ret == NULL) 04384 goto out; 04385 04386 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04387 } 04388 else if (dbus_message_is_method_call (message, 04389 DBUS_INTERFACE_PEER, 04390 "GetMachineId")) 04391 { 04392 DBusString uuid; 04393 04394 ret = dbus_message_new_method_return (message); 04395 if (ret == NULL) 04396 goto out; 04397 04398 _dbus_string_init (&uuid); 04399 if (_dbus_get_local_machine_uuid_encoded (&uuid)) 04400 { 04401 const char *v_STRING = _dbus_string_get_const_data (&uuid); 04402 if (dbus_message_append_args (ret, 04403 DBUS_TYPE_STRING, &v_STRING, 04404 DBUS_TYPE_INVALID)) 04405 { 04406 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04407 } 04408 } 04409 _dbus_string_free (&uuid); 04410 } 04411 else 04412 { 04413 /* We need to bounce anything else with this interface, otherwise apps 04414 * could start extending the interface and when we added extensions 04415 * here to DBusConnection we'd break those apps. 04416 */ 04417 ret = dbus_message_new_error (message, 04418 DBUS_ERROR_UNKNOWN_METHOD, 04419 "Unknown method invoked on org.freedesktop.DBus.Peer interface"); 04420 if (ret == NULL) 04421 goto out; 04422 04423 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04424 } 04425 04426 out: 04427 if (ret == NULL) 04428 { 04429 _dbus_list_free_link (expire_link); 04430 } 04431 else 04432 { 04433 /* It'll be safe to unref the reply when we unlock */ 04434 expire_link->data = ret; 04435 _dbus_list_prepend_link (&connection->expired_messages, expire_link); 04436 } 04437 04438 if (!sent) 04439 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04440 04441 return DBUS_HANDLER_RESULT_HANDLED; 04442 } 04443 04450 static DBusHandlerResult 04451 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection, 04452 DBusMessage *message) 04453 { 04454 /* We just run one filter for now but have the option to run more 04455 if the spec calls for it in the future */ 04456 04457 return _dbus_connection_peer_filter_unlocked_no_update (connection, message); 04458 } 04459 04502 DBusDispatchStatus 04503 dbus_connection_dispatch (DBusConnection *connection) 04504 { 04505 DBusMessage *message; 04506 DBusList *link, *filter_list_copy, *message_link; 04507 DBusHandlerResult result; 04508 DBusPendingCall *pending; 04509 dbus_int32_t reply_serial; 04510 DBusDispatchStatus status; 04511 dbus_bool_t found_object; 04512 04513 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE); 04514 04515 _dbus_verbose ("\n"); 04516 04517 CONNECTION_LOCK (connection); 04518 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04519 if (status != DBUS_DISPATCH_DATA_REMAINS) 04520 { 04521 /* unlocks and calls out to user code */ 04522 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04523 return status; 04524 } 04525 04526 /* We need to ref the connection since the callback could potentially 04527 * drop the last ref to it 04528 */ 04529 _dbus_connection_ref_unlocked (connection); 04530 04531 _dbus_connection_acquire_dispatch (connection); 04532 HAVE_LOCK_CHECK (connection); 04533 04534 message_link = _dbus_connection_pop_message_link_unlocked (connection); 04535 if (message_link == NULL) 04536 { 04537 /* another thread dispatched our stuff */ 04538 04539 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n"); 04540 04541 _dbus_connection_release_dispatch (connection); 04542 04543 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04544 04545 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04546 04547 dbus_connection_unref (connection); 04548 04549 return status; 04550 } 04551 04552 message = message_link->data; 04553 04554 _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n", 04555 message, 04556 dbus_message_type_to_string (dbus_message_get_type (message)), 04557 dbus_message_get_interface (message) ? 04558 dbus_message_get_interface (message) : 04559 "no interface", 04560 dbus_message_get_member (message) ? 04561 dbus_message_get_member (message) : 04562 "no member", 04563 dbus_message_get_signature (message)); 04564 04565 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04566 04567 /* Pending call handling must be first, because if you do 04568 * dbus_connection_send_with_reply_and_block() or 04569 * dbus_pending_call_block() then no handlers/filters will be run on 04570 * the reply. We want consistent semantics in the case where we 04571 * dbus_connection_dispatch() the reply. 04572 */ 04573 04574 reply_serial = dbus_message_get_reply_serial (message); 04575 pending = _dbus_hash_table_lookup_int (connection->pending_replies, 04576 reply_serial); 04577 if (pending) 04578 { 04579 _dbus_verbose ("Dispatching a pending reply\n"); 04580 complete_pending_call_and_unlock (connection, pending, message); 04581 pending = NULL; /* it's probably unref'd */ 04582 04583 CONNECTION_LOCK (connection); 04584 _dbus_verbose ("pending call completed in dispatch\n"); 04585 result = DBUS_HANDLER_RESULT_HANDLED; 04586 goto out; 04587 } 04588 04589 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message); 04590 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04591 goto out; 04592 04593 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy)) 04594 { 04595 _dbus_connection_release_dispatch (connection); 04596 HAVE_LOCK_CHECK (connection); 04597 04598 _dbus_connection_failed_pop (connection, message_link); 04599 04600 /* unlocks and calls user code */ 04601 _dbus_connection_update_dispatch_status_and_unlock (connection, 04602 DBUS_DISPATCH_NEED_MEMORY); 04603 dbus_connection_unref (connection); 04604 04605 return DBUS_DISPATCH_NEED_MEMORY; 04606 } 04607 04608 _dbus_list_foreach (&filter_list_copy, 04609 (DBusForeachFunction)_dbus_message_filter_ref, 04610 NULL); 04611 04612 /* We're still protected from dispatch() reentrancy here 04613 * since we acquired the dispatcher 04614 */ 04615 CONNECTION_UNLOCK (connection); 04616 04617 link = _dbus_list_get_first_link (&filter_list_copy); 04618 while (link != NULL) 04619 { 04620 DBusMessageFilter *filter = link->data; 04621 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link); 04622 04623 if (filter->function == NULL) 04624 { 04625 _dbus_verbose (" filter was removed in a callback function\n"); 04626 link = next; 04627 continue; 04628 } 04629 04630 _dbus_verbose (" running filter on message %p\n", message); 04631 result = (* filter->function) (connection, message, filter->user_data); 04632 04633 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04634 break; 04635 04636 link = next; 04637 } 04638 04639 _dbus_list_foreach (&filter_list_copy, 04640 (DBusForeachFunction)_dbus_message_filter_unref, 04641 NULL); 04642 _dbus_list_clear (&filter_list_copy); 04643 04644 CONNECTION_LOCK (connection); 04645 04646 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) 04647 { 04648 _dbus_verbose ("No memory\n"); 04649 goto out; 04650 } 04651 else if (result == DBUS_HANDLER_RESULT_HANDLED) 04652 { 04653 _dbus_verbose ("filter handled message in dispatch\n"); 04654 goto out; 04655 } 04656 04657 /* We're still protected from dispatch() reentrancy here 04658 * since we acquired the dispatcher 04659 */ 04660 _dbus_verbose (" running object path dispatch on message %p (%s %s %s '%s')\n", 04661 message, 04662 dbus_message_type_to_string (dbus_message_get_type (message)), 04663 dbus_message_get_interface (message) ? 04664 dbus_message_get_interface (message) : 04665 "no interface", 04666 dbus_message_get_member (message) ? 04667 dbus_message_get_member (message) : 04668 "no member", 04669 dbus_message_get_signature (message)); 04670 04671 HAVE_LOCK_CHECK (connection); 04672 result = _dbus_object_tree_dispatch_and_unlock (connection->objects, 04673 message, 04674 &found_object); 04675 04676 CONNECTION_LOCK (connection); 04677 04678 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04679 { 04680 _dbus_verbose ("object tree handled message in dispatch\n"); 04681 goto out; 04682 } 04683 04684 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL) 04685 { 04686 DBusMessage *reply; 04687 DBusString str; 04688 DBusPreallocatedSend *preallocated; 04689 DBusList *expire_link; 04690 04691 _dbus_verbose (" sending error %s\n", 04692 DBUS_ERROR_UNKNOWN_METHOD); 04693 04694 if (!_dbus_string_init (&str)) 04695 { 04696 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04697 _dbus_verbose ("no memory for error string in dispatch\n"); 04698 goto out; 04699 } 04700 04701 if (!_dbus_string_append_printf (&str, 04702 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n", 04703 dbus_message_get_member (message), 04704 dbus_message_get_signature (message), 04705 dbus_message_get_interface (message))) 04706 { 04707 _dbus_string_free (&str); 04708 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04709 _dbus_verbose ("no memory for error string in dispatch\n"); 04710 goto out; 04711 } 04712 04713 reply = dbus_message_new_error (message, 04714 found_object ? DBUS_ERROR_UNKNOWN_METHOD : DBUS_ERROR_UNKNOWN_OBJECT, 04715 _dbus_string_get_const_data (&str)); 04716 _dbus_string_free (&str); 04717 04718 if (reply == NULL) 04719 { 04720 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04721 _dbus_verbose ("no memory for error reply in dispatch\n"); 04722 goto out; 04723 } 04724 04725 expire_link = _dbus_list_alloc_link (reply); 04726 04727 if (expire_link == NULL) 04728 { 04729 dbus_message_unref (reply); 04730 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04731 _dbus_verbose ("no memory for error send in dispatch\n"); 04732 goto out; 04733 } 04734 04735 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 04736 04737 if (preallocated == NULL) 04738 { 04739 _dbus_list_free_link (expire_link); 04740 /* It's OK that this is finalized, because it hasn't been seen by 04741 * anything that could attach user callbacks */ 04742 dbus_message_unref (reply); 04743 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04744 _dbus_verbose ("no memory for error send in dispatch\n"); 04745 goto out; 04746 } 04747 04748 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated, 04749 reply, NULL); 04750 /* reply will be freed when we release the lock */ 04751 _dbus_list_prepend_link (&connection->expired_messages, expire_link); 04752 04753 result = DBUS_HANDLER_RESULT_HANDLED; 04754 } 04755 04756 _dbus_verbose (" done dispatching %p (%s %s %s '%s') on connection %p\n", message, 04757 dbus_message_type_to_string (dbus_message_get_type (message)), 04758 dbus_message_get_interface (message) ? 04759 dbus_message_get_interface (message) : 04760 "no interface", 04761 dbus_message_get_member (message) ? 04762 dbus_message_get_member (message) : 04763 "no member", 04764 dbus_message_get_signature (message), 04765 connection); 04766 04767 out: 04768 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) 04769 { 04770 _dbus_verbose ("out of memory\n"); 04771 04772 /* Put message back, and we'll start over. 04773 * Yes this means handlers must be idempotent if they 04774 * don't return HANDLED; c'est la vie. 04775 */ 04776 _dbus_connection_putback_message_link_unlocked (connection, 04777 message_link); 04778 /* now we don't want to free them */ 04779 message_link = NULL; 04780 message = NULL; 04781 } 04782 else 04783 { 04784 _dbus_verbose (" ... done dispatching\n"); 04785 } 04786 04787 _dbus_connection_release_dispatch (connection); 04788 HAVE_LOCK_CHECK (connection); 04789 04790 if (message != NULL) 04791 { 04792 /* We don't want this message to count in maximum message limits when 04793 * computing the dispatch status, below. We have to drop the lock 04794 * temporarily, because finalizing a message can trigger callbacks. 04795 * 04796 * We have a reference to the connection, and we don't use any cached 04797 * pointers to the connection's internals below this point, so it should 04798 * be safe to drop the lock and take it back. */ 04799 CONNECTION_UNLOCK (connection); 04800 dbus_message_unref (message); 04801 CONNECTION_LOCK (connection); 04802 } 04803 04804 if (message_link != NULL) 04805 _dbus_list_free_link (message_link); 04806 04807 _dbus_verbose ("before final status update\n"); 04808 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04809 04810 /* unlocks and calls user code */ 04811 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04812 04813 dbus_connection_unref (connection); 04814 04815 return status; 04816 } 04817 04879 dbus_bool_t 04880 dbus_connection_set_watch_functions (DBusConnection *connection, 04881 DBusAddWatchFunction add_function, 04882 DBusRemoveWatchFunction remove_function, 04883 DBusWatchToggledFunction toggled_function, 04884 void *data, 04885 DBusFreeFunction free_data_function) 04886 { 04887 dbus_bool_t retval; 04888 04889 _dbus_return_val_if_fail (connection != NULL, FALSE); 04890 04891 CONNECTION_LOCK (connection); 04892 04893 retval = _dbus_watch_list_set_functions (connection->watches, 04894 add_function, remove_function, 04895 toggled_function, 04896 data, free_data_function); 04897 04898 CONNECTION_UNLOCK (connection); 04899 04900 return retval; 04901 } 04902 04942 dbus_bool_t 04943 dbus_connection_set_timeout_functions (DBusConnection *connection, 04944 DBusAddTimeoutFunction add_function, 04945 DBusRemoveTimeoutFunction remove_function, 04946 DBusTimeoutToggledFunction toggled_function, 04947 void *data, 04948 DBusFreeFunction free_data_function) 04949 { 04950 dbus_bool_t retval; 04951 04952 _dbus_return_val_if_fail (connection != NULL, FALSE); 04953 04954 CONNECTION_LOCK (connection); 04955 04956 retval = _dbus_timeout_list_set_functions (connection->timeouts, 04957 add_function, remove_function, 04958 toggled_function, 04959 data, free_data_function); 04960 04961 CONNECTION_UNLOCK (connection); 04962 04963 return retval; 04964 } 04965 04980 void 04981 dbus_connection_set_wakeup_main_function (DBusConnection *connection, 04982 DBusWakeupMainFunction wakeup_main_function, 04983 void *data, 04984 DBusFreeFunction free_data_function) 04985 { 04986 void *old_data; 04987 DBusFreeFunction old_free_data; 04988 04989 _dbus_return_if_fail (connection != NULL); 04990 04991 CONNECTION_LOCK (connection); 04992 old_data = connection->wakeup_main_data; 04993 old_free_data = connection->free_wakeup_main_data; 04994 04995 connection->wakeup_main_function = wakeup_main_function; 04996 connection->wakeup_main_data = data; 04997 connection->free_wakeup_main_data = free_data_function; 04998 04999 CONNECTION_UNLOCK (connection); 05000 05001 /* Callback outside the lock */ 05002 if (old_free_data) 05003 (*old_free_data) (old_data); 05004 } 05005 05026 void 05027 dbus_connection_set_dispatch_status_function (DBusConnection *connection, 05028 DBusDispatchStatusFunction function, 05029 void *data, 05030 DBusFreeFunction free_data_function) 05031 { 05032 void *old_data; 05033 DBusFreeFunction old_free_data; 05034 05035 _dbus_return_if_fail (connection != NULL); 05036 05037 CONNECTION_LOCK (connection); 05038 old_data = connection->dispatch_status_data; 05039 old_free_data = connection->free_dispatch_status_data; 05040 05041 connection->dispatch_status_function = function; 05042 connection->dispatch_status_data = data; 05043 connection->free_dispatch_status_data = free_data_function; 05044 05045 CONNECTION_UNLOCK (connection); 05046 05047 /* Callback outside the lock */ 05048 if (old_free_data) 05049 (*old_free_data) (old_data); 05050 } 05051 05071 dbus_bool_t 05072 dbus_connection_get_unix_fd (DBusConnection *connection, 05073 int *fd) 05074 { 05075 _dbus_return_val_if_fail (connection != NULL, FALSE); 05076 _dbus_return_val_if_fail (connection->transport != NULL, FALSE); 05077 05078 #ifdef DBUS_WIN 05079 /* FIXME do this on a lower level */ 05080 return FALSE; 05081 #endif 05082 05083 return dbus_connection_get_socket(connection, fd); 05084 } 05085 05101 dbus_bool_t 05102 dbus_connection_get_socket(DBusConnection *connection, 05103 int *fd) 05104 { 05105 dbus_bool_t retval; 05106 05107 _dbus_return_val_if_fail (connection != NULL, FALSE); 05108 _dbus_return_val_if_fail (connection->transport != NULL, FALSE); 05109 05110 CONNECTION_LOCK (connection); 05111 05112 retval = _dbus_transport_get_socket_fd (connection->transport, 05113 fd); 05114 05115 CONNECTION_UNLOCK (connection); 05116 05117 return retval; 05118 } 05119 05120 05143 dbus_bool_t 05144 dbus_connection_get_unix_user (DBusConnection *connection, 05145 unsigned long *uid) 05146 { 05147 dbus_bool_t result; 05148 05149 _dbus_return_val_if_fail (connection != NULL, FALSE); 05150 _dbus_return_val_if_fail (uid != NULL, FALSE); 05151 05152 CONNECTION_LOCK (connection); 05153 05154 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05155 result = FALSE; 05156 else 05157 result = _dbus_transport_get_unix_user (connection->transport, 05158 uid); 05159 05160 #ifdef DBUS_WIN 05161 _dbus_assert (!result); 05162 #endif 05163 05164 CONNECTION_UNLOCK (connection); 05165 05166 return result; 05167 } 05168 05179 dbus_bool_t 05180 dbus_connection_get_unix_process_id (DBusConnection *connection, 05181 unsigned long *pid) 05182 { 05183 dbus_bool_t result; 05184 05185 _dbus_return_val_if_fail (connection != NULL, FALSE); 05186 _dbus_return_val_if_fail (pid != NULL, FALSE); 05187 05188 CONNECTION_LOCK (connection); 05189 05190 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05191 result = FALSE; 05192 else 05193 result = _dbus_transport_get_unix_process_id (connection->transport, 05194 pid); 05195 05196 CONNECTION_UNLOCK (connection); 05197 05198 return result; 05199 } 05200 05211 dbus_bool_t 05212 dbus_connection_get_adt_audit_session_data (DBusConnection *connection, 05213 void **data, 05214 dbus_int32_t *data_size) 05215 { 05216 dbus_bool_t result; 05217 05218 _dbus_return_val_if_fail (connection != NULL, FALSE); 05219 _dbus_return_val_if_fail (data != NULL, FALSE); 05220 _dbus_return_val_if_fail (data_size != NULL, FALSE); 05221 05222 CONNECTION_LOCK (connection); 05223 05224 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05225 result = FALSE; 05226 else 05227 result = _dbus_transport_get_adt_audit_session_data (connection->transport, 05228 data, 05229 data_size); 05230 CONNECTION_UNLOCK (connection); 05231 05232 return result; 05233 } 05234 05257 void 05258 dbus_connection_set_unix_user_function (DBusConnection *connection, 05259 DBusAllowUnixUserFunction function, 05260 void *data, 05261 DBusFreeFunction free_data_function) 05262 { 05263 void *old_data = NULL; 05264 DBusFreeFunction old_free_function = NULL; 05265 05266 _dbus_return_if_fail (connection != NULL); 05267 05268 CONNECTION_LOCK (connection); 05269 _dbus_transport_set_unix_user_function (connection->transport, 05270 function, data, free_data_function, 05271 &old_data, &old_free_function); 05272 CONNECTION_UNLOCK (connection); 05273 05274 if (old_free_function != NULL) 05275 (* old_free_function) (old_data); 05276 } 05277 05309 dbus_bool_t 05310 dbus_connection_get_windows_user (DBusConnection *connection, 05311 char **windows_sid_p) 05312 { 05313 dbus_bool_t result; 05314 05315 _dbus_return_val_if_fail (connection != NULL, FALSE); 05316 _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE); 05317 05318 CONNECTION_LOCK (connection); 05319 05320 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05321 result = FALSE; 05322 else 05323 result = _dbus_transport_get_windows_user (connection->transport, 05324 windows_sid_p); 05325 05326 #ifdef DBUS_UNIX 05327 _dbus_assert (!result); 05328 #endif 05329 05330 CONNECTION_UNLOCK (connection); 05331 05332 return result; 05333 } 05334 05356 void 05357 dbus_connection_set_windows_user_function (DBusConnection *connection, 05358 DBusAllowWindowsUserFunction function, 05359 void *data, 05360 DBusFreeFunction free_data_function) 05361 { 05362 void *old_data = NULL; 05363 DBusFreeFunction old_free_function = NULL; 05364 05365 _dbus_return_if_fail (connection != NULL); 05366 05367 CONNECTION_LOCK (connection); 05368 _dbus_transport_set_windows_user_function (connection->transport, 05369 function, data, free_data_function, 05370 &old_data, &old_free_function); 05371 CONNECTION_UNLOCK (connection); 05372 05373 if (old_free_function != NULL) 05374 (* old_free_function) (old_data); 05375 } 05376 05403 void 05404 dbus_connection_set_allow_anonymous (DBusConnection *connection, 05405 dbus_bool_t value) 05406 { 05407 _dbus_return_if_fail (connection != NULL); 05408 05409 CONNECTION_LOCK (connection); 05410 _dbus_transport_set_allow_anonymous (connection->transport, value); 05411 CONNECTION_UNLOCK (connection); 05412 } 05413 05431 void 05432 dbus_connection_set_route_peer_messages (DBusConnection *connection, 05433 dbus_bool_t value) 05434 { 05435 _dbus_return_if_fail (connection != NULL); 05436 05437 CONNECTION_LOCK (connection); 05438 connection->route_peer_messages = TRUE; 05439 CONNECTION_UNLOCK (connection); 05440 } 05441 05463 dbus_bool_t 05464 dbus_connection_add_filter (DBusConnection *connection, 05465 DBusHandleMessageFunction function, 05466 void *user_data, 05467 DBusFreeFunction free_data_function) 05468 { 05469 DBusMessageFilter *filter; 05470 05471 _dbus_return_val_if_fail (connection != NULL, FALSE); 05472 _dbus_return_val_if_fail (function != NULL, FALSE); 05473 05474 filter = dbus_new0 (DBusMessageFilter, 1); 05475 if (filter == NULL) 05476 return FALSE; 05477 05478 _dbus_atomic_inc (&filter->refcount); 05479 05480 CONNECTION_LOCK (connection); 05481 05482 if (!_dbus_list_append (&connection->filter_list, 05483 filter)) 05484 { 05485 _dbus_message_filter_unref (filter); 05486 CONNECTION_UNLOCK (connection); 05487 return FALSE; 05488 } 05489 05490 /* Fill in filter after all memory allocated, 05491 * so we don't run the free_user_data_function 05492 * if the add_filter() fails 05493 */ 05494 05495 filter->function = function; 05496 filter->user_data = user_data; 05497 filter->free_user_data_function = free_data_function; 05498 05499 CONNECTION_UNLOCK (connection); 05500 return TRUE; 05501 } 05502 05515 void 05516 dbus_connection_remove_filter (DBusConnection *connection, 05517 DBusHandleMessageFunction function, 05518 void *user_data) 05519 { 05520 DBusList *link; 05521 DBusMessageFilter *filter; 05522 05523 _dbus_return_if_fail (connection != NULL); 05524 _dbus_return_if_fail (function != NULL); 05525 05526 CONNECTION_LOCK (connection); 05527 05528 filter = NULL; 05529 05530 link = _dbus_list_get_last_link (&connection->filter_list); 05531 while (link != NULL) 05532 { 05533 filter = link->data; 05534 05535 if (filter->function == function && 05536 filter->user_data == user_data) 05537 { 05538 _dbus_list_remove_link (&connection->filter_list, link); 05539 filter->function = NULL; 05540 05541 break; 05542 } 05543 05544 link = _dbus_list_get_prev_link (&connection->filter_list, link); 05545 filter = NULL; 05546 } 05547 05548 CONNECTION_UNLOCK (connection); 05549 05550 #ifndef DBUS_DISABLE_CHECKS 05551 if (filter == NULL) 05552 { 05553 _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n", 05554 function, user_data); 05555 return; 05556 } 05557 #endif 05558 05559 /* Call application code */ 05560 if (filter->free_user_data_function) 05561 (* filter->free_user_data_function) (filter->user_data); 05562 05563 filter->free_user_data_function = NULL; 05564 filter->user_data = NULL; 05565 05566 _dbus_message_filter_unref (filter); 05567 } 05568 05584 static dbus_bool_t 05585 _dbus_connection_register_object_path (DBusConnection *connection, 05586 dbus_bool_t fallback, 05587 const char *path, 05588 const DBusObjectPathVTable *vtable, 05589 void *user_data, 05590 DBusError *error) 05591 { 05592 char **decomposed_path; 05593 dbus_bool_t retval; 05594 05595 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05596 return FALSE; 05597 05598 CONNECTION_LOCK (connection); 05599 05600 retval = _dbus_object_tree_register (connection->objects, 05601 fallback, 05602 (const char **) decomposed_path, vtable, 05603 user_data, error); 05604 05605 CONNECTION_UNLOCK (connection); 05606 05607 dbus_free_string_array (decomposed_path); 05608 05609 return retval; 05610 } 05611 05624 dbus_bool_t 05625 dbus_connection_try_register_object_path (DBusConnection *connection, 05626 const char *path, 05627 const DBusObjectPathVTable *vtable, 05628 void *user_data, 05629 DBusError *error) 05630 { 05631 _dbus_return_val_if_fail (connection != NULL, FALSE); 05632 _dbus_return_val_if_fail (path != NULL, FALSE); 05633 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05634 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05635 05636 return _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, error); 05637 } 05638 05654 dbus_bool_t 05655 dbus_connection_register_object_path (DBusConnection *connection, 05656 const char *path, 05657 const DBusObjectPathVTable *vtable, 05658 void *user_data) 05659 { 05660 dbus_bool_t retval; 05661 DBusError error = DBUS_ERROR_INIT; 05662 05663 _dbus_return_val_if_fail (connection != NULL, FALSE); 05664 _dbus_return_val_if_fail (path != NULL, FALSE); 05665 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05666 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05667 05668 retval = _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, &error); 05669 05670 if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE)) 05671 { 05672 _dbus_warn ("%s\n", error.message); 05673 dbus_error_free (&error); 05674 return FALSE; 05675 } 05676 05677 return retval; 05678 } 05679 05694 dbus_bool_t 05695 dbus_connection_try_register_fallback (DBusConnection *connection, 05696 const char *path, 05697 const DBusObjectPathVTable *vtable, 05698 void *user_data, 05699 DBusError *error) 05700 { 05701 _dbus_return_val_if_fail (connection != NULL, FALSE); 05702 _dbus_return_val_if_fail (path != NULL, FALSE); 05703 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05704 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05705 05706 return _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, error); 05707 } 05708 05726 dbus_bool_t 05727 dbus_connection_register_fallback (DBusConnection *connection, 05728 const char *path, 05729 const DBusObjectPathVTable *vtable, 05730 void *user_data) 05731 { 05732 dbus_bool_t retval; 05733 DBusError error = DBUS_ERROR_INIT; 05734 05735 _dbus_return_val_if_fail (connection != NULL, FALSE); 05736 _dbus_return_val_if_fail (path != NULL, FALSE); 05737 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05738 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05739 05740 retval = _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, &error); 05741 05742 if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE)) 05743 { 05744 _dbus_warn ("%s\n", error.message); 05745 dbus_error_free (&error); 05746 return FALSE; 05747 } 05748 05749 return retval; 05750 } 05751 05761 dbus_bool_t 05762 dbus_connection_unregister_object_path (DBusConnection *connection, 05763 const char *path) 05764 { 05765 char **decomposed_path; 05766 05767 _dbus_return_val_if_fail (connection != NULL, FALSE); 05768 _dbus_return_val_if_fail (path != NULL, FALSE); 05769 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05770 05771 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05772 return FALSE; 05773 05774 CONNECTION_LOCK (connection); 05775 05776 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path); 05777 05778 dbus_free_string_array (decomposed_path); 05779 05780 return TRUE; 05781 } 05782 05793 dbus_bool_t 05794 dbus_connection_get_object_path_data (DBusConnection *connection, 05795 const char *path, 05796 void **data_p) 05797 { 05798 char **decomposed_path; 05799 05800 _dbus_return_val_if_fail (connection != NULL, FALSE); 05801 _dbus_return_val_if_fail (path != NULL, FALSE); 05802 _dbus_return_val_if_fail (data_p != NULL, FALSE); 05803 05804 *data_p = NULL; 05805 05806 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05807 return FALSE; 05808 05809 CONNECTION_LOCK (connection); 05810 05811 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path); 05812 05813 CONNECTION_UNLOCK (connection); 05814 05815 dbus_free_string_array (decomposed_path); 05816 05817 return TRUE; 05818 } 05819 05830 dbus_bool_t 05831 dbus_connection_list_registered (DBusConnection *connection, 05832 const char *parent_path, 05833 char ***child_entries) 05834 { 05835 char **decomposed_path; 05836 dbus_bool_t retval; 05837 _dbus_return_val_if_fail (connection != NULL, FALSE); 05838 _dbus_return_val_if_fail (parent_path != NULL, FALSE); 05839 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE); 05840 _dbus_return_val_if_fail (child_entries != NULL, FALSE); 05841 05842 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL)) 05843 return FALSE; 05844 05845 CONNECTION_LOCK (connection); 05846 05847 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects, 05848 (const char **) decomposed_path, 05849 child_entries); 05850 dbus_free_string_array (decomposed_path); 05851 05852 return retval; 05853 } 05854 05855 static DBusDataSlotAllocator slot_allocator; 05856 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots); 05857 05872 dbus_bool_t 05873 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p) 05874 { 05875 return _dbus_data_slot_allocator_alloc (&slot_allocator, 05876 &_DBUS_LOCK_NAME (connection_slots), 05877 slot_p); 05878 } 05879 05891 void 05892 dbus_connection_free_data_slot (dbus_int32_t *slot_p) 05893 { 05894 _dbus_return_if_fail (*slot_p >= 0); 05895 05896 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 05897 } 05898 05921 dbus_bool_t 05922 dbus_connection_set_data (DBusConnection *connection, 05923 dbus_int32_t slot, 05924 void *data, 05925 DBusFreeFunction free_data_func) 05926 { 05927 DBusFreeFunction old_free_func; 05928 void *old_data; 05929 dbus_bool_t retval; 05930 05931 _dbus_return_val_if_fail (connection != NULL, FALSE); 05932 _dbus_return_val_if_fail (slot >= 0, FALSE); 05933 05934 SLOTS_LOCK (connection); 05935 05936 retval = _dbus_data_slot_list_set (&slot_allocator, 05937 &connection->slot_list, 05938 slot, data, free_data_func, 05939 &old_free_func, &old_data); 05940 05941 SLOTS_UNLOCK (connection); 05942 05943 if (retval) 05944 { 05945 /* Do the actual free outside the connection lock */ 05946 if (old_free_func) 05947 (* old_free_func) (old_data); 05948 } 05949 05950 return retval; 05951 } 05952 05970 void* 05971 dbus_connection_get_data (DBusConnection *connection, 05972 dbus_int32_t slot) 05973 { 05974 void *res; 05975 05976 _dbus_return_val_if_fail (connection != NULL, NULL); 05977 _dbus_return_val_if_fail (slot >= 0, NULL); 05978 05979 SLOTS_LOCK (connection); 05980 05981 res = _dbus_data_slot_list_get (&slot_allocator, 05982 &connection->slot_list, 05983 slot); 05984 05985 SLOTS_UNLOCK (connection); 05986 05987 return res; 05988 } 05989 05996 void 05997 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe) 05998 { 05999 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE; 06000 } 06001 06010 void 06011 dbus_connection_set_max_message_size (DBusConnection *connection, 06012 long size) 06013 { 06014 _dbus_return_if_fail (connection != NULL); 06015 06016 CONNECTION_LOCK (connection); 06017 _dbus_transport_set_max_message_size (connection->transport, 06018 size); 06019 CONNECTION_UNLOCK (connection); 06020 } 06021 06028 long 06029 dbus_connection_get_max_message_size (DBusConnection *connection) 06030 { 06031 long res; 06032 06033 _dbus_return_val_if_fail (connection != NULL, 0); 06034 06035 CONNECTION_LOCK (connection); 06036 res = _dbus_transport_get_max_message_size (connection->transport); 06037 CONNECTION_UNLOCK (connection); 06038 return res; 06039 } 06040 06049 void 06050 dbus_connection_set_max_message_unix_fds (DBusConnection *connection, 06051 long n) 06052 { 06053 _dbus_return_if_fail (connection != NULL); 06054 06055 CONNECTION_LOCK (connection); 06056 _dbus_transport_set_max_message_unix_fds (connection->transport, 06057 n); 06058 CONNECTION_UNLOCK (connection); 06059 } 06060 06067 long 06068 dbus_connection_get_max_message_unix_fds (DBusConnection *connection) 06069 { 06070 long res; 06071 06072 _dbus_return_val_if_fail (connection != NULL, 0); 06073 06074 CONNECTION_LOCK (connection); 06075 res = _dbus_transport_get_max_message_unix_fds (connection->transport); 06076 CONNECTION_UNLOCK (connection); 06077 return res; 06078 } 06079 06105 void 06106 dbus_connection_set_max_received_size (DBusConnection *connection, 06107 long size) 06108 { 06109 _dbus_return_if_fail (connection != NULL); 06110 06111 CONNECTION_LOCK (connection); 06112 _dbus_transport_set_max_received_size (connection->transport, 06113 size); 06114 CONNECTION_UNLOCK (connection); 06115 } 06116 06123 long 06124 dbus_connection_get_max_received_size (DBusConnection *connection) 06125 { 06126 long res; 06127 06128 _dbus_return_val_if_fail (connection != NULL, 0); 06129 06130 CONNECTION_LOCK (connection); 06131 res = _dbus_transport_get_max_received_size (connection->transport); 06132 CONNECTION_UNLOCK (connection); 06133 return res; 06134 } 06135 06147 void 06148 dbus_connection_set_max_received_unix_fds (DBusConnection *connection, 06149 long n) 06150 { 06151 _dbus_return_if_fail (connection != NULL); 06152 06153 CONNECTION_LOCK (connection); 06154 _dbus_transport_set_max_received_unix_fds (connection->transport, 06155 n); 06156 CONNECTION_UNLOCK (connection); 06157 } 06158 06165 long 06166 dbus_connection_get_max_received_unix_fds (DBusConnection *connection) 06167 { 06168 long res; 06169 06170 _dbus_return_val_if_fail (connection != NULL, 0); 06171 06172 CONNECTION_LOCK (connection); 06173 res = _dbus_transport_get_max_received_unix_fds (connection->transport); 06174 CONNECTION_UNLOCK (connection); 06175 return res; 06176 } 06177 06188 long 06189 dbus_connection_get_outgoing_size (DBusConnection *connection) 06190 { 06191 long res; 06192 06193 _dbus_return_val_if_fail (connection != NULL, 0); 06194 06195 CONNECTION_LOCK (connection); 06196 res = _dbus_counter_get_size_value (connection->outgoing_counter); 06197 CONNECTION_UNLOCK (connection); 06198 return res; 06199 } 06200 06201 #ifdef DBUS_ENABLE_STATS 06202 void 06203 _dbus_connection_get_stats (DBusConnection *connection, 06204 dbus_uint32_t *in_messages, 06205 dbus_uint32_t *in_bytes, 06206 dbus_uint32_t *in_fds, 06207 dbus_uint32_t *in_peak_bytes, 06208 dbus_uint32_t *in_peak_fds, 06209 dbus_uint32_t *out_messages, 06210 dbus_uint32_t *out_bytes, 06211 dbus_uint32_t *out_fds, 06212 dbus_uint32_t *out_peak_bytes, 06213 dbus_uint32_t *out_peak_fds) 06214 { 06215 CONNECTION_LOCK (connection); 06216 06217 if (in_messages != NULL) 06218 *in_messages = connection->n_incoming; 06219 06220 _dbus_transport_get_stats (connection->transport, 06221 in_bytes, in_fds, in_peak_bytes, in_peak_fds); 06222 06223 if (out_messages != NULL) 06224 *out_messages = connection->n_outgoing; 06225 06226 if (out_bytes != NULL) 06227 *out_bytes = _dbus_counter_get_size_value (connection->outgoing_counter); 06228 06229 if (out_fds != NULL) 06230 *out_fds = _dbus_counter_get_unix_fd_value (connection->outgoing_counter); 06231 06232 if (out_peak_bytes != NULL) 06233 *out_peak_bytes = _dbus_counter_get_peak_size_value (connection->outgoing_counter); 06234 06235 if (out_peak_fds != NULL) 06236 *out_peak_fds = _dbus_counter_get_peak_unix_fd_value (connection->outgoing_counter); 06237 06238 CONNECTION_UNLOCK (connection); 06239 } 06240 #endif /* DBUS_ENABLE_STATS */ 06241 06249 long 06250 dbus_connection_get_outgoing_unix_fds (DBusConnection *connection) 06251 { 06252 long res; 06253 06254 _dbus_return_val_if_fail (connection != NULL, 0); 06255 06256 CONNECTION_LOCK (connection); 06257 res = _dbus_counter_get_unix_fd_value (connection->outgoing_counter); 06258 CONNECTION_UNLOCK (connection); 06259 return res; 06260 } 06261 06262 #ifdef DBUS_BUILD_TESTS 06263 06269 const char* 06270 _dbus_connection_get_address (DBusConnection *connection) 06271 { 06272 return _dbus_transport_get_address (connection->transport); 06273 } 06274 #endif 06275