|
D-Bus
1.6.30
|
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 02540 int 02541 _dbus_connection_get_pending_fds_count (DBusConnection *connection) 02542 { 02543 return _dbus_transport_get_pending_fds_count (connection->transport); 02544 } 02545 02553 void 02554 _dbus_connection_set_pending_fds_function (DBusConnection *connection, 02555 DBusPendingFdsChangeFunction callback, 02556 void *data) 02557 { 02558 _dbus_transport_set_pending_fds_function (connection->transport, 02559 callback, data); 02560 } 02561 02598 DBusConnection* 02599 dbus_connection_open (const char *address, 02600 DBusError *error) 02601 { 02602 DBusConnection *connection; 02603 02604 _dbus_return_val_if_fail (address != NULL, NULL); 02605 _dbus_return_val_if_error_is_set (error, NULL); 02606 02607 connection = _dbus_connection_open_internal (address, 02608 TRUE, 02609 error); 02610 02611 return connection; 02612 } 02613 02641 DBusConnection* 02642 dbus_connection_open_private (const char *address, 02643 DBusError *error) 02644 { 02645 DBusConnection *connection; 02646 02647 _dbus_return_val_if_fail (address != NULL, NULL); 02648 _dbus_return_val_if_error_is_set (error, NULL); 02649 02650 connection = _dbus_connection_open_internal (address, 02651 FALSE, 02652 error); 02653 02654 return connection; 02655 } 02656 02663 DBusConnection * 02664 dbus_connection_ref (DBusConnection *connection) 02665 { 02666 dbus_int32_t old_refcount; 02667 02668 _dbus_return_val_if_fail (connection != NULL, NULL); 02669 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL); 02670 old_refcount = _dbus_atomic_inc (&connection->refcount); 02671 _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1, 02672 "ref"); 02673 02674 return connection; 02675 } 02676 02677 static void 02678 free_outgoing_message (void *element, 02679 void *data) 02680 { 02681 DBusMessage *message = element; 02682 DBusConnection *connection = data; 02683 02684 _dbus_message_remove_counter (message, connection->outgoing_counter); 02685 dbus_message_unref (message); 02686 } 02687 02688 /* This is run without the mutex held, but after the last reference 02689 * to the connection has been dropped we should have no thread-related 02690 * problems 02691 */ 02692 static void 02693 _dbus_connection_last_unref (DBusConnection *connection) 02694 { 02695 DBusList *link; 02696 02697 _dbus_verbose ("Finalizing connection %p\n", connection); 02698 02699 _dbus_assert (_dbus_atomic_get (&connection->refcount) == 0); 02700 02701 /* You have to disconnect the connection before unref:ing it. Otherwise 02702 * you won't get the disconnected message. 02703 */ 02704 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport)); 02705 _dbus_assert (connection->server_guid == NULL); 02706 02707 /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */ 02708 _dbus_object_tree_free_all_unlocked (connection->objects); 02709 02710 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL); 02711 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL); 02712 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL); 02713 02714 _dbus_watch_list_free (connection->watches); 02715 connection->watches = NULL; 02716 02717 _dbus_timeout_list_free (connection->timeouts); 02718 connection->timeouts = NULL; 02719 02720 _dbus_data_slot_list_free (&connection->slot_list); 02721 02722 link = _dbus_list_get_first_link (&connection->filter_list); 02723 while (link != NULL) 02724 { 02725 DBusMessageFilter *filter = link->data; 02726 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link); 02727 02728 filter->function = NULL; 02729 _dbus_message_filter_unref (filter); /* calls app callback */ 02730 link->data = NULL; 02731 02732 link = next; 02733 } 02734 _dbus_list_clear (&connection->filter_list); 02735 02736 /* ---- Done with stuff that invokes application callbacks */ 02737 02738 _dbus_object_tree_unref (connection->objects); 02739 02740 _dbus_hash_table_unref (connection->pending_replies); 02741 connection->pending_replies = NULL; 02742 02743 _dbus_list_clear (&connection->filter_list); 02744 02745 _dbus_list_foreach (&connection->outgoing_messages, 02746 free_outgoing_message, 02747 connection); 02748 _dbus_list_clear (&connection->outgoing_messages); 02749 02750 _dbus_list_foreach (&connection->incoming_messages, 02751 (DBusForeachFunction) dbus_message_unref, 02752 NULL); 02753 _dbus_list_clear (&connection->incoming_messages); 02754 02755 _dbus_counter_unref (connection->outgoing_counter); 02756 02757 _dbus_transport_unref (connection->transport); 02758 02759 if (connection->disconnect_message_link) 02760 { 02761 DBusMessage *message = connection->disconnect_message_link->data; 02762 dbus_message_unref (message); 02763 _dbus_list_free_link (connection->disconnect_message_link); 02764 } 02765 02766 _dbus_condvar_free_at_location (&connection->dispatch_cond); 02767 _dbus_condvar_free_at_location (&connection->io_path_cond); 02768 02769 _dbus_cmutex_free_at_location (&connection->io_path_mutex); 02770 _dbus_cmutex_free_at_location (&connection->dispatch_mutex); 02771 02772 _dbus_rmutex_free_at_location (&connection->slot_mutex); 02773 02774 _dbus_rmutex_free_at_location (&connection->mutex); 02775 02776 dbus_free (connection); 02777 } 02778 02798 void 02799 dbus_connection_unref (DBusConnection *connection) 02800 { 02801 dbus_int32_t old_refcount; 02802 02803 _dbus_return_if_fail (connection != NULL); 02804 _dbus_return_if_fail (connection->generation == _dbus_current_generation); 02805 02806 old_refcount = _dbus_atomic_dec (&connection->refcount); 02807 02808 _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1, 02809 "unref"); 02810 02811 if (old_refcount == 1) 02812 { 02813 #ifndef DBUS_DISABLE_CHECKS 02814 if (_dbus_transport_get_is_connected (connection->transport)) 02815 { 02816 _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", 02817 connection->shareable ? 02818 "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" : 02819 "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n"); 02820 return; 02821 } 02822 #endif 02823 _dbus_connection_last_unref (connection); 02824 } 02825 } 02826 02827 /* 02828 * Note that the transport can disconnect itself (other end drops us) 02829 * and in that case this function never runs. So this function must 02830 * not do anything more than disconnect the transport and update the 02831 * dispatch status. 02832 * 02833 * If the transport self-disconnects, then we assume someone will 02834 * dispatch the connection to cause the dispatch status update. 02835 */ 02836 static void 02837 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection) 02838 { 02839 DBusDispatchStatus status; 02840 02841 HAVE_LOCK_CHECK (connection); 02842 02843 _dbus_verbose ("Disconnecting %p\n", connection); 02844 02845 /* We need to ref because update_dispatch_status_and_unlock will unref 02846 * the connection if it was shared and libdbus was the only remaining 02847 * refcount holder. 02848 */ 02849 _dbus_connection_ref_unlocked (connection); 02850 02851 _dbus_transport_disconnect (connection->transport); 02852 02853 /* This has the side effect of queuing the disconnect message link 02854 * (unless we don't have enough memory, possibly, so don't assert it). 02855 * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open 02856 * should never again return the newly-disconnected connection. 02857 * 02858 * However, we only unref the shared connection and exit_on_disconnect when 02859 * the disconnect message reaches the head of the message queue, 02860 * NOT when it's first queued. 02861 */ 02862 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02863 02864 /* This calls out to user code */ 02865 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02866 02867 /* Could also call out to user code */ 02868 dbus_connection_unref (connection); 02869 } 02870 02913 void 02914 dbus_connection_close (DBusConnection *connection) 02915 { 02916 _dbus_return_if_fail (connection != NULL); 02917 _dbus_return_if_fail (connection->generation == _dbus_current_generation); 02918 02919 CONNECTION_LOCK (connection); 02920 02921 #ifndef DBUS_DISABLE_CHECKS 02922 if (connection->shareable) 02923 { 02924 CONNECTION_UNLOCK (connection); 02925 02926 _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n"); 02927 return; 02928 } 02929 #endif 02930 02931 _dbus_connection_close_possibly_shared_and_unlock (connection); 02932 } 02933 02934 static dbus_bool_t 02935 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection) 02936 { 02937 HAVE_LOCK_CHECK (connection); 02938 return _dbus_transport_get_is_connected (connection->transport); 02939 } 02940 02954 dbus_bool_t 02955 dbus_connection_get_is_connected (DBusConnection *connection) 02956 { 02957 dbus_bool_t res; 02958 02959 _dbus_return_val_if_fail (connection != NULL, FALSE); 02960 02961 CONNECTION_LOCK (connection); 02962 res = _dbus_connection_get_is_connected_unlocked (connection); 02963 CONNECTION_UNLOCK (connection); 02964 02965 return res; 02966 } 02967 02976 dbus_bool_t 02977 dbus_connection_get_is_authenticated (DBusConnection *connection) 02978 { 02979 dbus_bool_t res; 02980 02981 _dbus_return_val_if_fail (connection != NULL, FALSE); 02982 02983 CONNECTION_LOCK (connection); 02984 res = _dbus_transport_get_is_authenticated (connection->transport); 02985 CONNECTION_UNLOCK (connection); 02986 02987 return res; 02988 } 02989 03010 dbus_bool_t 03011 dbus_connection_get_is_anonymous (DBusConnection *connection) 03012 { 03013 dbus_bool_t res; 03014 03015 _dbus_return_val_if_fail (connection != NULL, FALSE); 03016 03017 CONNECTION_LOCK (connection); 03018 res = _dbus_transport_get_is_anonymous (connection->transport); 03019 CONNECTION_UNLOCK (connection); 03020 03021 return res; 03022 } 03023 03055 char* 03056 dbus_connection_get_server_id (DBusConnection *connection) 03057 { 03058 char *id; 03059 03060 _dbus_return_val_if_fail (connection != NULL, NULL); 03061 03062 CONNECTION_LOCK (connection); 03063 id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport)); 03064 CONNECTION_UNLOCK (connection); 03065 03066 return id; 03067 } 03068 03086 dbus_bool_t 03087 dbus_connection_can_send_type(DBusConnection *connection, 03088 int type) 03089 { 03090 _dbus_return_val_if_fail (connection != NULL, FALSE); 03091 03092 if (!dbus_type_is_valid (type)) 03093 return FALSE; 03094 03095 if (type != DBUS_TYPE_UNIX_FD) 03096 return TRUE; 03097 03098 #ifdef HAVE_UNIX_FD_PASSING 03099 { 03100 dbus_bool_t b; 03101 03102 CONNECTION_LOCK(connection); 03103 b = _dbus_transport_can_pass_unix_fd(connection->transport); 03104 CONNECTION_UNLOCK(connection); 03105 03106 return b; 03107 } 03108 #endif 03109 03110 return FALSE; 03111 } 03112 03126 void 03127 dbus_connection_set_exit_on_disconnect (DBusConnection *connection, 03128 dbus_bool_t exit_on_disconnect) 03129 { 03130 _dbus_return_if_fail (connection != NULL); 03131 03132 CONNECTION_LOCK (connection); 03133 connection->exit_on_disconnect = exit_on_disconnect != FALSE; 03134 CONNECTION_UNLOCK (connection); 03135 } 03136 03146 DBusPreallocatedSend* 03147 dbus_connection_preallocate_send (DBusConnection *connection) 03148 { 03149 DBusPreallocatedSend *preallocated; 03150 03151 _dbus_return_val_if_fail (connection != NULL, NULL); 03152 03153 CONNECTION_LOCK (connection); 03154 03155 preallocated = 03156 _dbus_connection_preallocate_send_unlocked (connection); 03157 03158 CONNECTION_UNLOCK (connection); 03159 03160 return preallocated; 03161 } 03162 03172 void 03173 dbus_connection_free_preallocated_send (DBusConnection *connection, 03174 DBusPreallocatedSend *preallocated) 03175 { 03176 _dbus_return_if_fail (connection != NULL); 03177 _dbus_return_if_fail (preallocated != NULL); 03178 _dbus_return_if_fail (connection == preallocated->connection); 03179 03180 _dbus_list_free_link (preallocated->queue_link); 03181 _dbus_counter_unref (preallocated->counter_link->data); 03182 _dbus_list_free_link (preallocated->counter_link); 03183 dbus_free (preallocated); 03184 } 03185 03198 void 03199 dbus_connection_send_preallocated (DBusConnection *connection, 03200 DBusPreallocatedSend *preallocated, 03201 DBusMessage *message, 03202 dbus_uint32_t *client_serial) 03203 { 03204 _dbus_return_if_fail (connection != NULL); 03205 _dbus_return_if_fail (preallocated != NULL); 03206 _dbus_return_if_fail (message != NULL); 03207 _dbus_return_if_fail (preallocated->connection == connection); 03208 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL || 03209 dbus_message_get_member (message) != NULL); 03210 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL || 03211 (dbus_message_get_interface (message) != NULL && 03212 dbus_message_get_member (message) != NULL)); 03213 03214 CONNECTION_LOCK (connection); 03215 03216 #ifdef HAVE_UNIX_FD_PASSING 03217 03218 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03219 message->n_unix_fds > 0) 03220 { 03221 /* Refuse to send fds on a connection that cannot handle 03222 them. Unfortunately we cannot return a proper error here, so 03223 the best we can is just return. */ 03224 CONNECTION_UNLOCK (connection); 03225 return; 03226 } 03227 03228 #endif 03229 03230 _dbus_connection_send_preallocated_and_unlock (connection, 03231 preallocated, 03232 message, client_serial); 03233 } 03234 03235 static dbus_bool_t 03236 _dbus_connection_send_unlocked_no_update (DBusConnection *connection, 03237 DBusMessage *message, 03238 dbus_uint32_t *client_serial) 03239 { 03240 DBusPreallocatedSend *preallocated; 03241 03242 _dbus_assert (connection != NULL); 03243 _dbus_assert (message != NULL); 03244 03245 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 03246 if (preallocated == NULL) 03247 return FALSE; 03248 03249 _dbus_connection_send_preallocated_unlocked_no_update (connection, 03250 preallocated, 03251 message, 03252 client_serial); 03253 return TRUE; 03254 } 03255 03283 dbus_bool_t 03284 dbus_connection_send (DBusConnection *connection, 03285 DBusMessage *message, 03286 dbus_uint32_t *serial) 03287 { 03288 _dbus_return_val_if_fail (connection != NULL, FALSE); 03289 _dbus_return_val_if_fail (message != NULL, FALSE); 03290 03291 CONNECTION_LOCK (connection); 03292 03293 #ifdef HAVE_UNIX_FD_PASSING 03294 03295 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03296 message->n_unix_fds > 0) 03297 { 03298 /* Refuse to send fds on a connection that cannot handle 03299 them. Unfortunately we cannot return a proper error here, so 03300 the best we can is just return. */ 03301 CONNECTION_UNLOCK (connection); 03302 return FALSE; 03303 } 03304 03305 #endif 03306 03307 return _dbus_connection_send_and_unlock (connection, 03308 message, 03309 serial); 03310 } 03311 03312 static dbus_bool_t 03313 reply_handler_timeout (void *data) 03314 { 03315 DBusConnection *connection; 03316 DBusDispatchStatus status; 03317 DBusPendingCall *pending = data; 03318 03319 connection = _dbus_pending_call_get_connection_and_lock (pending); 03320 _dbus_connection_ref_unlocked (connection); 03321 03322 _dbus_pending_call_queue_timeout_error_unlocked (pending, 03323 connection); 03324 _dbus_connection_remove_timeout_unlocked (connection, 03325 _dbus_pending_call_get_timeout_unlocked (pending)); 03326 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 03327 03328 _dbus_verbose ("middle\n"); 03329 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03330 03331 /* Unlocks, and calls out to user code */ 03332 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03333 dbus_connection_unref (connection); 03334 03335 return TRUE; 03336 } 03337 03380 dbus_bool_t 03381 dbus_connection_send_with_reply (DBusConnection *connection, 03382 DBusMessage *message, 03383 DBusPendingCall **pending_return, 03384 int timeout_milliseconds) 03385 { 03386 DBusPendingCall *pending; 03387 dbus_int32_t serial = -1; 03388 DBusDispatchStatus status; 03389 03390 _dbus_return_val_if_fail (connection != NULL, FALSE); 03391 _dbus_return_val_if_fail (message != NULL, FALSE); 03392 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03393 03394 if (pending_return) 03395 *pending_return = NULL; 03396 03397 CONNECTION_LOCK (connection); 03398 03399 #ifdef HAVE_UNIX_FD_PASSING 03400 03401 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03402 message->n_unix_fds > 0) 03403 { 03404 /* Refuse to send fds on a connection that cannot handle 03405 them. Unfortunately we cannot return a proper error here, so 03406 the best we can do is return TRUE but leave *pending_return 03407 as NULL. */ 03408 CONNECTION_UNLOCK (connection); 03409 return TRUE; 03410 } 03411 03412 #endif 03413 03414 if (!_dbus_connection_get_is_connected_unlocked (connection)) 03415 { 03416 CONNECTION_UNLOCK (connection); 03417 03418 return TRUE; 03419 } 03420 03421 pending = _dbus_pending_call_new_unlocked (connection, 03422 timeout_milliseconds, 03423 reply_handler_timeout); 03424 03425 if (pending == NULL) 03426 { 03427 CONNECTION_UNLOCK (connection); 03428 return FALSE; 03429 } 03430 03431 /* Assign a serial to the message */ 03432 serial = dbus_message_get_serial (message); 03433 if (serial == 0) 03434 { 03435 serial = _dbus_connection_get_next_client_serial (connection); 03436 dbus_message_set_serial (message, serial); 03437 } 03438 03439 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial)) 03440 goto error; 03441 03442 /* Insert the serial in the pending replies hash; 03443 * hash takes a refcount on DBusPendingCall. 03444 * Also, add the timeout. 03445 */ 03446 if (!_dbus_connection_attach_pending_call_unlocked (connection, 03447 pending)) 03448 goto error; 03449 03450 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL)) 03451 { 03452 _dbus_connection_detach_pending_call_and_unlock (connection, 03453 pending); 03454 goto error_unlocked; 03455 } 03456 03457 if (pending_return) 03458 *pending_return = pending; /* hand off refcount */ 03459 else 03460 { 03461 _dbus_connection_detach_pending_call_unlocked (connection, pending); 03462 /* we still have a ref to the pending call in this case, we unref 03463 * after unlocking, below 03464 */ 03465 } 03466 03467 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03468 03469 /* this calls out to user code */ 03470 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03471 03472 if (pending_return == NULL) 03473 dbus_pending_call_unref (pending); 03474 03475 return TRUE; 03476 03477 error: 03478 CONNECTION_UNLOCK (connection); 03479 error_unlocked: 03480 dbus_pending_call_unref (pending); 03481 return FALSE; 03482 } 03483 03516 DBusMessage* 03517 dbus_connection_send_with_reply_and_block (DBusConnection *connection, 03518 DBusMessage *message, 03519 int timeout_milliseconds, 03520 DBusError *error) 03521 { 03522 DBusMessage *reply; 03523 DBusPendingCall *pending; 03524 03525 _dbus_return_val_if_fail (connection != NULL, NULL); 03526 _dbus_return_val_if_fail (message != NULL, NULL); 03527 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL); 03528 _dbus_return_val_if_error_is_set (error, NULL); 03529 03530 #ifdef HAVE_UNIX_FD_PASSING 03531 03532 CONNECTION_LOCK (connection); 03533 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03534 message->n_unix_fds > 0) 03535 { 03536 CONNECTION_UNLOCK (connection); 03537 dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection."); 03538 return NULL; 03539 } 03540 CONNECTION_UNLOCK (connection); 03541 03542 #endif 03543 03544 if (!dbus_connection_send_with_reply (connection, message, 03545 &pending, timeout_milliseconds)) 03546 { 03547 _DBUS_SET_OOM (error); 03548 return NULL; 03549 } 03550 03551 if (pending == NULL) 03552 { 03553 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed"); 03554 return NULL; 03555 } 03556 03557 dbus_pending_call_block (pending); 03558 03559 reply = dbus_pending_call_steal_reply (pending); 03560 dbus_pending_call_unref (pending); 03561 03562 /* call_complete_and_unlock() called from pending_call_block() should 03563 * always fill this in. 03564 */ 03565 _dbus_assert (reply != NULL); 03566 03567 if (dbus_set_error_from_message (error, reply)) 03568 { 03569 dbus_message_unref (reply); 03570 return NULL; 03571 } 03572 else 03573 return reply; 03574 } 03575 03584 static DBusDispatchStatus 03585 _dbus_connection_flush_unlocked (DBusConnection *connection) 03586 { 03587 /* We have to specify DBUS_ITERATION_DO_READING here because 03588 * otherwise we could have two apps deadlock if they are both doing 03589 * a flush(), and the kernel buffers fill up. This could change the 03590 * dispatch status. 03591 */ 03592 DBusDispatchStatus status; 03593 03594 HAVE_LOCK_CHECK (connection); 03595 03596 while (connection->n_outgoing > 0 && 03597 _dbus_connection_get_is_connected_unlocked (connection)) 03598 { 03599 _dbus_verbose ("doing iteration in\n"); 03600 HAVE_LOCK_CHECK (connection); 03601 _dbus_connection_do_iteration_unlocked (connection, 03602 NULL, 03603 DBUS_ITERATION_DO_READING | 03604 DBUS_ITERATION_DO_WRITING | 03605 DBUS_ITERATION_BLOCK, 03606 -1); 03607 } 03608 03609 HAVE_LOCK_CHECK (connection); 03610 _dbus_verbose ("middle\n"); 03611 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03612 03613 HAVE_LOCK_CHECK (connection); 03614 return status; 03615 } 03616 03622 void 03623 dbus_connection_flush (DBusConnection *connection) 03624 { 03625 /* We have to specify DBUS_ITERATION_DO_READING here because 03626 * otherwise we could have two apps deadlock if they are both doing 03627 * a flush(), and the kernel buffers fill up. This could change the 03628 * dispatch status. 03629 */ 03630 DBusDispatchStatus status; 03631 03632 _dbus_return_if_fail (connection != NULL); 03633 03634 CONNECTION_LOCK (connection); 03635 03636 status = _dbus_connection_flush_unlocked (connection); 03637 03638 HAVE_LOCK_CHECK (connection); 03639 /* Unlocks and calls out to user code */ 03640 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03641 03642 _dbus_verbose ("end\n"); 03643 } 03644 03655 static dbus_bool_t 03656 _dbus_connection_read_write_dispatch (DBusConnection *connection, 03657 int timeout_milliseconds, 03658 dbus_bool_t dispatch) 03659 { 03660 DBusDispatchStatus dstatus; 03661 dbus_bool_t progress_possible; 03662 03663 /* Need to grab a ref here in case we're a private connection and 03664 * the user drops the last ref in a handler we call; see bug 03665 * https://bugs.freedesktop.org/show_bug.cgi?id=15635 03666 */ 03667 dbus_connection_ref (connection); 03668 dstatus = dbus_connection_get_dispatch_status (connection); 03669 03670 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS) 03671 { 03672 _dbus_verbose ("doing dispatch\n"); 03673 dbus_connection_dispatch (connection); 03674 CONNECTION_LOCK (connection); 03675 } 03676 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY) 03677 { 03678 _dbus_verbose ("pausing for memory\n"); 03679 _dbus_memory_pause_based_on_timeout (timeout_milliseconds); 03680 CONNECTION_LOCK (connection); 03681 } 03682 else 03683 { 03684 CONNECTION_LOCK (connection); 03685 if (_dbus_connection_get_is_connected_unlocked (connection)) 03686 { 03687 _dbus_verbose ("doing iteration\n"); 03688 _dbus_connection_do_iteration_unlocked (connection, 03689 NULL, 03690 DBUS_ITERATION_DO_READING | 03691 DBUS_ITERATION_DO_WRITING | 03692 DBUS_ITERATION_BLOCK, 03693 timeout_milliseconds); 03694 } 03695 } 03696 03697 HAVE_LOCK_CHECK (connection); 03698 /* If we can dispatch, we can make progress until the Disconnected message 03699 * has been processed; if we can only read/write, we can make progress 03700 * as long as the transport is open. 03701 */ 03702 if (dispatch) 03703 progress_possible = connection->n_incoming != 0 || 03704 connection->disconnect_message_link != NULL; 03705 else 03706 progress_possible = _dbus_connection_get_is_connected_unlocked (connection); 03707 03708 CONNECTION_UNLOCK (connection); 03709 03710 dbus_connection_unref (connection); 03711 03712 return progress_possible; /* TRUE if we can make more progress */ 03713 } 03714 03715 03750 dbus_bool_t 03751 dbus_connection_read_write_dispatch (DBusConnection *connection, 03752 int timeout_milliseconds) 03753 { 03754 _dbus_return_val_if_fail (connection != NULL, FALSE); 03755 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03756 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE); 03757 } 03758 03782 dbus_bool_t 03783 dbus_connection_read_write (DBusConnection *connection, 03784 int timeout_milliseconds) 03785 { 03786 _dbus_return_val_if_fail (connection != NULL, FALSE); 03787 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03788 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE); 03789 } 03790 03791 /* We need to call this anytime we pop the head of the queue, and then 03792 * update_dispatch_status_and_unlock needs to be called afterward 03793 * which will "process" the disconnected message and set 03794 * disconnected_message_processed. 03795 */ 03796 static void 03797 check_disconnected_message_arrived_unlocked (DBusConnection *connection, 03798 DBusMessage *head_of_queue) 03799 { 03800 HAVE_LOCK_CHECK (connection); 03801 03802 /* checking that the link is NULL is an optimization to avoid the is_signal call */ 03803 if (connection->disconnect_message_link == NULL && 03804 dbus_message_is_signal (head_of_queue, 03805 DBUS_INTERFACE_LOCAL, 03806 "Disconnected")) 03807 { 03808 connection->disconnected_message_arrived = TRUE; 03809 } 03810 } 03811 03831 DBusMessage* 03832 dbus_connection_borrow_message (DBusConnection *connection) 03833 { 03834 DBusDispatchStatus status; 03835 DBusMessage *message; 03836 03837 _dbus_return_val_if_fail (connection != NULL, NULL); 03838 03839 _dbus_verbose ("start\n"); 03840 03841 /* this is called for the side effect that it queues 03842 * up any messages from the transport 03843 */ 03844 status = dbus_connection_get_dispatch_status (connection); 03845 if (status != DBUS_DISPATCH_DATA_REMAINS) 03846 return NULL; 03847 03848 CONNECTION_LOCK (connection); 03849 03850 _dbus_connection_acquire_dispatch (connection); 03851 03852 /* While a message is outstanding, the dispatch lock is held */ 03853 _dbus_assert (connection->message_borrowed == NULL); 03854 03855 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages); 03856 03857 message = connection->message_borrowed; 03858 03859 check_disconnected_message_arrived_unlocked (connection, message); 03860 03861 /* Note that we KEEP the dispatch lock until the message is returned */ 03862 if (message == NULL) 03863 _dbus_connection_release_dispatch (connection); 03864 03865 CONNECTION_UNLOCK (connection); 03866 03867 _dbus_message_trace_ref (message, -1, -1, "dbus_connection_borrow_message"); 03868 03869 /* We don't update dispatch status until it's returned or stolen */ 03870 03871 return message; 03872 } 03873 03882 void 03883 dbus_connection_return_message (DBusConnection *connection, 03884 DBusMessage *message) 03885 { 03886 DBusDispatchStatus status; 03887 03888 _dbus_return_if_fail (connection != NULL); 03889 _dbus_return_if_fail (message != NULL); 03890 _dbus_return_if_fail (message == connection->message_borrowed); 03891 _dbus_return_if_fail (connection->dispatch_acquired); 03892 03893 CONNECTION_LOCK (connection); 03894 03895 _dbus_assert (message == connection->message_borrowed); 03896 03897 connection->message_borrowed = NULL; 03898 03899 _dbus_connection_release_dispatch (connection); 03900 03901 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03902 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03903 03904 _dbus_message_trace_ref (message, -1, -1, "dbus_connection_return_message"); 03905 } 03906 03916 void 03917 dbus_connection_steal_borrowed_message (DBusConnection *connection, 03918 DBusMessage *message) 03919 { 03920 DBusMessage *pop_message; 03921 DBusDispatchStatus status; 03922 03923 _dbus_return_if_fail (connection != NULL); 03924 _dbus_return_if_fail (message != NULL); 03925 _dbus_return_if_fail (message == connection->message_borrowed); 03926 _dbus_return_if_fail (connection->dispatch_acquired); 03927 03928 CONNECTION_LOCK (connection); 03929 03930 _dbus_assert (message == connection->message_borrowed); 03931 03932 pop_message = _dbus_list_pop_first (&connection->incoming_messages); 03933 _dbus_assert (message == pop_message); 03934 (void) pop_message; /* unused unless asserting */ 03935 03936 connection->n_incoming -= 1; 03937 03938 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n", 03939 message, connection->n_incoming); 03940 03941 connection->message_borrowed = NULL; 03942 03943 _dbus_connection_release_dispatch (connection); 03944 03945 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03946 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03947 _dbus_message_trace_ref (message, -1, -1, 03948 "dbus_connection_steal_borrowed_message"); 03949 } 03950 03951 /* See dbus_connection_pop_message, but requires the caller to own 03952 * the lock before calling. May drop the lock while running. 03953 */ 03954 static DBusList* 03955 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection) 03956 { 03957 HAVE_LOCK_CHECK (connection); 03958 03959 _dbus_assert (connection->message_borrowed == NULL); 03960 03961 if (connection->n_incoming > 0) 03962 { 03963 DBusList *link; 03964 03965 link = _dbus_list_pop_first_link (&connection->incoming_messages); 03966 connection->n_incoming -= 1; 03967 03968 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from incoming queue %p, %d incoming\n", 03969 link->data, 03970 dbus_message_type_to_string (dbus_message_get_type (link->data)), 03971 dbus_message_get_path (link->data) ? 03972 dbus_message_get_path (link->data) : 03973 "no path", 03974 dbus_message_get_interface (link->data) ? 03975 dbus_message_get_interface (link->data) : 03976 "no interface", 03977 dbus_message_get_member (link->data) ? 03978 dbus_message_get_member (link->data) : 03979 "no member", 03980 dbus_message_get_signature (link->data), 03981 connection, connection->n_incoming); 03982 03983 _dbus_message_trace_ref (link->data, -1, -1, 03984 "_dbus_connection_pop_message_link_unlocked"); 03985 03986 check_disconnected_message_arrived_unlocked (connection, link->data); 03987 03988 return link; 03989 } 03990 else 03991 return NULL; 03992 } 03993 03994 /* See dbus_connection_pop_message, but requires the caller to own 03995 * the lock before calling. May drop the lock while running. 03996 */ 03997 static DBusMessage* 03998 _dbus_connection_pop_message_unlocked (DBusConnection *connection) 03999 { 04000 DBusList *link; 04001 04002 HAVE_LOCK_CHECK (connection); 04003 04004 link = _dbus_connection_pop_message_link_unlocked (connection); 04005 04006 if (link != NULL) 04007 { 04008 DBusMessage *message; 04009 04010 message = link->data; 04011 04012 _dbus_list_free_link (link); 04013 04014 return message; 04015 } 04016 else 04017 return NULL; 04018 } 04019 04020 static void 04021 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection, 04022 DBusList *message_link) 04023 { 04024 HAVE_LOCK_CHECK (connection); 04025 04026 _dbus_assert (message_link != NULL); 04027 /* You can't borrow a message while a link is outstanding */ 04028 _dbus_assert (connection->message_borrowed == NULL); 04029 /* We had to have the dispatch lock across the pop/putback */ 04030 _dbus_assert (connection->dispatch_acquired); 04031 04032 _dbus_list_prepend_link (&connection->incoming_messages, 04033 message_link); 04034 connection->n_incoming += 1; 04035 04036 _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n", 04037 message_link->data, 04038 dbus_message_type_to_string (dbus_message_get_type (message_link->data)), 04039 dbus_message_get_interface (message_link->data) ? 04040 dbus_message_get_interface (message_link->data) : 04041 "no interface", 04042 dbus_message_get_member (message_link->data) ? 04043 dbus_message_get_member (message_link->data) : 04044 "no member", 04045 dbus_message_get_signature (message_link->data), 04046 connection, connection->n_incoming); 04047 04048 _dbus_message_trace_ref (message_link->data, -1, -1, 04049 "_dbus_connection_putback_message_link_unlocked"); 04050 } 04051 04071 DBusMessage* 04072 dbus_connection_pop_message (DBusConnection *connection) 04073 { 04074 DBusMessage *message; 04075 DBusDispatchStatus status; 04076 04077 _dbus_verbose ("start\n"); 04078 04079 /* this is called for the side effect that it queues 04080 * up any messages from the transport 04081 */ 04082 status = dbus_connection_get_dispatch_status (connection); 04083 if (status != DBUS_DISPATCH_DATA_REMAINS) 04084 return NULL; 04085 04086 CONNECTION_LOCK (connection); 04087 _dbus_connection_acquire_dispatch (connection); 04088 HAVE_LOCK_CHECK (connection); 04089 04090 message = _dbus_connection_pop_message_unlocked (connection); 04091 04092 _dbus_verbose ("Returning popped message %p\n", message); 04093 04094 _dbus_connection_release_dispatch (connection); 04095 04096 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04097 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04098 04099 return message; 04100 } 04101 04109 static void 04110 _dbus_connection_acquire_dispatch (DBusConnection *connection) 04111 { 04112 HAVE_LOCK_CHECK (connection); 04113 04114 _dbus_connection_ref_unlocked (connection); 04115 CONNECTION_UNLOCK (connection); 04116 04117 _dbus_verbose ("locking dispatch_mutex\n"); 04118 _dbus_cmutex_lock (connection->dispatch_mutex); 04119 04120 while (connection->dispatch_acquired) 04121 { 04122 _dbus_verbose ("waiting for dispatch to be acquirable\n"); 04123 _dbus_condvar_wait (connection->dispatch_cond, 04124 connection->dispatch_mutex); 04125 } 04126 04127 _dbus_assert (!connection->dispatch_acquired); 04128 04129 connection->dispatch_acquired = TRUE; 04130 04131 _dbus_verbose ("unlocking dispatch_mutex\n"); 04132 _dbus_cmutex_unlock (connection->dispatch_mutex); 04133 04134 CONNECTION_LOCK (connection); 04135 _dbus_connection_unref_unlocked (connection); 04136 } 04137 04145 static void 04146 _dbus_connection_release_dispatch (DBusConnection *connection) 04147 { 04148 HAVE_LOCK_CHECK (connection); 04149 04150 _dbus_verbose ("locking dispatch_mutex\n"); 04151 _dbus_cmutex_lock (connection->dispatch_mutex); 04152 04153 _dbus_assert (connection->dispatch_acquired); 04154 04155 connection->dispatch_acquired = FALSE; 04156 _dbus_condvar_wake_one (connection->dispatch_cond); 04157 04158 _dbus_verbose ("unlocking dispatch_mutex\n"); 04159 _dbus_cmutex_unlock (connection->dispatch_mutex); 04160 } 04161 04162 static void 04163 _dbus_connection_failed_pop (DBusConnection *connection, 04164 DBusList *message_link) 04165 { 04166 _dbus_list_prepend_link (&connection->incoming_messages, 04167 message_link); 04168 connection->n_incoming += 1; 04169 } 04170 04171 /* Note this may be called multiple times since we don't track whether we already did it */ 04172 static void 04173 notify_disconnected_unlocked (DBusConnection *connection) 04174 { 04175 HAVE_LOCK_CHECK (connection); 04176 04177 /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected 04178 * connection from dbus_bus_get(). We make the same guarantee for 04179 * dbus_connection_open() but in a different way since we don't want to 04180 * unref right here; we instead check for connectedness before returning 04181 * the connection from the hash. 04182 */ 04183 _dbus_bus_notify_shared_connection_disconnected_unlocked (connection); 04184 04185 /* Dump the outgoing queue, we aren't going to be able to 04186 * send it now, and we'd like accessors like 04187 * dbus_connection_get_outgoing_size() to be accurate. 04188 */ 04189 if (connection->n_outgoing > 0) 04190 { 04191 DBusList *link; 04192 04193 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n", 04194 connection->n_outgoing); 04195 04196 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages))) 04197 { 04198 _dbus_connection_message_sent_unlocked (connection, link->data); 04199 } 04200 } 04201 } 04202 04203 /* Note this may be called multiple times since we don't track whether we already did it */ 04204 static DBusDispatchStatus 04205 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection) 04206 { 04207 HAVE_LOCK_CHECK (connection); 04208 04209 if (connection->disconnect_message_link != NULL) 04210 { 04211 _dbus_verbose ("Sending disconnect message\n"); 04212 04213 /* If we have pending calls, queue their timeouts - we want the Disconnected 04214 * to be the last message, after these timeouts. 04215 */ 04216 connection_timeout_and_complete_all_pending_calls_unlocked (connection); 04217 04218 /* We haven't sent the disconnect message already, 04219 * and all real messages have been queued up. 04220 */ 04221 _dbus_connection_queue_synthesized_message_link (connection, 04222 connection->disconnect_message_link); 04223 connection->disconnect_message_link = NULL; 04224 04225 return DBUS_DISPATCH_DATA_REMAINS; 04226 } 04227 04228 return DBUS_DISPATCH_COMPLETE; 04229 } 04230 04231 static DBusDispatchStatus 04232 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection) 04233 { 04234 HAVE_LOCK_CHECK (connection); 04235 04236 if (connection->n_incoming > 0) 04237 return DBUS_DISPATCH_DATA_REMAINS; 04238 else if (!_dbus_transport_queue_messages (connection->transport)) 04239 return DBUS_DISPATCH_NEED_MEMORY; 04240 else 04241 { 04242 DBusDispatchStatus status; 04243 dbus_bool_t is_connected; 04244 04245 status = _dbus_transport_get_dispatch_status (connection->transport); 04246 is_connected = _dbus_transport_get_is_connected (connection->transport); 04247 04248 _dbus_verbose ("dispatch status = %s is_connected = %d\n", 04249 DISPATCH_STATUS_NAME (status), is_connected); 04250 04251 if (!is_connected) 04252 { 04253 /* It's possible this would be better done by having an explicit 04254 * notification from _dbus_transport_disconnect() that would 04255 * synchronously do this, instead of waiting for the next dispatch 04256 * status check. However, probably not good to change until it causes 04257 * a problem. 04258 */ 04259 notify_disconnected_unlocked (connection); 04260 04261 /* I'm not sure this is needed; the idea is that we want to 04262 * queue the Disconnected only after we've read all the 04263 * messages, but if we're disconnected maybe we are guaranteed 04264 * to have read them all ? 04265 */ 04266 if (status == DBUS_DISPATCH_COMPLETE) 04267 status = notify_disconnected_and_dispatch_complete_unlocked (connection); 04268 } 04269 04270 if (status != DBUS_DISPATCH_COMPLETE) 04271 return status; 04272 else if (connection->n_incoming > 0) 04273 return DBUS_DISPATCH_DATA_REMAINS; 04274 else 04275 return DBUS_DISPATCH_COMPLETE; 04276 } 04277 } 04278 04279 static void 04280 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection, 04281 DBusDispatchStatus new_status) 04282 { 04283 dbus_bool_t changed; 04284 DBusDispatchStatusFunction function; 04285 void *data; 04286 04287 HAVE_LOCK_CHECK (connection); 04288 04289 _dbus_connection_ref_unlocked (connection); 04290 04291 changed = new_status != connection->last_dispatch_status; 04292 04293 connection->last_dispatch_status = new_status; 04294 04295 function = connection->dispatch_status_function; 04296 data = connection->dispatch_status_data; 04297 04298 if (connection->disconnected_message_arrived && 04299 !connection->disconnected_message_processed) 04300 { 04301 connection->disconnected_message_processed = TRUE; 04302 04303 /* this does an unref, but we have a ref 04304 * so we should not run the finalizer here 04305 * inside the lock. 04306 */ 04307 connection_forget_shared_unlocked (connection); 04308 04309 if (connection->exit_on_disconnect) 04310 { 04311 CONNECTION_UNLOCK (connection); 04312 04313 _dbus_verbose ("Exiting on Disconnected signal\n"); 04314 _dbus_exit (1); 04315 _dbus_assert_not_reached ("Call to exit() returned"); 04316 } 04317 } 04318 04319 /* We drop the lock */ 04320 CONNECTION_UNLOCK (connection); 04321 04322 if (changed && function) 04323 { 04324 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n", 04325 connection, new_status, 04326 DISPATCH_STATUS_NAME (new_status)); 04327 (* function) (connection, new_status, data); 04328 } 04329 04330 dbus_connection_unref (connection); 04331 } 04332 04358 DBusDispatchStatus 04359 dbus_connection_get_dispatch_status (DBusConnection *connection) 04360 { 04361 DBusDispatchStatus status; 04362 04363 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE); 04364 04365 _dbus_verbose ("start\n"); 04366 04367 CONNECTION_LOCK (connection); 04368 04369 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04370 04371 CONNECTION_UNLOCK (connection); 04372 04373 return status; 04374 } 04375 04379 static DBusHandlerResult 04380 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection, 04381 DBusMessage *message) 04382 { 04383 dbus_bool_t sent = FALSE; 04384 DBusMessage *ret = NULL; 04385 DBusList *expire_link; 04386 04387 if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL) 04388 { 04389 /* This means we're letting the bus route this message */ 04390 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04391 } 04392 04393 if (!dbus_message_has_interface (message, DBUS_INTERFACE_PEER)) 04394 { 04395 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04396 } 04397 04398 /* Preallocate a linked-list link, so that if we need to dispose of a 04399 * message, we can attach it to the expired list */ 04400 expire_link = _dbus_list_alloc_link (NULL); 04401 04402 if (!expire_link) 04403 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04404 04405 if (dbus_message_is_method_call (message, 04406 DBUS_INTERFACE_PEER, 04407 "Ping")) 04408 { 04409 ret = dbus_message_new_method_return (message); 04410 if (ret == NULL) 04411 goto out; 04412 04413 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04414 } 04415 else if (dbus_message_is_method_call (message, 04416 DBUS_INTERFACE_PEER, 04417 "GetMachineId")) 04418 { 04419 DBusString uuid; 04420 04421 ret = dbus_message_new_method_return (message); 04422 if (ret == NULL) 04423 goto out; 04424 04425 _dbus_string_init (&uuid); 04426 if (_dbus_get_local_machine_uuid_encoded (&uuid)) 04427 { 04428 const char *v_STRING = _dbus_string_get_const_data (&uuid); 04429 if (dbus_message_append_args (ret, 04430 DBUS_TYPE_STRING, &v_STRING, 04431 DBUS_TYPE_INVALID)) 04432 { 04433 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04434 } 04435 } 04436 _dbus_string_free (&uuid); 04437 } 04438 else 04439 { 04440 /* We need to bounce anything else with this interface, otherwise apps 04441 * could start extending the interface and when we added extensions 04442 * here to DBusConnection we'd break those apps. 04443 */ 04444 ret = dbus_message_new_error (message, 04445 DBUS_ERROR_UNKNOWN_METHOD, 04446 "Unknown method invoked on org.freedesktop.DBus.Peer interface"); 04447 if (ret == NULL) 04448 goto out; 04449 04450 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04451 } 04452 04453 out: 04454 if (ret == NULL) 04455 { 04456 _dbus_list_free_link (expire_link); 04457 } 04458 else 04459 { 04460 /* It'll be safe to unref the reply when we unlock */ 04461 expire_link->data = ret; 04462 _dbus_list_prepend_link (&connection->expired_messages, expire_link); 04463 } 04464 04465 if (!sent) 04466 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04467 04468 return DBUS_HANDLER_RESULT_HANDLED; 04469 } 04470 04477 static DBusHandlerResult 04478 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection, 04479 DBusMessage *message) 04480 { 04481 /* We just run one filter for now but have the option to run more 04482 if the spec calls for it in the future */ 04483 04484 return _dbus_connection_peer_filter_unlocked_no_update (connection, message); 04485 } 04486 04529 DBusDispatchStatus 04530 dbus_connection_dispatch (DBusConnection *connection) 04531 { 04532 DBusMessage *message; 04533 DBusList *link, *filter_list_copy, *message_link; 04534 DBusHandlerResult result; 04535 DBusPendingCall *pending; 04536 dbus_int32_t reply_serial; 04537 DBusDispatchStatus status; 04538 dbus_bool_t found_object; 04539 04540 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE); 04541 04542 _dbus_verbose ("\n"); 04543 04544 CONNECTION_LOCK (connection); 04545 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04546 if (status != DBUS_DISPATCH_DATA_REMAINS) 04547 { 04548 /* unlocks and calls out to user code */ 04549 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04550 return status; 04551 } 04552 04553 /* We need to ref the connection since the callback could potentially 04554 * drop the last ref to it 04555 */ 04556 _dbus_connection_ref_unlocked (connection); 04557 04558 _dbus_connection_acquire_dispatch (connection); 04559 HAVE_LOCK_CHECK (connection); 04560 04561 message_link = _dbus_connection_pop_message_link_unlocked (connection); 04562 if (message_link == NULL) 04563 { 04564 /* another thread dispatched our stuff */ 04565 04566 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n"); 04567 04568 _dbus_connection_release_dispatch (connection); 04569 04570 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04571 04572 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04573 04574 dbus_connection_unref (connection); 04575 04576 return status; 04577 } 04578 04579 message = message_link->data; 04580 04581 _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n", 04582 message, 04583 dbus_message_type_to_string (dbus_message_get_type (message)), 04584 dbus_message_get_interface (message) ? 04585 dbus_message_get_interface (message) : 04586 "no interface", 04587 dbus_message_get_member (message) ? 04588 dbus_message_get_member (message) : 04589 "no member", 04590 dbus_message_get_signature (message)); 04591 04592 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04593 04594 /* Pending call handling must be first, because if you do 04595 * dbus_connection_send_with_reply_and_block() or 04596 * dbus_pending_call_block() then no handlers/filters will be run on 04597 * the reply. We want consistent semantics in the case where we 04598 * dbus_connection_dispatch() the reply. 04599 */ 04600 04601 reply_serial = dbus_message_get_reply_serial (message); 04602 pending = _dbus_hash_table_lookup_int (connection->pending_replies, 04603 reply_serial); 04604 if (pending) 04605 { 04606 _dbus_verbose ("Dispatching a pending reply\n"); 04607 complete_pending_call_and_unlock (connection, pending, message); 04608 pending = NULL; /* it's probably unref'd */ 04609 04610 CONNECTION_LOCK (connection); 04611 _dbus_verbose ("pending call completed in dispatch\n"); 04612 result = DBUS_HANDLER_RESULT_HANDLED; 04613 goto out; 04614 } 04615 04616 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message); 04617 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04618 goto out; 04619 04620 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy)) 04621 { 04622 _dbus_connection_release_dispatch (connection); 04623 HAVE_LOCK_CHECK (connection); 04624 04625 _dbus_connection_failed_pop (connection, message_link); 04626 04627 /* unlocks and calls user code */ 04628 _dbus_connection_update_dispatch_status_and_unlock (connection, 04629 DBUS_DISPATCH_NEED_MEMORY); 04630 dbus_connection_unref (connection); 04631 04632 return DBUS_DISPATCH_NEED_MEMORY; 04633 } 04634 04635 _dbus_list_foreach (&filter_list_copy, 04636 (DBusForeachFunction)_dbus_message_filter_ref, 04637 NULL); 04638 04639 /* We're still protected from dispatch() reentrancy here 04640 * since we acquired the dispatcher 04641 */ 04642 CONNECTION_UNLOCK (connection); 04643 04644 link = _dbus_list_get_first_link (&filter_list_copy); 04645 while (link != NULL) 04646 { 04647 DBusMessageFilter *filter = link->data; 04648 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link); 04649 04650 if (filter->function == NULL) 04651 { 04652 _dbus_verbose (" filter was removed in a callback function\n"); 04653 link = next; 04654 continue; 04655 } 04656 04657 _dbus_verbose (" running filter on message %p\n", message); 04658 result = (* filter->function) (connection, message, filter->user_data); 04659 04660 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04661 break; 04662 04663 link = next; 04664 } 04665 04666 _dbus_list_foreach (&filter_list_copy, 04667 (DBusForeachFunction)_dbus_message_filter_unref, 04668 NULL); 04669 _dbus_list_clear (&filter_list_copy); 04670 04671 CONNECTION_LOCK (connection); 04672 04673 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) 04674 { 04675 _dbus_verbose ("No memory\n"); 04676 goto out; 04677 } 04678 else if (result == DBUS_HANDLER_RESULT_HANDLED) 04679 { 04680 _dbus_verbose ("filter handled message in dispatch\n"); 04681 goto out; 04682 } 04683 04684 /* We're still protected from dispatch() reentrancy here 04685 * since we acquired the dispatcher 04686 */ 04687 _dbus_verbose (" running object path dispatch on message %p (%s %s %s '%s')\n", 04688 message, 04689 dbus_message_type_to_string (dbus_message_get_type (message)), 04690 dbus_message_get_interface (message) ? 04691 dbus_message_get_interface (message) : 04692 "no interface", 04693 dbus_message_get_member (message) ? 04694 dbus_message_get_member (message) : 04695 "no member", 04696 dbus_message_get_signature (message)); 04697 04698 HAVE_LOCK_CHECK (connection); 04699 result = _dbus_object_tree_dispatch_and_unlock (connection->objects, 04700 message, 04701 &found_object); 04702 04703 CONNECTION_LOCK (connection); 04704 04705 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04706 { 04707 _dbus_verbose ("object tree handled message in dispatch\n"); 04708 goto out; 04709 } 04710 04711 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL) 04712 { 04713 DBusMessage *reply; 04714 DBusString str; 04715 DBusPreallocatedSend *preallocated; 04716 DBusList *expire_link; 04717 04718 _dbus_verbose (" sending error %s\n", 04719 DBUS_ERROR_UNKNOWN_METHOD); 04720 04721 if (!_dbus_string_init (&str)) 04722 { 04723 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04724 _dbus_verbose ("no memory for error string in dispatch\n"); 04725 goto out; 04726 } 04727 04728 if (!_dbus_string_append_printf (&str, 04729 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n", 04730 dbus_message_get_member (message), 04731 dbus_message_get_signature (message), 04732 dbus_message_get_interface (message))) 04733 { 04734 _dbus_string_free (&str); 04735 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04736 _dbus_verbose ("no memory for error string in dispatch\n"); 04737 goto out; 04738 } 04739 04740 reply = dbus_message_new_error (message, 04741 found_object ? DBUS_ERROR_UNKNOWN_METHOD : DBUS_ERROR_UNKNOWN_OBJECT, 04742 _dbus_string_get_const_data (&str)); 04743 _dbus_string_free (&str); 04744 04745 if (reply == NULL) 04746 { 04747 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04748 _dbus_verbose ("no memory for error reply in dispatch\n"); 04749 goto out; 04750 } 04751 04752 expire_link = _dbus_list_alloc_link (reply); 04753 04754 if (expire_link == NULL) 04755 { 04756 dbus_message_unref (reply); 04757 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04758 _dbus_verbose ("no memory for error send in dispatch\n"); 04759 goto out; 04760 } 04761 04762 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 04763 04764 if (preallocated == NULL) 04765 { 04766 _dbus_list_free_link (expire_link); 04767 /* It's OK that this is finalized, because it hasn't been seen by 04768 * anything that could attach user callbacks */ 04769 dbus_message_unref (reply); 04770 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04771 _dbus_verbose ("no memory for error send in dispatch\n"); 04772 goto out; 04773 } 04774 04775 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated, 04776 reply, NULL); 04777 /* reply will be freed when we release the lock */ 04778 _dbus_list_prepend_link (&connection->expired_messages, expire_link); 04779 04780 result = DBUS_HANDLER_RESULT_HANDLED; 04781 } 04782 04783 _dbus_verbose (" done dispatching %p (%s %s %s '%s') on connection %p\n", message, 04784 dbus_message_type_to_string (dbus_message_get_type (message)), 04785 dbus_message_get_interface (message) ? 04786 dbus_message_get_interface (message) : 04787 "no interface", 04788 dbus_message_get_member (message) ? 04789 dbus_message_get_member (message) : 04790 "no member", 04791 dbus_message_get_signature (message), 04792 connection); 04793 04794 out: 04795 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) 04796 { 04797 _dbus_verbose ("out of memory\n"); 04798 04799 /* Put message back, and we'll start over. 04800 * Yes this means handlers must be idempotent if they 04801 * don't return HANDLED; c'est la vie. 04802 */ 04803 _dbus_connection_putback_message_link_unlocked (connection, 04804 message_link); 04805 /* now we don't want to free them */ 04806 message_link = NULL; 04807 message = NULL; 04808 } 04809 else 04810 { 04811 _dbus_verbose (" ... done dispatching\n"); 04812 } 04813 04814 _dbus_connection_release_dispatch (connection); 04815 HAVE_LOCK_CHECK (connection); 04816 04817 if (message != NULL) 04818 { 04819 /* We don't want this message to count in maximum message limits when 04820 * computing the dispatch status, below. We have to drop the lock 04821 * temporarily, because finalizing a message can trigger callbacks. 04822 * 04823 * We have a reference to the connection, and we don't use any cached 04824 * pointers to the connection's internals below this point, so it should 04825 * be safe to drop the lock and take it back. */ 04826 CONNECTION_UNLOCK (connection); 04827 dbus_message_unref (message); 04828 CONNECTION_LOCK (connection); 04829 } 04830 04831 if (message_link != NULL) 04832 _dbus_list_free_link (message_link); 04833 04834 _dbus_verbose ("before final status update\n"); 04835 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04836 04837 /* unlocks and calls user code */ 04838 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04839 04840 dbus_connection_unref (connection); 04841 04842 return status; 04843 } 04844 04906 dbus_bool_t 04907 dbus_connection_set_watch_functions (DBusConnection *connection, 04908 DBusAddWatchFunction add_function, 04909 DBusRemoveWatchFunction remove_function, 04910 DBusWatchToggledFunction toggled_function, 04911 void *data, 04912 DBusFreeFunction free_data_function) 04913 { 04914 dbus_bool_t retval; 04915 04916 _dbus_return_val_if_fail (connection != NULL, FALSE); 04917 04918 CONNECTION_LOCK (connection); 04919 04920 retval = _dbus_watch_list_set_functions (connection->watches, 04921 add_function, remove_function, 04922 toggled_function, 04923 data, free_data_function); 04924 04925 CONNECTION_UNLOCK (connection); 04926 04927 return retval; 04928 } 04929 04969 dbus_bool_t 04970 dbus_connection_set_timeout_functions (DBusConnection *connection, 04971 DBusAddTimeoutFunction add_function, 04972 DBusRemoveTimeoutFunction remove_function, 04973 DBusTimeoutToggledFunction toggled_function, 04974 void *data, 04975 DBusFreeFunction free_data_function) 04976 { 04977 dbus_bool_t retval; 04978 04979 _dbus_return_val_if_fail (connection != NULL, FALSE); 04980 04981 CONNECTION_LOCK (connection); 04982 04983 retval = _dbus_timeout_list_set_functions (connection->timeouts, 04984 add_function, remove_function, 04985 toggled_function, 04986 data, free_data_function); 04987 04988 CONNECTION_UNLOCK (connection); 04989 04990 return retval; 04991 } 04992 05007 void 05008 dbus_connection_set_wakeup_main_function (DBusConnection *connection, 05009 DBusWakeupMainFunction wakeup_main_function, 05010 void *data, 05011 DBusFreeFunction free_data_function) 05012 { 05013 void *old_data; 05014 DBusFreeFunction old_free_data; 05015 05016 _dbus_return_if_fail (connection != NULL); 05017 05018 CONNECTION_LOCK (connection); 05019 old_data = connection->wakeup_main_data; 05020 old_free_data = connection->free_wakeup_main_data; 05021 05022 connection->wakeup_main_function = wakeup_main_function; 05023 connection->wakeup_main_data = data; 05024 connection->free_wakeup_main_data = free_data_function; 05025 05026 CONNECTION_UNLOCK (connection); 05027 05028 /* Callback outside the lock */ 05029 if (old_free_data) 05030 (*old_free_data) (old_data); 05031 } 05032 05053 void 05054 dbus_connection_set_dispatch_status_function (DBusConnection *connection, 05055 DBusDispatchStatusFunction function, 05056 void *data, 05057 DBusFreeFunction free_data_function) 05058 { 05059 void *old_data; 05060 DBusFreeFunction old_free_data; 05061 05062 _dbus_return_if_fail (connection != NULL); 05063 05064 CONNECTION_LOCK (connection); 05065 old_data = connection->dispatch_status_data; 05066 old_free_data = connection->free_dispatch_status_data; 05067 05068 connection->dispatch_status_function = function; 05069 connection->dispatch_status_data = data; 05070 connection->free_dispatch_status_data = free_data_function; 05071 05072 CONNECTION_UNLOCK (connection); 05073 05074 /* Callback outside the lock */ 05075 if (old_free_data) 05076 (*old_free_data) (old_data); 05077 } 05078 05098 dbus_bool_t 05099 dbus_connection_get_unix_fd (DBusConnection *connection, 05100 int *fd) 05101 { 05102 _dbus_return_val_if_fail (connection != NULL, FALSE); 05103 _dbus_return_val_if_fail (connection->transport != NULL, FALSE); 05104 05105 #ifdef DBUS_WIN 05106 /* FIXME do this on a lower level */ 05107 return FALSE; 05108 #endif 05109 05110 return dbus_connection_get_socket(connection, fd); 05111 } 05112 05128 dbus_bool_t 05129 dbus_connection_get_socket(DBusConnection *connection, 05130 int *fd) 05131 { 05132 dbus_bool_t retval; 05133 05134 _dbus_return_val_if_fail (connection != NULL, FALSE); 05135 _dbus_return_val_if_fail (connection->transport != NULL, FALSE); 05136 05137 CONNECTION_LOCK (connection); 05138 05139 retval = _dbus_transport_get_socket_fd (connection->transport, 05140 fd); 05141 05142 CONNECTION_UNLOCK (connection); 05143 05144 return retval; 05145 } 05146 05147 05170 dbus_bool_t 05171 dbus_connection_get_unix_user (DBusConnection *connection, 05172 unsigned long *uid) 05173 { 05174 dbus_bool_t result; 05175 05176 _dbus_return_val_if_fail (connection != NULL, FALSE); 05177 _dbus_return_val_if_fail (uid != NULL, FALSE); 05178 05179 CONNECTION_LOCK (connection); 05180 05181 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05182 result = FALSE; 05183 else 05184 result = _dbus_transport_get_unix_user (connection->transport, 05185 uid); 05186 05187 #ifdef DBUS_WIN 05188 _dbus_assert (!result); 05189 #endif 05190 05191 CONNECTION_UNLOCK (connection); 05192 05193 return result; 05194 } 05195 05206 dbus_bool_t 05207 dbus_connection_get_unix_process_id (DBusConnection *connection, 05208 unsigned long *pid) 05209 { 05210 dbus_bool_t result; 05211 05212 _dbus_return_val_if_fail (connection != NULL, FALSE); 05213 _dbus_return_val_if_fail (pid != NULL, FALSE); 05214 05215 CONNECTION_LOCK (connection); 05216 05217 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05218 result = FALSE; 05219 else 05220 result = _dbus_transport_get_unix_process_id (connection->transport, 05221 pid); 05222 05223 CONNECTION_UNLOCK (connection); 05224 05225 return result; 05226 } 05227 05238 dbus_bool_t 05239 dbus_connection_get_adt_audit_session_data (DBusConnection *connection, 05240 void **data, 05241 dbus_int32_t *data_size) 05242 { 05243 dbus_bool_t result; 05244 05245 _dbus_return_val_if_fail (connection != NULL, FALSE); 05246 _dbus_return_val_if_fail (data != NULL, FALSE); 05247 _dbus_return_val_if_fail (data_size != NULL, FALSE); 05248 05249 CONNECTION_LOCK (connection); 05250 05251 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05252 result = FALSE; 05253 else 05254 result = _dbus_transport_get_adt_audit_session_data (connection->transport, 05255 data, 05256 data_size); 05257 CONNECTION_UNLOCK (connection); 05258 05259 return result; 05260 } 05261 05284 void 05285 dbus_connection_set_unix_user_function (DBusConnection *connection, 05286 DBusAllowUnixUserFunction function, 05287 void *data, 05288 DBusFreeFunction free_data_function) 05289 { 05290 void *old_data = NULL; 05291 DBusFreeFunction old_free_function = NULL; 05292 05293 _dbus_return_if_fail (connection != NULL); 05294 05295 CONNECTION_LOCK (connection); 05296 _dbus_transport_set_unix_user_function (connection->transport, 05297 function, data, free_data_function, 05298 &old_data, &old_free_function); 05299 CONNECTION_UNLOCK (connection); 05300 05301 if (old_free_function != NULL) 05302 (* old_free_function) (old_data); 05303 } 05304 05336 dbus_bool_t 05337 dbus_connection_get_windows_user (DBusConnection *connection, 05338 char **windows_sid_p) 05339 { 05340 dbus_bool_t result; 05341 05342 _dbus_return_val_if_fail (connection != NULL, FALSE); 05343 _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE); 05344 05345 CONNECTION_LOCK (connection); 05346 05347 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05348 result = FALSE; 05349 else 05350 result = _dbus_transport_get_windows_user (connection->transport, 05351 windows_sid_p); 05352 05353 #ifdef DBUS_UNIX 05354 _dbus_assert (!result); 05355 #endif 05356 05357 CONNECTION_UNLOCK (connection); 05358 05359 return result; 05360 } 05361 05383 void 05384 dbus_connection_set_windows_user_function (DBusConnection *connection, 05385 DBusAllowWindowsUserFunction function, 05386 void *data, 05387 DBusFreeFunction free_data_function) 05388 { 05389 void *old_data = NULL; 05390 DBusFreeFunction old_free_function = NULL; 05391 05392 _dbus_return_if_fail (connection != NULL); 05393 05394 CONNECTION_LOCK (connection); 05395 _dbus_transport_set_windows_user_function (connection->transport, 05396 function, data, free_data_function, 05397 &old_data, &old_free_function); 05398 CONNECTION_UNLOCK (connection); 05399 05400 if (old_free_function != NULL) 05401 (* old_free_function) (old_data); 05402 } 05403 05430 void 05431 dbus_connection_set_allow_anonymous (DBusConnection *connection, 05432 dbus_bool_t value) 05433 { 05434 _dbus_return_if_fail (connection != NULL); 05435 05436 CONNECTION_LOCK (connection); 05437 _dbus_transport_set_allow_anonymous (connection->transport, value); 05438 CONNECTION_UNLOCK (connection); 05439 } 05440 05458 void 05459 dbus_connection_set_route_peer_messages (DBusConnection *connection, 05460 dbus_bool_t value) 05461 { 05462 _dbus_return_if_fail (connection != NULL); 05463 05464 CONNECTION_LOCK (connection); 05465 connection->route_peer_messages = value; 05466 CONNECTION_UNLOCK (connection); 05467 } 05468 05490 dbus_bool_t 05491 dbus_connection_add_filter (DBusConnection *connection, 05492 DBusHandleMessageFunction function, 05493 void *user_data, 05494 DBusFreeFunction free_data_function) 05495 { 05496 DBusMessageFilter *filter; 05497 05498 _dbus_return_val_if_fail (connection != NULL, FALSE); 05499 _dbus_return_val_if_fail (function != NULL, FALSE); 05500 05501 filter = dbus_new0 (DBusMessageFilter, 1); 05502 if (filter == NULL) 05503 return FALSE; 05504 05505 _dbus_atomic_inc (&filter->refcount); 05506 05507 CONNECTION_LOCK (connection); 05508 05509 if (!_dbus_list_append (&connection->filter_list, 05510 filter)) 05511 { 05512 _dbus_message_filter_unref (filter); 05513 CONNECTION_UNLOCK (connection); 05514 return FALSE; 05515 } 05516 05517 /* Fill in filter after all memory allocated, 05518 * so we don't run the free_user_data_function 05519 * if the add_filter() fails 05520 */ 05521 05522 filter->function = function; 05523 filter->user_data = user_data; 05524 filter->free_user_data_function = free_data_function; 05525 05526 CONNECTION_UNLOCK (connection); 05527 return TRUE; 05528 } 05529 05542 void 05543 dbus_connection_remove_filter (DBusConnection *connection, 05544 DBusHandleMessageFunction function, 05545 void *user_data) 05546 { 05547 DBusList *link; 05548 DBusMessageFilter *filter; 05549 05550 _dbus_return_if_fail (connection != NULL); 05551 _dbus_return_if_fail (function != NULL); 05552 05553 CONNECTION_LOCK (connection); 05554 05555 filter = NULL; 05556 05557 link = _dbus_list_get_last_link (&connection->filter_list); 05558 while (link != NULL) 05559 { 05560 filter = link->data; 05561 05562 if (filter->function == function && 05563 filter->user_data == user_data) 05564 { 05565 _dbus_list_remove_link (&connection->filter_list, link); 05566 filter->function = NULL; 05567 05568 break; 05569 } 05570 05571 link = _dbus_list_get_prev_link (&connection->filter_list, link); 05572 filter = NULL; 05573 } 05574 05575 CONNECTION_UNLOCK (connection); 05576 05577 #ifndef DBUS_DISABLE_CHECKS 05578 if (filter == NULL) 05579 { 05580 _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n", 05581 function, user_data); 05582 return; 05583 } 05584 #endif 05585 05586 /* Call application code */ 05587 if (filter->free_user_data_function) 05588 (* filter->free_user_data_function) (filter->user_data); 05589 05590 filter->free_user_data_function = NULL; 05591 filter->user_data = NULL; 05592 05593 _dbus_message_filter_unref (filter); 05594 } 05595 05611 static dbus_bool_t 05612 _dbus_connection_register_object_path (DBusConnection *connection, 05613 dbus_bool_t fallback, 05614 const char *path, 05615 const DBusObjectPathVTable *vtable, 05616 void *user_data, 05617 DBusError *error) 05618 { 05619 char **decomposed_path; 05620 dbus_bool_t retval; 05621 05622 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05623 return FALSE; 05624 05625 CONNECTION_LOCK (connection); 05626 05627 retval = _dbus_object_tree_register (connection->objects, 05628 fallback, 05629 (const char **) decomposed_path, vtable, 05630 user_data, error); 05631 05632 CONNECTION_UNLOCK (connection); 05633 05634 dbus_free_string_array (decomposed_path); 05635 05636 return retval; 05637 } 05638 05651 dbus_bool_t 05652 dbus_connection_try_register_object_path (DBusConnection *connection, 05653 const char *path, 05654 const DBusObjectPathVTable *vtable, 05655 void *user_data, 05656 DBusError *error) 05657 { 05658 _dbus_return_val_if_fail (connection != NULL, FALSE); 05659 _dbus_return_val_if_fail (path != NULL, FALSE); 05660 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05661 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05662 05663 return _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, error); 05664 } 05665 05681 dbus_bool_t 05682 dbus_connection_register_object_path (DBusConnection *connection, 05683 const char *path, 05684 const DBusObjectPathVTable *vtable, 05685 void *user_data) 05686 { 05687 dbus_bool_t retval; 05688 DBusError error = DBUS_ERROR_INIT; 05689 05690 _dbus_return_val_if_fail (connection != NULL, FALSE); 05691 _dbus_return_val_if_fail (path != NULL, FALSE); 05692 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05693 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05694 05695 retval = _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, &error); 05696 05697 if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE)) 05698 { 05699 _dbus_warn ("%s\n", error.message); 05700 dbus_error_free (&error); 05701 return FALSE; 05702 } 05703 05704 return retval; 05705 } 05706 05721 dbus_bool_t 05722 dbus_connection_try_register_fallback (DBusConnection *connection, 05723 const char *path, 05724 const DBusObjectPathVTable *vtable, 05725 void *user_data, 05726 DBusError *error) 05727 { 05728 _dbus_return_val_if_fail (connection != NULL, FALSE); 05729 _dbus_return_val_if_fail (path != NULL, FALSE); 05730 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05731 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05732 05733 return _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, error); 05734 } 05735 05753 dbus_bool_t 05754 dbus_connection_register_fallback (DBusConnection *connection, 05755 const char *path, 05756 const DBusObjectPathVTable *vtable, 05757 void *user_data) 05758 { 05759 dbus_bool_t retval; 05760 DBusError error = DBUS_ERROR_INIT; 05761 05762 _dbus_return_val_if_fail (connection != NULL, FALSE); 05763 _dbus_return_val_if_fail (path != NULL, FALSE); 05764 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05765 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05766 05767 retval = _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, &error); 05768 05769 if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE)) 05770 { 05771 _dbus_warn ("%s\n", error.message); 05772 dbus_error_free (&error); 05773 return FALSE; 05774 } 05775 05776 return retval; 05777 } 05778 05788 dbus_bool_t 05789 dbus_connection_unregister_object_path (DBusConnection *connection, 05790 const char *path) 05791 { 05792 char **decomposed_path; 05793 05794 _dbus_return_val_if_fail (connection != NULL, FALSE); 05795 _dbus_return_val_if_fail (path != NULL, FALSE); 05796 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05797 05798 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05799 return FALSE; 05800 05801 CONNECTION_LOCK (connection); 05802 05803 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path); 05804 05805 dbus_free_string_array (decomposed_path); 05806 05807 return TRUE; 05808 } 05809 05820 dbus_bool_t 05821 dbus_connection_get_object_path_data (DBusConnection *connection, 05822 const char *path, 05823 void **data_p) 05824 { 05825 char **decomposed_path; 05826 05827 _dbus_return_val_if_fail (connection != NULL, FALSE); 05828 _dbus_return_val_if_fail (path != NULL, FALSE); 05829 _dbus_return_val_if_fail (data_p != NULL, FALSE); 05830 05831 *data_p = NULL; 05832 05833 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05834 return FALSE; 05835 05836 CONNECTION_LOCK (connection); 05837 05838 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path); 05839 05840 CONNECTION_UNLOCK (connection); 05841 05842 dbus_free_string_array (decomposed_path); 05843 05844 return TRUE; 05845 } 05846 05857 dbus_bool_t 05858 dbus_connection_list_registered (DBusConnection *connection, 05859 const char *parent_path, 05860 char ***child_entries) 05861 { 05862 char **decomposed_path; 05863 dbus_bool_t retval; 05864 _dbus_return_val_if_fail (connection != NULL, FALSE); 05865 _dbus_return_val_if_fail (parent_path != NULL, FALSE); 05866 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE); 05867 _dbus_return_val_if_fail (child_entries != NULL, FALSE); 05868 05869 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL)) 05870 return FALSE; 05871 05872 CONNECTION_LOCK (connection); 05873 05874 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects, 05875 (const char **) decomposed_path, 05876 child_entries); 05877 dbus_free_string_array (decomposed_path); 05878 05879 return retval; 05880 } 05881 05882 static DBusDataSlotAllocator slot_allocator; 05883 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots); 05884 05899 dbus_bool_t 05900 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p) 05901 { 05902 return _dbus_data_slot_allocator_alloc (&slot_allocator, 05903 &_DBUS_LOCK_NAME (connection_slots), 05904 slot_p); 05905 } 05906 05918 void 05919 dbus_connection_free_data_slot (dbus_int32_t *slot_p) 05920 { 05921 _dbus_return_if_fail (*slot_p >= 0); 05922 05923 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 05924 } 05925 05948 dbus_bool_t 05949 dbus_connection_set_data (DBusConnection *connection, 05950 dbus_int32_t slot, 05951 void *data, 05952 DBusFreeFunction free_data_func) 05953 { 05954 DBusFreeFunction old_free_func; 05955 void *old_data; 05956 dbus_bool_t retval; 05957 05958 _dbus_return_val_if_fail (connection != NULL, FALSE); 05959 _dbus_return_val_if_fail (slot >= 0, FALSE); 05960 05961 SLOTS_LOCK (connection); 05962 05963 retval = _dbus_data_slot_list_set (&slot_allocator, 05964 &connection->slot_list, 05965 slot, data, free_data_func, 05966 &old_free_func, &old_data); 05967 05968 SLOTS_UNLOCK (connection); 05969 05970 if (retval) 05971 { 05972 /* Do the actual free outside the connection lock */ 05973 if (old_free_func) 05974 (* old_free_func) (old_data); 05975 } 05976 05977 return retval; 05978 } 05979 05997 void* 05998 dbus_connection_get_data (DBusConnection *connection, 05999 dbus_int32_t slot) 06000 { 06001 void *res; 06002 06003 _dbus_return_val_if_fail (connection != NULL, NULL); 06004 _dbus_return_val_if_fail (slot >= 0, NULL); 06005 06006 SLOTS_LOCK (connection); 06007 06008 res = _dbus_data_slot_list_get (&slot_allocator, 06009 &connection->slot_list, 06010 slot); 06011 06012 SLOTS_UNLOCK (connection); 06013 06014 return res; 06015 } 06016 06023 void 06024 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe) 06025 { 06026 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE; 06027 } 06028 06037 void 06038 dbus_connection_set_max_message_size (DBusConnection *connection, 06039 long size) 06040 { 06041 _dbus_return_if_fail (connection != NULL); 06042 06043 CONNECTION_LOCK (connection); 06044 _dbus_transport_set_max_message_size (connection->transport, 06045 size); 06046 CONNECTION_UNLOCK (connection); 06047 } 06048 06055 long 06056 dbus_connection_get_max_message_size (DBusConnection *connection) 06057 { 06058 long res; 06059 06060 _dbus_return_val_if_fail (connection != NULL, 0); 06061 06062 CONNECTION_LOCK (connection); 06063 res = _dbus_transport_get_max_message_size (connection->transport); 06064 CONNECTION_UNLOCK (connection); 06065 return res; 06066 } 06067 06076 void 06077 dbus_connection_set_max_message_unix_fds (DBusConnection *connection, 06078 long n) 06079 { 06080 _dbus_return_if_fail (connection != NULL); 06081 06082 CONNECTION_LOCK (connection); 06083 _dbus_transport_set_max_message_unix_fds (connection->transport, 06084 n); 06085 CONNECTION_UNLOCK (connection); 06086 } 06087 06094 long 06095 dbus_connection_get_max_message_unix_fds (DBusConnection *connection) 06096 { 06097 long res; 06098 06099 _dbus_return_val_if_fail (connection != NULL, 0); 06100 06101 CONNECTION_LOCK (connection); 06102 res = _dbus_transport_get_max_message_unix_fds (connection->transport); 06103 CONNECTION_UNLOCK (connection); 06104 return res; 06105 } 06106 06132 void 06133 dbus_connection_set_max_received_size (DBusConnection *connection, 06134 long size) 06135 { 06136 _dbus_return_if_fail (connection != NULL); 06137 06138 CONNECTION_LOCK (connection); 06139 _dbus_transport_set_max_received_size (connection->transport, 06140 size); 06141 CONNECTION_UNLOCK (connection); 06142 } 06143 06150 long 06151 dbus_connection_get_max_received_size (DBusConnection *connection) 06152 { 06153 long res; 06154 06155 _dbus_return_val_if_fail (connection != NULL, 0); 06156 06157 CONNECTION_LOCK (connection); 06158 res = _dbus_transport_get_max_received_size (connection->transport); 06159 CONNECTION_UNLOCK (connection); 06160 return res; 06161 } 06162 06174 void 06175 dbus_connection_set_max_received_unix_fds (DBusConnection *connection, 06176 long n) 06177 { 06178 _dbus_return_if_fail (connection != NULL); 06179 06180 CONNECTION_LOCK (connection); 06181 _dbus_transport_set_max_received_unix_fds (connection->transport, 06182 n); 06183 CONNECTION_UNLOCK (connection); 06184 } 06185 06192 long 06193 dbus_connection_get_max_received_unix_fds (DBusConnection *connection) 06194 { 06195 long res; 06196 06197 _dbus_return_val_if_fail (connection != NULL, 0); 06198 06199 CONNECTION_LOCK (connection); 06200 res = _dbus_transport_get_max_received_unix_fds (connection->transport); 06201 CONNECTION_UNLOCK (connection); 06202 return res; 06203 } 06204 06215 long 06216 dbus_connection_get_outgoing_size (DBusConnection *connection) 06217 { 06218 long res; 06219 06220 _dbus_return_val_if_fail (connection != NULL, 0); 06221 06222 CONNECTION_LOCK (connection); 06223 res = _dbus_counter_get_size_value (connection->outgoing_counter); 06224 CONNECTION_UNLOCK (connection); 06225 return res; 06226 } 06227 06228 #ifdef DBUS_ENABLE_STATS 06229 void 06230 _dbus_connection_get_stats (DBusConnection *connection, 06231 dbus_uint32_t *in_messages, 06232 dbus_uint32_t *in_bytes, 06233 dbus_uint32_t *in_fds, 06234 dbus_uint32_t *in_peak_bytes, 06235 dbus_uint32_t *in_peak_fds, 06236 dbus_uint32_t *out_messages, 06237 dbus_uint32_t *out_bytes, 06238 dbus_uint32_t *out_fds, 06239 dbus_uint32_t *out_peak_bytes, 06240 dbus_uint32_t *out_peak_fds) 06241 { 06242 CONNECTION_LOCK (connection); 06243 06244 if (in_messages != NULL) 06245 *in_messages = connection->n_incoming; 06246 06247 _dbus_transport_get_stats (connection->transport, 06248 in_bytes, in_fds, in_peak_bytes, in_peak_fds); 06249 06250 if (out_messages != NULL) 06251 *out_messages = connection->n_outgoing; 06252 06253 if (out_bytes != NULL) 06254 *out_bytes = _dbus_counter_get_size_value (connection->outgoing_counter); 06255 06256 if (out_fds != NULL) 06257 *out_fds = _dbus_counter_get_unix_fd_value (connection->outgoing_counter); 06258 06259 if (out_peak_bytes != NULL) 06260 *out_peak_bytes = _dbus_counter_get_peak_size_value (connection->outgoing_counter); 06261 06262 if (out_peak_fds != NULL) 06263 *out_peak_fds = _dbus_counter_get_peak_unix_fd_value (connection->outgoing_counter); 06264 06265 CONNECTION_UNLOCK (connection); 06266 } 06267 #endif /* DBUS_ENABLE_STATS */ 06268 06276 long 06277 dbus_connection_get_outgoing_unix_fds (DBusConnection *connection) 06278 { 06279 long res; 06280 06281 _dbus_return_val_if_fail (connection != NULL, 0); 06282 06283 CONNECTION_LOCK (connection); 06284 res = _dbus_counter_get_unix_fd_value (connection->outgoing_counter); 06285 CONNECTION_UNLOCK (connection); 06286 return res; 06287 } 06288 06289 #ifdef DBUS_BUILD_TESTS 06290 06296 const char* 06297 _dbus_connection_get_address (DBusConnection *connection) 06298 { 06299 return _dbus_transport_get_address (connection->transport); 06300 } 06301 #endif 06302
1.7.6.1