|
D-Bus
1.5.8
|
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_mutex_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_mutex_lock ((connection)->slot_mutex); \ 00077 } while (0) 00078 00079 #define SLOTS_UNLOCK(connection) do { \ 00080 _dbus_mutex_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 00209 typedef struct DBusMessageFilter DBusMessageFilter; 00210 00214 struct DBusMessageFilter 00215 { 00216 DBusAtomic refcount; 00217 DBusHandleMessageFunction function; 00218 void *user_data; 00219 DBusFreeFunction free_user_data_function; 00220 }; 00221 00222 00226 struct DBusPreallocatedSend 00227 { 00228 DBusConnection *connection; 00229 DBusList *queue_link; 00230 DBusList *counter_link; 00231 }; 00232 00233 #if HAVE_DECL_MSG_NOSIGNAL 00234 static dbus_bool_t _dbus_modify_sigpipe = FALSE; 00235 #else 00236 static dbus_bool_t _dbus_modify_sigpipe = TRUE; 00237 #endif 00238 00242 struct DBusConnection 00243 { 00244 DBusAtomic refcount; 00246 DBusMutex *mutex; 00248 DBusMutex *dispatch_mutex; 00249 DBusCondVar *dispatch_cond; 00250 DBusMutex *io_path_mutex; 00251 DBusCondVar *io_path_cond; 00253 DBusList *outgoing_messages; 00254 DBusList *incoming_messages; 00255 DBusList *expired_messages; 00257 DBusMessage *message_borrowed; 00261 int n_outgoing; 00262 int n_incoming; 00264 DBusCounter *outgoing_counter; 00266 DBusTransport *transport; 00267 DBusWatchList *watches; 00268 DBusTimeoutList *timeouts; 00270 DBusList *filter_list; 00272 DBusMutex *slot_mutex; 00273 DBusDataSlotList slot_list; 00275 DBusHashTable *pending_replies; 00277 dbus_uint32_t client_serial; 00278 DBusList *disconnect_message_link; 00280 DBusWakeupMainFunction wakeup_main_function; 00281 void *wakeup_main_data; 00282 DBusFreeFunction free_wakeup_main_data; 00284 DBusDispatchStatusFunction dispatch_status_function; 00285 void *dispatch_status_data; 00286 DBusFreeFunction free_dispatch_status_data; 00288 DBusDispatchStatus last_dispatch_status; 00290 DBusObjectTree *objects; 00292 char *server_guid; 00294 /* These two MUST be bools and not bitfields, because they are protected by a separate lock 00295 * from connection->mutex and all bitfields in a word have to be read/written together. 00296 * So you can't have a different lock for different bitfields in the same word. 00297 */ 00298 dbus_bool_t dispatch_acquired; 00299 dbus_bool_t io_path_acquired; 00301 unsigned int shareable : 1; 00303 unsigned int exit_on_disconnect : 1; 00305 unsigned int route_peer_messages : 1; 00307 unsigned int disconnected_message_arrived : 1; 00311 unsigned int disconnected_message_processed : 1; 00315 #ifndef DBUS_DISABLE_CHECKS 00316 unsigned int have_connection_lock : 1; 00317 #endif 00318 00319 #ifndef DBUS_DISABLE_CHECKS 00320 int generation; 00321 #endif 00322 }; 00323 00324 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection); 00325 static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection, 00326 DBusDispatchStatus new_status); 00327 static void _dbus_connection_last_unref (DBusConnection *connection); 00328 static void _dbus_connection_acquire_dispatch (DBusConnection *connection); 00329 static void _dbus_connection_release_dispatch (DBusConnection *connection); 00330 static DBusDispatchStatus _dbus_connection_flush_unlocked (DBusConnection *connection); 00331 static void _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection); 00332 static dbus_bool_t _dbus_connection_get_is_connected_unlocked (DBusConnection *connection); 00333 static dbus_bool_t _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection, 00334 dbus_uint32_t client_serial); 00335 00336 static DBusMessageFilter * 00337 _dbus_message_filter_ref (DBusMessageFilter *filter) 00338 { 00339 #ifdef DBUS_DISABLE_ASSERT 00340 _dbus_atomic_inc (&filter->refcount); 00341 #else 00342 dbus_int32_t old_value; 00343 00344 old_value = _dbus_atomic_inc (&filter->refcount); 00345 _dbus_assert (old_value > 0); 00346 #endif 00347 00348 return filter; 00349 } 00350 00351 static void 00352 _dbus_message_filter_unref (DBusMessageFilter *filter) 00353 { 00354 dbus_int32_t old_value; 00355 00356 old_value = _dbus_atomic_dec (&filter->refcount); 00357 _dbus_assert (old_value > 0); 00358 00359 if (old_value == 1) 00360 { 00361 if (filter->free_user_data_function) 00362 (* filter->free_user_data_function) (filter->user_data); 00363 00364 dbus_free (filter); 00365 } 00366 } 00367 00373 void 00374 _dbus_connection_lock (DBusConnection *connection) 00375 { 00376 CONNECTION_LOCK (connection); 00377 } 00378 00384 void 00385 _dbus_connection_unlock (DBusConnection *connection) 00386 { 00387 DBusList *expired_messages; 00388 DBusList *iter; 00389 00390 if (TRACE_LOCKS) 00391 { 00392 _dbus_verbose ("UNLOCK\n"); 00393 } 00394 00395 /* If we had messages that expired (fell off the incoming or outgoing 00396 * queues) while we were locked, actually release them now */ 00397 expired_messages = connection->expired_messages; 00398 connection->expired_messages = NULL; 00399 00400 RELEASING_LOCK_CHECK (connection); 00401 _dbus_mutex_unlock (connection->mutex); 00402 00403 for (iter = _dbus_list_pop_first_link (&expired_messages); 00404 iter != NULL; 00405 iter = _dbus_list_pop_first_link (&expired_messages)) 00406 { 00407 DBusMessage *message = iter->data; 00408 00409 dbus_message_unref (message); 00410 _dbus_list_free_link (iter); 00411 } 00412 } 00413 00421 static void 00422 _dbus_connection_wakeup_mainloop (DBusConnection *connection) 00423 { 00424 if (connection->wakeup_main_function) 00425 (*connection->wakeup_main_function) (connection->wakeup_main_data); 00426 } 00427 00428 #ifdef DBUS_BUILD_TESTS 00429 /* For now this function isn't used */ 00439 dbus_bool_t 00440 _dbus_connection_queue_received_message (DBusConnection *connection, 00441 DBusMessage *message) 00442 { 00443 DBusList *link; 00444 00445 link = _dbus_list_alloc_link (message); 00446 if (link == NULL) 00447 return FALSE; 00448 00449 dbus_message_ref (message); 00450 _dbus_connection_queue_received_message_link (connection, link); 00451 00452 return TRUE; 00453 } 00454 00467 void 00468 _dbus_connection_test_get_locks (DBusConnection *connection, 00469 DBusMutex **mutex_loc, 00470 DBusMutex **dispatch_mutex_loc, 00471 DBusMutex **io_path_mutex_loc, 00472 DBusCondVar **dispatch_cond_loc, 00473 DBusCondVar **io_path_cond_loc) 00474 { 00475 *mutex_loc = connection->mutex; 00476 *dispatch_mutex_loc = connection->dispatch_mutex; 00477 *io_path_mutex_loc = connection->io_path_mutex; 00478 *dispatch_cond_loc = connection->dispatch_cond; 00479 *io_path_cond_loc = connection->io_path_cond; 00480 } 00481 #endif 00482 00491 void 00492 _dbus_connection_queue_received_message_link (DBusConnection *connection, 00493 DBusList *link) 00494 { 00495 DBusPendingCall *pending; 00496 dbus_uint32_t reply_serial; 00497 DBusMessage *message; 00498 00499 _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport)); 00500 00501 _dbus_list_append_link (&connection->incoming_messages, 00502 link); 00503 message = link->data; 00504 00505 /* If this is a reply we're waiting on, remove timeout for it */ 00506 reply_serial = dbus_message_get_reply_serial (message); 00507 if (reply_serial != 0) 00508 { 00509 pending = _dbus_hash_table_lookup_int (connection->pending_replies, 00510 reply_serial); 00511 if (pending != NULL) 00512 { 00513 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 00514 _dbus_connection_remove_timeout_unlocked (connection, 00515 _dbus_pending_call_get_timeout_unlocked (pending)); 00516 00517 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 00518 } 00519 } 00520 00521 00522 00523 connection->n_incoming += 1; 00524 00525 _dbus_connection_wakeup_mainloop (connection); 00526 00527 _dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n", 00528 message, 00529 dbus_message_type_to_string (dbus_message_get_type (message)), 00530 dbus_message_get_path (message) ? 00531 dbus_message_get_path (message) : 00532 "no path", 00533 dbus_message_get_interface (message) ? 00534 dbus_message_get_interface (message) : 00535 "no interface", 00536 dbus_message_get_member (message) ? 00537 dbus_message_get_member (message) : 00538 "no member", 00539 dbus_message_get_signature (message), 00540 dbus_message_get_reply_serial (message), 00541 connection, 00542 connection->n_incoming);} 00543 00552 void 00553 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection, 00554 DBusList *link) 00555 { 00556 HAVE_LOCK_CHECK (connection); 00557 00558 _dbus_list_append_link (&connection->incoming_messages, link); 00559 00560 connection->n_incoming += 1; 00561 00562 _dbus_connection_wakeup_mainloop (connection); 00563 00564 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n", 00565 link->data, connection, connection->n_incoming); 00566 } 00567 00568 00576 dbus_bool_t 00577 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection) 00578 { 00579 HAVE_LOCK_CHECK (connection); 00580 return connection->outgoing_messages != NULL; 00581 } 00582 00592 dbus_bool_t 00593 dbus_connection_has_messages_to_send (DBusConnection *connection) 00594 { 00595 dbus_bool_t v; 00596 00597 _dbus_return_val_if_fail (connection != NULL, FALSE); 00598 00599 CONNECTION_LOCK (connection); 00600 v = _dbus_connection_has_messages_to_send_unlocked (connection); 00601 CONNECTION_UNLOCK (connection); 00602 00603 return v; 00604 } 00605 00613 DBusMessage* 00614 _dbus_connection_get_message_to_send (DBusConnection *connection) 00615 { 00616 HAVE_LOCK_CHECK (connection); 00617 00618 return _dbus_list_get_last (&connection->outgoing_messages); 00619 } 00620 00629 void 00630 _dbus_connection_message_sent_unlocked (DBusConnection *connection, 00631 DBusMessage *message) 00632 { 00633 DBusList *link; 00634 00635 HAVE_LOCK_CHECK (connection); 00636 00637 /* This can be called before we even complete authentication, since 00638 * it's called on disconnect to clean up the outgoing queue. 00639 * It's also called as we successfully send each message. 00640 */ 00641 00642 link = _dbus_list_get_last_link (&connection->outgoing_messages); 00643 _dbus_assert (link != NULL); 00644 _dbus_assert (link->data == message); 00645 00646 _dbus_list_unlink (&connection->outgoing_messages, 00647 link); 00648 _dbus_list_prepend_link (&connection->expired_messages, link); 00649 00650 connection->n_outgoing -= 1; 00651 00652 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n", 00653 message, 00654 dbus_message_type_to_string (dbus_message_get_type (message)), 00655 dbus_message_get_path (message) ? 00656 dbus_message_get_path (message) : 00657 "no path", 00658 dbus_message_get_interface (message) ? 00659 dbus_message_get_interface (message) : 00660 "no interface", 00661 dbus_message_get_member (message) ? 00662 dbus_message_get_member (message) : 00663 "no member", 00664 dbus_message_get_signature (message), 00665 connection, connection->n_outgoing); 00666 00667 /* It's OK that in principle we call the notify function, because for the 00668 * outgoing limit, there isn't one */ 00669 _dbus_message_remove_counter (message, connection->outgoing_counter); 00670 00671 /* The message will actually be unreffed when we unlock */ 00672 } 00673 00675 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list, 00676 DBusWatch *watch); 00678 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list, 00679 DBusWatch *watch); 00681 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list, 00682 DBusWatch *watch, 00683 dbus_bool_t enabled); 00684 00685 static dbus_bool_t 00686 protected_change_watch (DBusConnection *connection, 00687 DBusWatch *watch, 00688 DBusWatchAddFunction add_function, 00689 DBusWatchRemoveFunction remove_function, 00690 DBusWatchToggleFunction toggle_function, 00691 dbus_bool_t enabled) 00692 { 00693 dbus_bool_t retval; 00694 00695 HAVE_LOCK_CHECK (connection); 00696 00697 /* The original purpose of protected_change_watch() was to hold a 00698 * ref on the connection while dropping the connection lock, then 00699 * calling out to the app. This was a broken hack that did not 00700 * work, since the connection was in a hosed state (no WatchList 00701 * field) while calling out. 00702 * 00703 * So for now we'll just keep the lock while calling out. This means 00704 * apps are not allowed to call DBusConnection methods inside a 00705 * watch function or they will deadlock. 00706 * 00707 * The "real fix" is to use the _and_unlock() pattern found 00708 * elsewhere in the code, to defer calling out to the app until 00709 * we're about to drop locks and return flow of control to the app 00710 * anyway. 00711 * 00712 * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144 00713 */ 00714 00715 if (connection->watches) 00716 { 00717 if (add_function) 00718 retval = (* add_function) (connection->watches, watch); 00719 else if (remove_function) 00720 { 00721 retval = TRUE; 00722 (* remove_function) (connection->watches, watch); 00723 } 00724 else 00725 { 00726 retval = TRUE; 00727 (* toggle_function) (connection->watches, watch, enabled); 00728 } 00729 return retval; 00730 } 00731 else 00732 return FALSE; 00733 } 00734 00735 00747 dbus_bool_t 00748 _dbus_connection_add_watch_unlocked (DBusConnection *connection, 00749 DBusWatch *watch) 00750 { 00751 return protected_change_watch (connection, watch, 00752 _dbus_watch_list_add_watch, 00753 NULL, NULL, FALSE); 00754 } 00755 00765 void 00766 _dbus_connection_remove_watch_unlocked (DBusConnection *connection, 00767 DBusWatch *watch) 00768 { 00769 protected_change_watch (connection, watch, 00770 NULL, 00771 _dbus_watch_list_remove_watch, 00772 NULL, FALSE); 00773 } 00774 00785 void 00786 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection, 00787 DBusWatch *watch, 00788 dbus_bool_t enabled) 00789 { 00790 _dbus_assert (watch != NULL); 00791 00792 protected_change_watch (connection, watch, 00793 NULL, NULL, 00794 _dbus_watch_list_toggle_watch, 00795 enabled); 00796 } 00797 00799 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list, 00800 DBusTimeout *timeout); 00802 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list, 00803 DBusTimeout *timeout); 00805 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list, 00806 DBusTimeout *timeout, 00807 dbus_bool_t enabled); 00808 00809 static dbus_bool_t 00810 protected_change_timeout (DBusConnection *connection, 00811 DBusTimeout *timeout, 00812 DBusTimeoutAddFunction add_function, 00813 DBusTimeoutRemoveFunction remove_function, 00814 DBusTimeoutToggleFunction toggle_function, 00815 dbus_bool_t enabled) 00816 { 00817 dbus_bool_t retval; 00818 00819 HAVE_LOCK_CHECK (connection); 00820 00821 /* The original purpose of protected_change_timeout() was to hold a 00822 * ref on the connection while dropping the connection lock, then 00823 * calling out to the app. This was a broken hack that did not 00824 * work, since the connection was in a hosed state (no TimeoutList 00825 * field) while calling out. 00826 * 00827 * So for now we'll just keep the lock while calling out. This means 00828 * apps are not allowed to call DBusConnection methods inside a 00829 * timeout function or they will deadlock. 00830 * 00831 * The "real fix" is to use the _and_unlock() pattern found 00832 * elsewhere in the code, to defer calling out to the app until 00833 * we're about to drop locks and return flow of control to the app 00834 * anyway. 00835 * 00836 * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144 00837 */ 00838 00839 if (connection->timeouts) 00840 { 00841 if (add_function) 00842 retval = (* add_function) (connection->timeouts, timeout); 00843 else if (remove_function) 00844 { 00845 retval = TRUE; 00846 (* remove_function) (connection->timeouts, timeout); 00847 } 00848 else 00849 { 00850 retval = TRUE; 00851 (* toggle_function) (connection->timeouts, timeout, enabled); 00852 } 00853 return retval; 00854 } 00855 else 00856 return FALSE; 00857 } 00858 00871 dbus_bool_t 00872 _dbus_connection_add_timeout_unlocked (DBusConnection *connection, 00873 DBusTimeout *timeout) 00874 { 00875 return protected_change_timeout (connection, timeout, 00876 _dbus_timeout_list_add_timeout, 00877 NULL, NULL, FALSE); 00878 } 00879 00889 void 00890 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection, 00891 DBusTimeout *timeout) 00892 { 00893 protected_change_timeout (connection, timeout, 00894 NULL, 00895 _dbus_timeout_list_remove_timeout, 00896 NULL, FALSE); 00897 } 00898 00909 void 00910 _dbus_connection_toggle_timeout_unlocked (DBusConnection *connection, 00911 DBusTimeout *timeout, 00912 dbus_bool_t enabled) 00913 { 00914 protected_change_timeout (connection, timeout, 00915 NULL, NULL, 00916 _dbus_timeout_list_toggle_timeout, 00917 enabled); 00918 } 00919 00920 static dbus_bool_t 00921 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection, 00922 DBusPendingCall *pending) 00923 { 00924 dbus_uint32_t reply_serial; 00925 DBusTimeout *timeout; 00926 00927 HAVE_LOCK_CHECK (connection); 00928 00929 reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending); 00930 00931 _dbus_assert (reply_serial != 0); 00932 00933 timeout = _dbus_pending_call_get_timeout_unlocked (pending); 00934 00935 if (timeout) 00936 { 00937 if (!_dbus_connection_add_timeout_unlocked (connection, timeout)) 00938 return FALSE; 00939 00940 if (!_dbus_hash_table_insert_int (connection->pending_replies, 00941 reply_serial, 00942 pending)) 00943 { 00944 _dbus_connection_remove_timeout_unlocked (connection, timeout); 00945 00946 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 00947 HAVE_LOCK_CHECK (connection); 00948 return FALSE; 00949 } 00950 00951 _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE); 00952 } 00953 else 00954 { 00955 if (!_dbus_hash_table_insert_int (connection->pending_replies, 00956 reply_serial, 00957 pending)) 00958 { 00959 HAVE_LOCK_CHECK (connection); 00960 return FALSE; 00961 } 00962 } 00963 00964 _dbus_pending_call_ref_unlocked (pending); 00965 00966 HAVE_LOCK_CHECK (connection); 00967 00968 return TRUE; 00969 } 00970 00971 static void 00972 free_pending_call_on_hash_removal (void *data) 00973 { 00974 DBusPendingCall *pending; 00975 DBusConnection *connection; 00976 00977 if (data == NULL) 00978 return; 00979 00980 pending = data; 00981 00982 connection = _dbus_pending_call_get_connection_unlocked (pending); 00983 00984 HAVE_LOCK_CHECK (connection); 00985 00986 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 00987 { 00988 _dbus_connection_remove_timeout_unlocked (connection, 00989 _dbus_pending_call_get_timeout_unlocked (pending)); 00990 00991 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 00992 } 00993 00994 /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock 00995 * here, but the pending call finalizer could in principle call out to 00996 * application code so we pretty much have to... some larger code reorg 00997 * might be needed. 00998 */ 00999 _dbus_connection_ref_unlocked (connection); 01000 _dbus_pending_call_unref_and_unlock (pending); 01001 CONNECTION_LOCK (connection); 01002 _dbus_connection_unref_unlocked (connection); 01003 } 01004 01005 static void 01006 _dbus_connection_detach_pending_call_unlocked (DBusConnection *connection, 01007 DBusPendingCall *pending) 01008 { 01009 /* This ends up unlocking to call the pending call finalizer, which is unexpected to 01010 * say the least. 01011 */ 01012 _dbus_hash_table_remove_int (connection->pending_replies, 01013 _dbus_pending_call_get_reply_serial_unlocked (pending)); 01014 } 01015 01016 static void 01017 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection, 01018 DBusPendingCall *pending) 01019 { 01020 /* The idea here is to avoid finalizing the pending call 01021 * with the lock held, since there's a destroy notifier 01022 * in pending call that goes out to application code. 01023 * 01024 * There's an extra unlock inside the hash table 01025 * "free pending call" function FIXME... 01026 */ 01027 _dbus_pending_call_ref_unlocked (pending); 01028 _dbus_hash_table_remove_int (connection->pending_replies, 01029 _dbus_pending_call_get_reply_serial_unlocked (pending)); 01030 01031 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 01032 _dbus_connection_remove_timeout_unlocked (connection, 01033 _dbus_pending_call_get_timeout_unlocked (pending)); 01034 01035 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 01036 01037 _dbus_pending_call_unref_and_unlock (pending); 01038 } 01039 01048 void 01049 _dbus_connection_remove_pending_call (DBusConnection *connection, 01050 DBusPendingCall *pending) 01051 { 01052 CONNECTION_LOCK (connection); 01053 _dbus_connection_detach_pending_call_and_unlock (connection, pending); 01054 } 01055 01065 static dbus_bool_t 01066 _dbus_connection_acquire_io_path (DBusConnection *connection, 01067 int timeout_milliseconds) 01068 { 01069 dbus_bool_t we_acquired; 01070 01071 HAVE_LOCK_CHECK (connection); 01072 01073 /* We don't want the connection to vanish */ 01074 _dbus_connection_ref_unlocked (connection); 01075 01076 /* We will only touch io_path_acquired which is protected by our mutex */ 01077 CONNECTION_UNLOCK (connection); 01078 01079 _dbus_verbose ("locking io_path_mutex\n"); 01080 _dbus_mutex_lock (connection->io_path_mutex); 01081 01082 _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n", 01083 connection->io_path_acquired, timeout_milliseconds); 01084 01085 we_acquired = FALSE; 01086 01087 if (connection->io_path_acquired) 01088 { 01089 if (timeout_milliseconds != -1) 01090 { 01091 _dbus_verbose ("waiting %d for IO path to be acquirable\n", 01092 timeout_milliseconds); 01093 01094 if (!_dbus_condvar_wait_timeout (connection->io_path_cond, 01095 connection->io_path_mutex, 01096 timeout_milliseconds)) 01097 { 01098 /* We timed out before anyone signaled. */ 01099 /* (writing the loop to handle the !timedout case by 01100 * waiting longer if needed is a pain since dbus 01101 * wraps pthread_cond_timedwait to take a relative 01102 * time instead of absolute, something kind of stupid 01103 * on our part. for now it doesn't matter, we will just 01104 * end up back here eventually.) 01105 */ 01106 } 01107 } 01108 else 01109 { 01110 while (connection->io_path_acquired) 01111 { 01112 _dbus_verbose ("waiting for IO path to be acquirable\n"); 01113 _dbus_condvar_wait (connection->io_path_cond, 01114 connection->io_path_mutex); 01115 } 01116 } 01117 } 01118 01119 if (!connection->io_path_acquired) 01120 { 01121 we_acquired = TRUE; 01122 connection->io_path_acquired = TRUE; 01123 } 01124 01125 _dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n", 01126 connection->io_path_acquired, we_acquired); 01127 01128 _dbus_verbose ("unlocking io_path_mutex\n"); 01129 _dbus_mutex_unlock (connection->io_path_mutex); 01130 01131 CONNECTION_LOCK (connection); 01132 01133 HAVE_LOCK_CHECK (connection); 01134 01135 _dbus_connection_unref_unlocked (connection); 01136 01137 return we_acquired; 01138 } 01139 01147 static void 01148 _dbus_connection_release_io_path (DBusConnection *connection) 01149 { 01150 HAVE_LOCK_CHECK (connection); 01151 01152 _dbus_verbose ("locking io_path_mutex\n"); 01153 _dbus_mutex_lock (connection->io_path_mutex); 01154 01155 _dbus_assert (connection->io_path_acquired); 01156 01157 _dbus_verbose ("start connection->io_path_acquired = %d\n", 01158 connection->io_path_acquired); 01159 01160 connection->io_path_acquired = FALSE; 01161 _dbus_condvar_wake_one (connection->io_path_cond); 01162 01163 _dbus_verbose ("unlocking io_path_mutex\n"); 01164 _dbus_mutex_unlock (connection->io_path_mutex); 01165 } 01166 01202 void 01203 _dbus_connection_do_iteration_unlocked (DBusConnection *connection, 01204 DBusPendingCall *pending, 01205 unsigned int flags, 01206 int timeout_milliseconds) 01207 { 01208 _dbus_verbose ("start\n"); 01209 01210 HAVE_LOCK_CHECK (connection); 01211 01212 if (connection->n_outgoing == 0) 01213 flags &= ~DBUS_ITERATION_DO_WRITING; 01214 01215 if (_dbus_connection_acquire_io_path (connection, 01216 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0)) 01217 { 01218 HAVE_LOCK_CHECK (connection); 01219 01220 if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending)) 01221 { 01222 _dbus_verbose ("pending call completed while acquiring I/O path"); 01223 } 01224 else if ( (pending != NULL) && 01225 _dbus_connection_peek_for_reply_unlocked (connection, 01226 _dbus_pending_call_get_reply_serial_unlocked (pending))) 01227 { 01228 _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)"); 01229 } 01230 else 01231 { 01232 _dbus_transport_do_iteration (connection->transport, 01233 flags, timeout_milliseconds); 01234 } 01235 01236 _dbus_connection_release_io_path (connection); 01237 } 01238 01239 HAVE_LOCK_CHECK (connection); 01240 01241 _dbus_verbose ("end\n"); 01242 } 01243 01253 DBusConnection* 01254 _dbus_connection_new_for_transport (DBusTransport *transport) 01255 { 01256 DBusConnection *connection; 01257 DBusWatchList *watch_list; 01258 DBusTimeoutList *timeout_list; 01259 DBusHashTable *pending_replies; 01260 DBusList *disconnect_link; 01261 DBusMessage *disconnect_message; 01262 DBusCounter *outgoing_counter; 01263 DBusObjectTree *objects; 01264 01265 watch_list = NULL; 01266 connection = NULL; 01267 pending_replies = NULL; 01268 timeout_list = NULL; 01269 disconnect_link = NULL; 01270 disconnect_message = NULL; 01271 outgoing_counter = NULL; 01272 objects = NULL; 01273 01274 watch_list = _dbus_watch_list_new (); 01275 if (watch_list == NULL) 01276 goto error; 01277 01278 timeout_list = _dbus_timeout_list_new (); 01279 if (timeout_list == NULL) 01280 goto error; 01281 01282 pending_replies = 01283 _dbus_hash_table_new (DBUS_HASH_INT, 01284 NULL, 01285 (DBusFreeFunction)free_pending_call_on_hash_removal); 01286 if (pending_replies == NULL) 01287 goto error; 01288 01289 connection = dbus_new0 (DBusConnection, 1); 01290 if (connection == NULL) 01291 goto error; 01292 01293 _dbus_mutex_new_at_location (&connection->mutex); 01294 if (connection->mutex == NULL) 01295 goto error; 01296 01297 _dbus_mutex_new_at_location (&connection->io_path_mutex); 01298 if (connection->io_path_mutex == NULL) 01299 goto error; 01300 01301 _dbus_mutex_new_at_location (&connection->dispatch_mutex); 01302 if (connection->dispatch_mutex == NULL) 01303 goto error; 01304 01305 _dbus_condvar_new_at_location (&connection->dispatch_cond); 01306 if (connection->dispatch_cond == NULL) 01307 goto error; 01308 01309 _dbus_condvar_new_at_location (&connection->io_path_cond); 01310 if (connection->io_path_cond == NULL) 01311 goto error; 01312 01313 _dbus_mutex_new_at_location (&connection->slot_mutex); 01314 if (connection->slot_mutex == NULL) 01315 goto error; 01316 01317 disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL, 01318 DBUS_INTERFACE_LOCAL, 01319 "Disconnected"); 01320 01321 if (disconnect_message == NULL) 01322 goto error; 01323 01324 disconnect_link = _dbus_list_alloc_link (disconnect_message); 01325 if (disconnect_link == NULL) 01326 goto error; 01327 01328 outgoing_counter = _dbus_counter_new (); 01329 if (outgoing_counter == NULL) 01330 goto error; 01331 01332 objects = _dbus_object_tree_new (connection); 01333 if (objects == NULL) 01334 goto error; 01335 01336 if (_dbus_modify_sigpipe) 01337 _dbus_disable_sigpipe (); 01338 01339 /* initialized to 0: use atomic op to avoid mixing atomic and non-atomic */ 01340 _dbus_atomic_inc (&connection->refcount); 01341 connection->transport = transport; 01342 connection->watches = watch_list; 01343 connection->timeouts = timeout_list; 01344 connection->pending_replies = pending_replies; 01345 connection->outgoing_counter = outgoing_counter; 01346 connection->filter_list = NULL; 01347 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */ 01348 connection->objects = objects; 01349 connection->exit_on_disconnect = FALSE; 01350 connection->shareable = FALSE; 01351 connection->route_peer_messages = FALSE; 01352 connection->disconnected_message_arrived = FALSE; 01353 connection->disconnected_message_processed = FALSE; 01354 01355 #ifndef DBUS_DISABLE_CHECKS 01356 connection->generation = _dbus_current_generation; 01357 #endif 01358 01359 _dbus_data_slot_list_init (&connection->slot_list); 01360 01361 connection->client_serial = 1; 01362 01363 connection->disconnect_message_link = disconnect_link; 01364 01365 CONNECTION_LOCK (connection); 01366 01367 if (!_dbus_transport_set_connection (transport, connection)) 01368 { 01369 CONNECTION_UNLOCK (connection); 01370 01371 goto error; 01372 } 01373 01374 _dbus_transport_ref (transport); 01375 01376 CONNECTION_UNLOCK (connection); 01377 01378 return connection; 01379 01380 error: 01381 if (disconnect_message != NULL) 01382 dbus_message_unref (disconnect_message); 01383 01384 if (disconnect_link != NULL) 01385 _dbus_list_free_link (disconnect_link); 01386 01387 if (connection != NULL) 01388 { 01389 _dbus_condvar_free_at_location (&connection->io_path_cond); 01390 _dbus_condvar_free_at_location (&connection->dispatch_cond); 01391 _dbus_mutex_free_at_location (&connection->mutex); 01392 _dbus_mutex_free_at_location (&connection->io_path_mutex); 01393 _dbus_mutex_free_at_location (&connection->dispatch_mutex); 01394 _dbus_mutex_free_at_location (&connection->slot_mutex); 01395 dbus_free (connection); 01396 } 01397 if (pending_replies) 01398 _dbus_hash_table_unref (pending_replies); 01399 01400 if (watch_list) 01401 _dbus_watch_list_free (watch_list); 01402 01403 if (timeout_list) 01404 _dbus_timeout_list_free (timeout_list); 01405 01406 if (outgoing_counter) 01407 _dbus_counter_unref (outgoing_counter); 01408 01409 if (objects) 01410 _dbus_object_tree_unref (objects); 01411 01412 return NULL; 01413 } 01414 01422 DBusConnection * 01423 _dbus_connection_ref_unlocked (DBusConnection *connection) 01424 { 01425 _dbus_assert (connection != NULL); 01426 _dbus_assert (connection->generation == _dbus_current_generation); 01427 01428 HAVE_LOCK_CHECK (connection); 01429 01430 _dbus_atomic_inc (&connection->refcount); 01431 01432 return connection; 01433 } 01434 01441 void 01442 _dbus_connection_unref_unlocked (DBusConnection *connection) 01443 { 01444 dbus_bool_t last_unref; 01445 01446 HAVE_LOCK_CHECK (connection); 01447 01448 _dbus_assert (connection != NULL); 01449 01450 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1); 01451 01452 if (last_unref) 01453 _dbus_connection_last_unref (connection); 01454 } 01455 01456 static dbus_uint32_t 01457 _dbus_connection_get_next_client_serial (DBusConnection *connection) 01458 { 01459 dbus_uint32_t serial; 01460 01461 serial = connection->client_serial++; 01462 01463 if (connection->client_serial == 0) 01464 connection->client_serial = 1; 01465 01466 return serial; 01467 } 01468 01482 dbus_bool_t 01483 _dbus_connection_handle_watch (DBusWatch *watch, 01484 unsigned int condition, 01485 void *data) 01486 { 01487 DBusConnection *connection; 01488 dbus_bool_t retval; 01489 DBusDispatchStatus status; 01490 01491 connection = data; 01492 01493 _dbus_verbose ("start\n"); 01494 01495 CONNECTION_LOCK (connection); 01496 01497 if (!_dbus_connection_acquire_io_path (connection, 1)) 01498 { 01499 /* another thread is handling the message */ 01500 CONNECTION_UNLOCK (connection); 01501 return TRUE; 01502 } 01503 01504 HAVE_LOCK_CHECK (connection); 01505 retval = _dbus_transport_handle_watch (connection->transport, 01506 watch, condition); 01507 01508 _dbus_connection_release_io_path (connection); 01509 01510 HAVE_LOCK_CHECK (connection); 01511 01512 _dbus_verbose ("middle\n"); 01513 01514 status = _dbus_connection_get_dispatch_status_unlocked (connection); 01515 01516 /* this calls out to user code */ 01517 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 01518 01519 _dbus_verbose ("end\n"); 01520 01521 return retval; 01522 } 01523 01524 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections); 01525 static DBusHashTable *shared_connections = NULL; 01526 static DBusList *shared_connections_no_guid = NULL; 01527 01528 static void 01529 close_connection_on_shutdown (DBusConnection *connection) 01530 { 01531 DBusMessage *message; 01532 01533 dbus_connection_ref (connection); 01534 _dbus_connection_close_possibly_shared (connection); 01535 01536 /* Churn through to the Disconnected message */ 01537 while ((message = dbus_connection_pop_message (connection))) 01538 { 01539 dbus_message_unref (message); 01540 } 01541 dbus_connection_unref (connection); 01542 } 01543 01544 static void 01545 shared_connections_shutdown (void *data) 01546 { 01547 int n_entries; 01548 01549 _DBUS_LOCK (shared_connections); 01550 01551 /* This is a little bit unpleasant... better ideas? */ 01552 while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0) 01553 { 01554 DBusConnection *connection; 01555 DBusHashIter iter; 01556 01557 _dbus_hash_iter_init (shared_connections, &iter); 01558 _dbus_hash_iter_next (&iter); 01559 01560 connection = _dbus_hash_iter_get_value (&iter); 01561 01562 _DBUS_UNLOCK (shared_connections); 01563 close_connection_on_shutdown (connection); 01564 _DBUS_LOCK (shared_connections); 01565 01566 /* The connection should now be dead and not in our hash ... */ 01567 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries); 01568 } 01569 01570 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0); 01571 01572 _dbus_hash_table_unref (shared_connections); 01573 shared_connections = NULL; 01574 01575 if (shared_connections_no_guid != NULL) 01576 { 01577 DBusConnection *connection; 01578 connection = _dbus_list_pop_first (&shared_connections_no_guid); 01579 while (connection != NULL) 01580 { 01581 _DBUS_UNLOCK (shared_connections); 01582 close_connection_on_shutdown (connection); 01583 _DBUS_LOCK (shared_connections); 01584 connection = _dbus_list_pop_first (&shared_connections_no_guid); 01585 } 01586 } 01587 01588 shared_connections_no_guid = NULL; 01589 01590 _DBUS_UNLOCK (shared_connections); 01591 } 01592 01593 static dbus_bool_t 01594 connection_lookup_shared (DBusAddressEntry *entry, 01595 DBusConnection **result) 01596 { 01597 _dbus_verbose ("checking for existing connection\n"); 01598 01599 *result = NULL; 01600 01601 _DBUS_LOCK (shared_connections); 01602 01603 if (shared_connections == NULL) 01604 { 01605 _dbus_verbose ("creating shared_connections hash table\n"); 01606 01607 shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING, 01608 dbus_free, 01609 NULL); 01610 if (shared_connections == NULL) 01611 { 01612 _DBUS_UNLOCK (shared_connections); 01613 return FALSE; 01614 } 01615 01616 if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL)) 01617 { 01618 _dbus_hash_table_unref (shared_connections); 01619 shared_connections = NULL; 01620 _DBUS_UNLOCK (shared_connections); 01621 return FALSE; 01622 } 01623 01624 _dbus_verbose (" successfully created shared_connections\n"); 01625 01626 _DBUS_UNLOCK (shared_connections); 01627 return TRUE; /* no point looking up in the hash we just made */ 01628 } 01629 else 01630 { 01631 const char *guid; 01632 01633 guid = dbus_address_entry_get_value (entry, "guid"); 01634 01635 if (guid != NULL) 01636 { 01637 DBusConnection *connection; 01638 01639 connection = _dbus_hash_table_lookup_string (shared_connections, 01640 guid); 01641 01642 if (connection) 01643 { 01644 /* The DBusConnection can't be finalized without taking 01645 * the shared_connections lock to remove it from the 01646 * hash. So it's safe to ref the connection here. 01647 * However, it may be disconnected if the Disconnected 01648 * message hasn't been processed yet, in which case we 01649 * want to pretend it isn't in the hash and avoid 01650 * returning it. 01651 * 01652 * The idea is to avoid ever returning a disconnected connection 01653 * from dbus_connection_open(). We could just synchronously 01654 * drop our shared ref to the connection on connection disconnect, 01655 * and then assert here that the connection is connected, but 01656 * that causes reentrancy headaches. 01657 */ 01658 CONNECTION_LOCK (connection); 01659 if (_dbus_connection_get_is_connected_unlocked (connection)) 01660 { 01661 _dbus_connection_ref_unlocked (connection); 01662 *result = connection; 01663 _dbus_verbose ("looked up existing connection to server guid %s\n", 01664 guid); 01665 } 01666 else 01667 { 01668 _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n", 01669 guid); 01670 } 01671 CONNECTION_UNLOCK (connection); 01672 } 01673 } 01674 01675 _DBUS_UNLOCK (shared_connections); 01676 return TRUE; 01677 } 01678 } 01679 01680 static dbus_bool_t 01681 connection_record_shared_unlocked (DBusConnection *connection, 01682 const char *guid) 01683 { 01684 char *guid_key; 01685 char *guid_in_connection; 01686 01687 HAVE_LOCK_CHECK (connection); 01688 _dbus_assert (connection->server_guid == NULL); 01689 _dbus_assert (connection->shareable); 01690 01691 /* get a hard ref on this connection, even if 01692 * we won't in fact store it in the hash, we still 01693 * need to hold a ref on it until it's disconnected. 01694 */ 01695 _dbus_connection_ref_unlocked (connection); 01696 01697 if (guid == NULL) 01698 { 01699 _DBUS_LOCK (shared_connections); 01700 01701 if (!_dbus_list_prepend (&shared_connections_no_guid, connection)) 01702 { 01703 _DBUS_UNLOCK (shared_connections); 01704 return FALSE; 01705 } 01706 01707 _DBUS_UNLOCK (shared_connections); 01708 return TRUE; /* don't store in the hash */ 01709 } 01710 01711 /* A separate copy of the key is required in the hash table, because 01712 * we don't have a lock on the connection when we are doing a hash 01713 * lookup. 01714 */ 01715 01716 guid_key = _dbus_strdup (guid); 01717 if (guid_key == NULL) 01718 return FALSE; 01719 01720 guid_in_connection = _dbus_strdup (guid); 01721 if (guid_in_connection == NULL) 01722 { 01723 dbus_free (guid_key); 01724 return FALSE; 01725 } 01726 01727 _DBUS_LOCK (shared_connections); 01728 _dbus_assert (shared_connections != NULL); 01729 01730 if (!_dbus_hash_table_insert_string (shared_connections, 01731 guid_key, connection)) 01732 { 01733 dbus_free (guid_key); 01734 dbus_free (guid_in_connection); 01735 _DBUS_UNLOCK (shared_connections); 01736 return FALSE; 01737 } 01738 01739 connection->server_guid = guid_in_connection; 01740 01741 _dbus_verbose ("stored connection to %s to be shared\n", 01742 connection->server_guid); 01743 01744 _DBUS_UNLOCK (shared_connections); 01745 01746 _dbus_assert (connection->server_guid != NULL); 01747 01748 return TRUE; 01749 } 01750 01751 static void 01752 connection_forget_shared_unlocked (DBusConnection *connection) 01753 { 01754 HAVE_LOCK_CHECK (connection); 01755 01756 if (!connection->shareable) 01757 return; 01758 01759 _DBUS_LOCK (shared_connections); 01760 01761 if (connection->server_guid != NULL) 01762 { 01763 _dbus_verbose ("dropping connection to %s out of the shared table\n", 01764 connection->server_guid); 01765 01766 if (!_dbus_hash_table_remove_string (shared_connections, 01767 connection->server_guid)) 01768 _dbus_assert_not_reached ("connection was not in the shared table"); 01769 01770 dbus_free (connection->server_guid); 01771 connection->server_guid = NULL; 01772 } 01773 else 01774 { 01775 _dbus_list_remove (&shared_connections_no_guid, connection); 01776 } 01777 01778 _DBUS_UNLOCK (shared_connections); 01779 01780 /* remove our reference held on all shareable connections */ 01781 _dbus_connection_unref_unlocked (connection); 01782 } 01783 01784 static DBusConnection* 01785 connection_try_from_address_entry (DBusAddressEntry *entry, 01786 DBusError *error) 01787 { 01788 DBusTransport *transport; 01789 DBusConnection *connection; 01790 01791 transport = _dbus_transport_open (entry, error); 01792 01793 if (transport == NULL) 01794 { 01795 _DBUS_ASSERT_ERROR_IS_SET (error); 01796 return NULL; 01797 } 01798 01799 connection = _dbus_connection_new_for_transport (transport); 01800 01801 _dbus_transport_unref (transport); 01802 01803 if (connection == NULL) 01804 { 01805 _DBUS_SET_OOM (error); 01806 return NULL; 01807 } 01808 01809 #ifndef DBUS_DISABLE_CHECKS 01810 _dbus_assert (!connection->have_connection_lock); 01811 #endif 01812 return connection; 01813 } 01814 01815 /* 01816 * If the shared parameter is true, then any existing connection will 01817 * be used (and if a new connection is created, it will be available 01818 * for use by others). If the shared parameter is false, a new 01819 * connection will always be created, and the new connection will 01820 * never be returned to other callers. 01821 * 01822 * @param address the address 01823 * @param shared whether the connection is shared or private 01824 * @param error error return 01825 * @returns the connection or #NULL on error 01826 */ 01827 static DBusConnection* 01828 _dbus_connection_open_internal (const char *address, 01829 dbus_bool_t shared, 01830 DBusError *error) 01831 { 01832 DBusConnection *connection; 01833 DBusAddressEntry **entries; 01834 DBusError tmp_error = DBUS_ERROR_INIT; 01835 DBusError first_error = DBUS_ERROR_INIT; 01836 int len, i; 01837 01838 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01839 01840 _dbus_verbose ("opening %s connection to: %s\n", 01841 shared ? "shared" : "private", address); 01842 01843 if (!dbus_parse_address (address, &entries, &len, error)) 01844 return NULL; 01845 01846 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01847 01848 connection = NULL; 01849 01850 for (i = 0; i < len; i++) 01851 { 01852 if (shared) 01853 { 01854 if (!connection_lookup_shared (entries[i], &connection)) 01855 _DBUS_SET_OOM (&tmp_error); 01856 } 01857 01858 if (connection == NULL) 01859 { 01860 connection = connection_try_from_address_entry (entries[i], 01861 &tmp_error); 01862 01863 if (connection != NULL && shared) 01864 { 01865 const char *guid; 01866 01867 connection->shareable = TRUE; 01868 01869 /* guid may be NULL */ 01870 guid = dbus_address_entry_get_value (entries[i], "guid"); 01871 01872 CONNECTION_LOCK (connection); 01873 01874 if (!connection_record_shared_unlocked (connection, guid)) 01875 { 01876 _DBUS_SET_OOM (&tmp_error); 01877 _dbus_connection_close_possibly_shared_and_unlock (connection); 01878 dbus_connection_unref (connection); 01879 connection = NULL; 01880 } 01881 else 01882 CONNECTION_UNLOCK (connection); 01883 } 01884 } 01885 01886 if (connection) 01887 break; 01888 01889 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 01890 01891 if (i == 0) 01892 dbus_move_error (&tmp_error, &first_error); 01893 else 01894 dbus_error_free (&tmp_error); 01895 } 01896 01897 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01898 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 01899 01900 if (connection == NULL) 01901 { 01902 _DBUS_ASSERT_ERROR_IS_SET (&first_error); 01903 dbus_move_error (&first_error, error); 01904 } 01905 else 01906 dbus_error_free (&first_error); 01907 01908 dbus_address_entries_free (entries); 01909 return connection; 01910 } 01911 01920 void 01921 _dbus_connection_close_possibly_shared (DBusConnection *connection) 01922 { 01923 _dbus_assert (connection != NULL); 01924 _dbus_assert (connection->generation == _dbus_current_generation); 01925 01926 CONNECTION_LOCK (connection); 01927 _dbus_connection_close_possibly_shared_and_unlock (connection); 01928 } 01929 01930 static DBusPreallocatedSend* 01931 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection) 01932 { 01933 DBusPreallocatedSend *preallocated; 01934 01935 HAVE_LOCK_CHECK (connection); 01936 01937 _dbus_assert (connection != NULL); 01938 01939 preallocated = dbus_new (DBusPreallocatedSend, 1); 01940 if (preallocated == NULL) 01941 return NULL; 01942 01943 preallocated->queue_link = _dbus_list_alloc_link (NULL); 01944 if (preallocated->queue_link == NULL) 01945 goto failed_0; 01946 01947 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter); 01948 if (preallocated->counter_link == NULL) 01949 goto failed_1; 01950 01951 _dbus_counter_ref (preallocated->counter_link->data); 01952 01953 preallocated->connection = connection; 01954 01955 return preallocated; 01956 01957 failed_1: 01958 _dbus_list_free_link (preallocated->queue_link); 01959 failed_0: 01960 dbus_free (preallocated); 01961 01962 return NULL; 01963 } 01964 01965 /* Called with lock held, does not update dispatch status */ 01966 static void 01967 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection, 01968 DBusPreallocatedSend *preallocated, 01969 DBusMessage *message, 01970 dbus_uint32_t *client_serial) 01971 { 01972 dbus_uint32_t serial; 01973 01974 preallocated->queue_link->data = message; 01975 _dbus_list_prepend_link (&connection->outgoing_messages, 01976 preallocated->queue_link); 01977 01978 /* It's OK that we'll never call the notify function, because for the 01979 * outgoing limit, there isn't one */ 01980 _dbus_message_add_counter_link (message, 01981 preallocated->counter_link); 01982 01983 dbus_free (preallocated); 01984 preallocated = NULL; 01985 01986 dbus_message_ref (message); 01987 01988 connection->n_outgoing += 1; 01989 01990 _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n", 01991 message, 01992 dbus_message_type_to_string (dbus_message_get_type (message)), 01993 dbus_message_get_path (message) ? 01994 dbus_message_get_path (message) : 01995 "no path", 01996 dbus_message_get_interface (message) ? 01997 dbus_message_get_interface (message) : 01998 "no interface", 01999 dbus_message_get_member (message) ? 02000 dbus_message_get_member (message) : 02001 "no member", 02002 dbus_message_get_signature (message), 02003 dbus_message_get_destination (message) ? 02004 dbus_message_get_destination (message) : 02005 "null", 02006 connection, 02007 connection->n_outgoing); 02008 02009 if (dbus_message_get_serial (message) == 0) 02010 { 02011 serial = _dbus_connection_get_next_client_serial (connection); 02012 dbus_message_set_serial (message, serial); 02013 if (client_serial) 02014 *client_serial = serial; 02015 } 02016 else 02017 { 02018 if (client_serial) 02019 *client_serial = dbus_message_get_serial (message); 02020 } 02021 02022 _dbus_verbose ("Message %p serial is %u\n", 02023 message, dbus_message_get_serial (message)); 02024 02025 dbus_message_lock (message); 02026 02027 /* Now we need to run an iteration to hopefully just write the messages 02028 * out immediately, and otherwise get them queued up 02029 */ 02030 _dbus_connection_do_iteration_unlocked (connection, 02031 NULL, 02032 DBUS_ITERATION_DO_WRITING, 02033 -1); 02034 02035 /* If stuff is still queued up, be sure we wake up the main loop */ 02036 if (connection->n_outgoing > 0) 02037 _dbus_connection_wakeup_mainloop (connection); 02038 } 02039 02040 static void 02041 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection, 02042 DBusPreallocatedSend *preallocated, 02043 DBusMessage *message, 02044 dbus_uint32_t *client_serial) 02045 { 02046 DBusDispatchStatus status; 02047 02048 HAVE_LOCK_CHECK (connection); 02049 02050 _dbus_connection_send_preallocated_unlocked_no_update (connection, 02051 preallocated, 02052 message, client_serial); 02053 02054 _dbus_verbose ("middle\n"); 02055 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02056 02057 /* this calls out to user code */ 02058 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02059 } 02060 02070 dbus_bool_t 02071 _dbus_connection_send_and_unlock (DBusConnection *connection, 02072 DBusMessage *message, 02073 dbus_uint32_t *client_serial) 02074 { 02075 DBusPreallocatedSend *preallocated; 02076 02077 _dbus_assert (connection != NULL); 02078 _dbus_assert (message != NULL); 02079 02080 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 02081 if (preallocated == NULL) 02082 { 02083 CONNECTION_UNLOCK (connection); 02084 return FALSE; 02085 } 02086 02087 _dbus_connection_send_preallocated_and_unlock (connection, 02088 preallocated, 02089 message, 02090 client_serial); 02091 return TRUE; 02092 } 02093 02118 void 02119 _dbus_connection_close_if_only_one_ref (DBusConnection *connection) 02120 { 02121 dbus_int32_t refcount; 02122 02123 CONNECTION_LOCK (connection); 02124 02125 refcount = _dbus_atomic_get (&connection->refcount); 02126 /* The caller should have at least one ref */ 02127 _dbus_assert (refcount >= 1); 02128 02129 if (refcount == 1) 02130 _dbus_connection_close_possibly_shared_and_unlock (connection); 02131 else 02132 CONNECTION_UNLOCK (connection); 02133 } 02134 02135 02145 static void 02146 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds) 02147 { 02148 if (timeout_milliseconds == -1) 02149 _dbus_sleep_milliseconds (1000); 02150 else if (timeout_milliseconds < 100) 02151 ; /* just busy loop */ 02152 else if (timeout_milliseconds <= 1000) 02153 _dbus_sleep_milliseconds (timeout_milliseconds / 3); 02154 else 02155 _dbus_sleep_milliseconds (1000); 02156 } 02157 02158 static DBusMessage * 02159 generate_local_error_message (dbus_uint32_t serial, 02160 char *error_name, 02161 char *error_msg) 02162 { 02163 DBusMessage *message; 02164 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR); 02165 if (!message) 02166 goto out; 02167 02168 if (!dbus_message_set_error_name (message, error_name)) 02169 { 02170 dbus_message_unref (message); 02171 message = NULL; 02172 goto out; 02173 } 02174 02175 dbus_message_set_no_reply (message, TRUE); 02176 02177 if (!dbus_message_set_reply_serial (message, 02178 serial)) 02179 { 02180 dbus_message_unref (message); 02181 message = NULL; 02182 goto out; 02183 } 02184 02185 if (error_msg != NULL) 02186 { 02187 DBusMessageIter iter; 02188 02189 dbus_message_iter_init_append (message, &iter); 02190 if (!dbus_message_iter_append_basic (&iter, 02191 DBUS_TYPE_STRING, 02192 &error_msg)) 02193 { 02194 dbus_message_unref (message); 02195 message = NULL; 02196 goto out; 02197 } 02198 } 02199 02200 out: 02201 return message; 02202 } 02203 02204 /* 02205 * Peek the incoming queue to see if we got reply for a specific serial 02206 */ 02207 static dbus_bool_t 02208 _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection, 02209 dbus_uint32_t client_serial) 02210 { 02211 DBusList *link; 02212 HAVE_LOCK_CHECK (connection); 02213 02214 link = _dbus_list_get_first_link (&connection->incoming_messages); 02215 02216 while (link != NULL) 02217 { 02218 DBusMessage *reply = link->data; 02219 02220 if (dbus_message_get_reply_serial (reply) == client_serial) 02221 { 02222 _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial); 02223 return TRUE; 02224 } 02225 link = _dbus_list_get_next_link (&connection->incoming_messages, link); 02226 } 02227 02228 return FALSE; 02229 } 02230 02231 /* This is slightly strange since we can pop a message here without 02232 * the dispatch lock. 02233 */ 02234 static DBusMessage* 02235 check_for_reply_unlocked (DBusConnection *connection, 02236 dbus_uint32_t client_serial) 02237 { 02238 DBusList *link; 02239 02240 HAVE_LOCK_CHECK (connection); 02241 02242 link = _dbus_list_get_first_link (&connection->incoming_messages); 02243 02244 while (link != NULL) 02245 { 02246 DBusMessage *reply = link->data; 02247 02248 if (dbus_message_get_reply_serial (reply) == client_serial) 02249 { 02250 _dbus_list_remove_link (&connection->incoming_messages, link); 02251 connection->n_incoming -= 1; 02252 return reply; 02253 } 02254 link = _dbus_list_get_next_link (&connection->incoming_messages, link); 02255 } 02256 02257 return NULL; 02258 } 02259 02260 static void 02261 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection) 02262 { 02263 /* We can't iterate over the hash in the normal way since we'll be 02264 * dropping the lock for each item. So we restart the 02265 * iter each time as we drain the hash table. 02266 */ 02267 02268 while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0) 02269 { 02270 DBusPendingCall *pending; 02271 DBusHashIter iter; 02272 02273 _dbus_hash_iter_init (connection->pending_replies, &iter); 02274 _dbus_hash_iter_next (&iter); 02275 02276 pending = _dbus_hash_iter_get_value (&iter); 02277 _dbus_pending_call_ref_unlocked (pending); 02278 02279 _dbus_pending_call_queue_timeout_error_unlocked (pending, 02280 connection); 02281 02282 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 02283 _dbus_connection_remove_timeout_unlocked (connection, 02284 _dbus_pending_call_get_timeout_unlocked (pending)); 02285 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 02286 _dbus_hash_iter_remove_entry (&iter); 02287 02288 _dbus_pending_call_unref_and_unlock (pending); 02289 CONNECTION_LOCK (connection); 02290 } 02291 HAVE_LOCK_CHECK (connection); 02292 } 02293 02294 static void 02295 complete_pending_call_and_unlock (DBusConnection *connection, 02296 DBusPendingCall *pending, 02297 DBusMessage *message) 02298 { 02299 _dbus_pending_call_set_reply_unlocked (pending, message); 02300 _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */ 02301 _dbus_connection_detach_pending_call_and_unlock (connection, pending); 02302 02303 /* Must be called unlocked since it invokes app callback */ 02304 _dbus_pending_call_complete (pending); 02305 dbus_pending_call_unref (pending); 02306 } 02307 02308 static dbus_bool_t 02309 check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection, 02310 DBusPendingCall *pending) 02311 { 02312 DBusMessage *reply; 02313 DBusDispatchStatus status; 02314 02315 reply = check_for_reply_unlocked (connection, 02316 _dbus_pending_call_get_reply_serial_unlocked (pending)); 02317 if (reply != NULL) 02318 { 02319 _dbus_verbose ("checked for reply\n"); 02320 02321 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n"); 02322 02323 complete_pending_call_and_unlock (connection, pending, reply); 02324 dbus_message_unref (reply); 02325 02326 CONNECTION_LOCK (connection); 02327 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02328 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02329 dbus_pending_call_unref (pending); 02330 02331 return TRUE; 02332 } 02333 02334 return FALSE; 02335 } 02336 02351 void 02352 _dbus_connection_block_pending_call (DBusPendingCall *pending) 02353 { 02354 long start_tv_sec, start_tv_usec; 02355 long tv_sec, tv_usec; 02356 DBusDispatchStatus status; 02357 DBusConnection *connection; 02358 dbus_uint32_t client_serial; 02359 DBusTimeout *timeout; 02360 int timeout_milliseconds, elapsed_milliseconds; 02361 02362 _dbus_assert (pending != NULL); 02363 02364 if (dbus_pending_call_get_completed (pending)) 02365 return; 02366 02367 dbus_pending_call_ref (pending); /* necessary because the call could be canceled */ 02368 02369 connection = _dbus_pending_call_get_connection_and_lock (pending); 02370 02371 /* Flush message queue - note, can affect dispatch status */ 02372 _dbus_connection_flush_unlocked (connection); 02373 02374 client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending); 02375 02376 /* note that timeout_milliseconds is limited to a smallish value 02377 * in _dbus_pending_call_new() so overflows aren't possible 02378 * below 02379 */ 02380 timeout = _dbus_pending_call_get_timeout_unlocked (pending); 02381 _dbus_get_current_time (&start_tv_sec, &start_tv_usec); 02382 if (timeout) 02383 { 02384 timeout_milliseconds = dbus_timeout_get_interval (timeout); 02385 02386 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n", 02387 timeout_milliseconds, 02388 client_serial, 02389 start_tv_sec, start_tv_usec); 02390 } 02391 else 02392 { 02393 timeout_milliseconds = -1; 02394 02395 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial); 02396 } 02397 02398 /* check to see if we already got the data off the socket */ 02399 /* from another blocked pending call */ 02400 if (check_for_reply_and_update_dispatch_unlocked (connection, pending)) 02401 return; 02402 02403 /* Now we wait... */ 02404 /* always block at least once as we know we don't have the reply yet */ 02405 _dbus_connection_do_iteration_unlocked (connection, 02406 pending, 02407 DBUS_ITERATION_DO_READING | 02408 DBUS_ITERATION_BLOCK, 02409 timeout_milliseconds); 02410 02411 recheck_status: 02412 02413 _dbus_verbose ("top of recheck\n"); 02414 02415 HAVE_LOCK_CHECK (connection); 02416 02417 /* queue messages and get status */ 02418 02419 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02420 02421 /* the get_completed() is in case a dispatch() while we were blocking 02422 * got the reply instead of us. 02423 */ 02424 if (_dbus_pending_call_get_completed_unlocked (pending)) 02425 { 02426 _dbus_verbose ("Pending call completed by dispatch\n"); 02427 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02428 dbus_pending_call_unref (pending); 02429 return; 02430 } 02431 02432 if (status == DBUS_DISPATCH_DATA_REMAINS) 02433 { 02434 if (check_for_reply_and_update_dispatch_unlocked (connection, pending)) 02435 return; 02436 } 02437 02438 _dbus_get_current_time (&tv_sec, &tv_usec); 02439 elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 + 02440 (tv_usec - start_tv_usec) / 1000; 02441 02442 if (!_dbus_connection_get_is_connected_unlocked (connection)) 02443 { 02444 DBusMessage *error_msg; 02445 02446 error_msg = generate_local_error_message (client_serial, 02447 DBUS_ERROR_DISCONNECTED, 02448 "Connection was disconnected before a reply was received"); 02449 02450 /* on OOM error_msg is set to NULL */ 02451 complete_pending_call_and_unlock (connection, pending, error_msg); 02452 dbus_pending_call_unref (pending); 02453 return; 02454 } 02455 else if (connection->disconnect_message_link == NULL) 02456 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n"); 02457 else if (timeout == NULL) 02458 { 02459 if (status == DBUS_DISPATCH_NEED_MEMORY) 02460 { 02461 /* Try sleeping a bit, as we aren't sure we need to block for reading, 02462 * we may already have a reply in the buffer and just can't process 02463 * it. 02464 */ 02465 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n"); 02466 02467 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds); 02468 } 02469 else 02470 { 02471 /* block again, we don't have the reply buffered yet. */ 02472 _dbus_connection_do_iteration_unlocked (connection, 02473 pending, 02474 DBUS_ITERATION_DO_READING | 02475 DBUS_ITERATION_BLOCK, 02476 timeout_milliseconds - elapsed_milliseconds); 02477 } 02478 02479 goto recheck_status; 02480 } 02481 else if (tv_sec < start_tv_sec) 02482 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n"); 02483 else if (elapsed_milliseconds < timeout_milliseconds) 02484 { 02485 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds); 02486 02487 if (status == DBUS_DISPATCH_NEED_MEMORY) 02488 { 02489 /* Try sleeping a bit, as we aren't sure we need to block for reading, 02490 * we may already have a reply in the buffer and just can't process 02491 * it. 02492 */ 02493 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n"); 02494 02495 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds); 02496 } 02497 else 02498 { 02499 /* block again, we don't have the reply buffered yet. */ 02500 _dbus_connection_do_iteration_unlocked (connection, 02501 NULL, 02502 DBUS_ITERATION_DO_READING | 02503 DBUS_ITERATION_BLOCK, 02504 timeout_milliseconds - elapsed_milliseconds); 02505 } 02506 02507 goto recheck_status; 02508 } 02509 02510 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n", 02511 elapsed_milliseconds); 02512 02513 _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending)); 02514 02515 /* unlock and call user code */ 02516 complete_pending_call_and_unlock (connection, pending, NULL); 02517 02518 /* update user code on dispatch status */ 02519 CONNECTION_LOCK (connection); 02520 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02521 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02522 dbus_pending_call_unref (pending); 02523 } 02524 02561 DBusConnection* 02562 dbus_connection_open (const char *address, 02563 DBusError *error) 02564 { 02565 DBusConnection *connection; 02566 02567 _dbus_return_val_if_fail (address != NULL, NULL); 02568 _dbus_return_val_if_error_is_set (error, NULL); 02569 02570 connection = _dbus_connection_open_internal (address, 02571 TRUE, 02572 error); 02573 02574 return connection; 02575 } 02576 02604 DBusConnection* 02605 dbus_connection_open_private (const char *address, 02606 DBusError *error) 02607 { 02608 DBusConnection *connection; 02609 02610 _dbus_return_val_if_fail (address != NULL, NULL); 02611 _dbus_return_val_if_error_is_set (error, NULL); 02612 02613 connection = _dbus_connection_open_internal (address, 02614 FALSE, 02615 error); 02616 02617 return connection; 02618 } 02619 02626 DBusConnection * 02627 dbus_connection_ref (DBusConnection *connection) 02628 { 02629 _dbus_return_val_if_fail (connection != NULL, NULL); 02630 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL); 02631 02632 _dbus_atomic_inc (&connection->refcount); 02633 02634 return connection; 02635 } 02636 02637 static void 02638 free_outgoing_message (void *element, 02639 void *data) 02640 { 02641 DBusMessage *message = element; 02642 DBusConnection *connection = data; 02643 02644 _dbus_message_remove_counter (message, connection->outgoing_counter); 02645 dbus_message_unref (message); 02646 } 02647 02648 /* This is run without the mutex held, but after the last reference 02649 * to the connection has been dropped we should have no thread-related 02650 * problems 02651 */ 02652 static void 02653 _dbus_connection_last_unref (DBusConnection *connection) 02654 { 02655 DBusList *link; 02656 02657 _dbus_verbose ("Finalizing connection %p\n", connection); 02658 02659 _dbus_assert (_dbus_atomic_get (&connection->refcount) == 0); 02660 02661 /* You have to disconnect the connection before unref:ing it. Otherwise 02662 * you won't get the disconnected message. 02663 */ 02664 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport)); 02665 _dbus_assert (connection->server_guid == NULL); 02666 02667 /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */ 02668 _dbus_object_tree_free_all_unlocked (connection->objects); 02669 02670 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL); 02671 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL); 02672 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL); 02673 02674 _dbus_watch_list_free (connection->watches); 02675 connection->watches = NULL; 02676 02677 _dbus_timeout_list_free (connection->timeouts); 02678 connection->timeouts = NULL; 02679 02680 _dbus_data_slot_list_free (&connection->slot_list); 02681 02682 link = _dbus_list_get_first_link (&connection->filter_list); 02683 while (link != NULL) 02684 { 02685 DBusMessageFilter *filter = link->data; 02686 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link); 02687 02688 filter->function = NULL; 02689 _dbus_message_filter_unref (filter); /* calls app callback */ 02690 link->data = NULL; 02691 02692 link = next; 02693 } 02694 _dbus_list_clear (&connection->filter_list); 02695 02696 /* ---- Done with stuff that invokes application callbacks */ 02697 02698 _dbus_object_tree_unref (connection->objects); 02699 02700 _dbus_hash_table_unref (connection->pending_replies); 02701 connection->pending_replies = NULL; 02702 02703 _dbus_list_clear (&connection->filter_list); 02704 02705 _dbus_list_foreach (&connection->outgoing_messages, 02706 free_outgoing_message, 02707 connection); 02708 _dbus_list_clear (&connection->outgoing_messages); 02709 02710 _dbus_list_foreach (&connection->incoming_messages, 02711 (DBusForeachFunction) dbus_message_unref, 02712 NULL); 02713 _dbus_list_clear (&connection->incoming_messages); 02714 02715 _dbus_counter_unref (connection->outgoing_counter); 02716 02717 _dbus_transport_unref (connection->transport); 02718 02719 if (connection->disconnect_message_link) 02720 { 02721 DBusMessage *message = connection->disconnect_message_link->data; 02722 dbus_message_unref (message); 02723 _dbus_list_free_link (connection->disconnect_message_link); 02724 } 02725 02726 _dbus_condvar_free_at_location (&connection->dispatch_cond); 02727 _dbus_condvar_free_at_location (&connection->io_path_cond); 02728 02729 _dbus_mutex_free_at_location (&connection->io_path_mutex); 02730 _dbus_mutex_free_at_location (&connection->dispatch_mutex); 02731 02732 _dbus_mutex_free_at_location (&connection->slot_mutex); 02733 02734 _dbus_mutex_free_at_location (&connection->mutex); 02735 02736 dbus_free (connection); 02737 } 02738 02758 void 02759 dbus_connection_unref (DBusConnection *connection) 02760 { 02761 dbus_bool_t last_unref; 02762 02763 _dbus_return_if_fail (connection != NULL); 02764 _dbus_return_if_fail (connection->generation == _dbus_current_generation); 02765 02766 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1); 02767 02768 if (last_unref) 02769 { 02770 #ifndef DBUS_DISABLE_CHECKS 02771 if (_dbus_transport_get_is_connected (connection->transport)) 02772 { 02773 _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", 02774 connection->shareable ? 02775 "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" : 02776 "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n"); 02777 return; 02778 } 02779 #endif 02780 _dbus_connection_last_unref (connection); 02781 } 02782 } 02783 02784 /* 02785 * Note that the transport can disconnect itself (other end drops us) 02786 * and in that case this function never runs. So this function must 02787 * not do anything more than disconnect the transport and update the 02788 * dispatch status. 02789 * 02790 * If the transport self-disconnects, then we assume someone will 02791 * dispatch the connection to cause the dispatch status update. 02792 */ 02793 static void 02794 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection) 02795 { 02796 DBusDispatchStatus status; 02797 02798 HAVE_LOCK_CHECK (connection); 02799 02800 _dbus_verbose ("Disconnecting %p\n", connection); 02801 02802 /* We need to ref because update_dispatch_status_and_unlock will unref 02803 * the connection if it was shared and libdbus was the only remaining 02804 * refcount holder. 02805 */ 02806 _dbus_connection_ref_unlocked (connection); 02807 02808 _dbus_transport_disconnect (connection->transport); 02809 02810 /* This has the side effect of queuing the disconnect message link 02811 * (unless we don't have enough memory, possibly, so don't assert it). 02812 * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open 02813 * should never again return the newly-disconnected connection. 02814 * 02815 * However, we only unref the shared connection and exit_on_disconnect when 02816 * the disconnect message reaches the head of the message queue, 02817 * NOT when it's first queued. 02818 */ 02819 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02820 02821 /* This calls out to user code */ 02822 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02823 02824 /* Could also call out to user code */ 02825 dbus_connection_unref (connection); 02826 } 02827 02870 void 02871 dbus_connection_close (DBusConnection *connection) 02872 { 02873 _dbus_return_if_fail (connection != NULL); 02874 _dbus_return_if_fail (connection->generation == _dbus_current_generation); 02875 02876 CONNECTION_LOCK (connection); 02877 02878 #ifndef DBUS_DISABLE_CHECKS 02879 if (connection->shareable) 02880 { 02881 CONNECTION_UNLOCK (connection); 02882 02883 _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n"); 02884 return; 02885 } 02886 #endif 02887 02888 _dbus_connection_close_possibly_shared_and_unlock (connection); 02889 } 02890 02891 static dbus_bool_t 02892 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection) 02893 { 02894 HAVE_LOCK_CHECK (connection); 02895 return _dbus_transport_get_is_connected (connection->transport); 02896 } 02897 02911 dbus_bool_t 02912 dbus_connection_get_is_connected (DBusConnection *connection) 02913 { 02914 dbus_bool_t res; 02915 02916 _dbus_return_val_if_fail (connection != NULL, FALSE); 02917 02918 CONNECTION_LOCK (connection); 02919 res = _dbus_connection_get_is_connected_unlocked (connection); 02920 CONNECTION_UNLOCK (connection); 02921 02922 return res; 02923 } 02924 02933 dbus_bool_t 02934 dbus_connection_get_is_authenticated (DBusConnection *connection) 02935 { 02936 dbus_bool_t res; 02937 02938 _dbus_return_val_if_fail (connection != NULL, FALSE); 02939 02940 CONNECTION_LOCK (connection); 02941 res = _dbus_transport_get_is_authenticated (connection->transport); 02942 CONNECTION_UNLOCK (connection); 02943 02944 return res; 02945 } 02946 02967 dbus_bool_t 02968 dbus_connection_get_is_anonymous (DBusConnection *connection) 02969 { 02970 dbus_bool_t res; 02971 02972 _dbus_return_val_if_fail (connection != NULL, FALSE); 02973 02974 CONNECTION_LOCK (connection); 02975 res = _dbus_transport_get_is_anonymous (connection->transport); 02976 CONNECTION_UNLOCK (connection); 02977 02978 return res; 02979 } 02980 03012 char* 03013 dbus_connection_get_server_id (DBusConnection *connection) 03014 { 03015 char *id; 03016 03017 _dbus_return_val_if_fail (connection != NULL, NULL); 03018 03019 CONNECTION_LOCK (connection); 03020 id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport)); 03021 CONNECTION_UNLOCK (connection); 03022 03023 return id; 03024 } 03025 03043 dbus_bool_t 03044 dbus_connection_can_send_type(DBusConnection *connection, 03045 int type) 03046 { 03047 _dbus_return_val_if_fail (connection != NULL, FALSE); 03048 03049 if (!dbus_type_is_valid (type)) 03050 return FALSE; 03051 03052 if (type != DBUS_TYPE_UNIX_FD) 03053 return TRUE; 03054 03055 #ifdef HAVE_UNIX_FD_PASSING 03056 { 03057 dbus_bool_t b; 03058 03059 CONNECTION_LOCK(connection); 03060 b = _dbus_transport_can_pass_unix_fd(connection->transport); 03061 CONNECTION_UNLOCK(connection); 03062 03063 return b; 03064 } 03065 #endif 03066 03067 return FALSE; 03068 } 03069 03083 void 03084 dbus_connection_set_exit_on_disconnect (DBusConnection *connection, 03085 dbus_bool_t exit_on_disconnect) 03086 { 03087 _dbus_return_if_fail (connection != NULL); 03088 03089 CONNECTION_LOCK (connection); 03090 connection->exit_on_disconnect = exit_on_disconnect != FALSE; 03091 CONNECTION_UNLOCK (connection); 03092 } 03093 03103 DBusPreallocatedSend* 03104 dbus_connection_preallocate_send (DBusConnection *connection) 03105 { 03106 DBusPreallocatedSend *preallocated; 03107 03108 _dbus_return_val_if_fail (connection != NULL, NULL); 03109 03110 CONNECTION_LOCK (connection); 03111 03112 preallocated = 03113 _dbus_connection_preallocate_send_unlocked (connection); 03114 03115 CONNECTION_UNLOCK (connection); 03116 03117 return preallocated; 03118 } 03119 03129 void 03130 dbus_connection_free_preallocated_send (DBusConnection *connection, 03131 DBusPreallocatedSend *preallocated) 03132 { 03133 _dbus_return_if_fail (connection != NULL); 03134 _dbus_return_if_fail (preallocated != NULL); 03135 _dbus_return_if_fail (connection == preallocated->connection); 03136 03137 _dbus_list_free_link (preallocated->queue_link); 03138 _dbus_counter_unref (preallocated->counter_link->data); 03139 _dbus_list_free_link (preallocated->counter_link); 03140 dbus_free (preallocated); 03141 } 03142 03155 void 03156 dbus_connection_send_preallocated (DBusConnection *connection, 03157 DBusPreallocatedSend *preallocated, 03158 DBusMessage *message, 03159 dbus_uint32_t *client_serial) 03160 { 03161 _dbus_return_if_fail (connection != NULL); 03162 _dbus_return_if_fail (preallocated != NULL); 03163 _dbus_return_if_fail (message != NULL); 03164 _dbus_return_if_fail (preallocated->connection == connection); 03165 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL || 03166 dbus_message_get_member (message) != NULL); 03167 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL || 03168 (dbus_message_get_interface (message) != NULL && 03169 dbus_message_get_member (message) != NULL)); 03170 03171 CONNECTION_LOCK (connection); 03172 03173 #ifdef HAVE_UNIX_FD_PASSING 03174 03175 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03176 message->n_unix_fds > 0) 03177 { 03178 /* Refuse to send fds on a connection that cannot handle 03179 them. Unfortunately we cannot return a proper error here, so 03180 the best we can is just return. */ 03181 CONNECTION_UNLOCK (connection); 03182 return; 03183 } 03184 03185 #endif 03186 03187 _dbus_connection_send_preallocated_and_unlock (connection, 03188 preallocated, 03189 message, client_serial); 03190 } 03191 03192 static dbus_bool_t 03193 _dbus_connection_send_unlocked_no_update (DBusConnection *connection, 03194 DBusMessage *message, 03195 dbus_uint32_t *client_serial) 03196 { 03197 DBusPreallocatedSend *preallocated; 03198 03199 _dbus_assert (connection != NULL); 03200 _dbus_assert (message != NULL); 03201 03202 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 03203 if (preallocated == NULL) 03204 return FALSE; 03205 03206 _dbus_connection_send_preallocated_unlocked_no_update (connection, 03207 preallocated, 03208 message, 03209 client_serial); 03210 return TRUE; 03211 } 03212 03240 dbus_bool_t 03241 dbus_connection_send (DBusConnection *connection, 03242 DBusMessage *message, 03243 dbus_uint32_t *serial) 03244 { 03245 _dbus_return_val_if_fail (connection != NULL, FALSE); 03246 _dbus_return_val_if_fail (message != NULL, FALSE); 03247 03248 CONNECTION_LOCK (connection); 03249 03250 #ifdef HAVE_UNIX_FD_PASSING 03251 03252 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03253 message->n_unix_fds > 0) 03254 { 03255 /* Refuse to send fds on a connection that cannot handle 03256 them. Unfortunately we cannot return a proper error here, so 03257 the best we can is just return. */ 03258 CONNECTION_UNLOCK (connection); 03259 return FALSE; 03260 } 03261 03262 #endif 03263 03264 return _dbus_connection_send_and_unlock (connection, 03265 message, 03266 serial); 03267 } 03268 03269 static dbus_bool_t 03270 reply_handler_timeout (void *data) 03271 { 03272 DBusConnection *connection; 03273 DBusDispatchStatus status; 03274 DBusPendingCall *pending = data; 03275 03276 connection = _dbus_pending_call_get_connection_and_lock (pending); 03277 _dbus_connection_ref_unlocked (connection); 03278 03279 _dbus_pending_call_queue_timeout_error_unlocked (pending, 03280 connection); 03281 _dbus_connection_remove_timeout_unlocked (connection, 03282 _dbus_pending_call_get_timeout_unlocked (pending)); 03283 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 03284 03285 _dbus_verbose ("middle\n"); 03286 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03287 03288 /* Unlocks, and calls out to user code */ 03289 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03290 dbus_connection_unref (connection); 03291 03292 return TRUE; 03293 } 03294 03337 dbus_bool_t 03338 dbus_connection_send_with_reply (DBusConnection *connection, 03339 DBusMessage *message, 03340 DBusPendingCall **pending_return, 03341 int timeout_milliseconds) 03342 { 03343 DBusPendingCall *pending; 03344 dbus_int32_t serial = -1; 03345 DBusDispatchStatus status; 03346 03347 _dbus_return_val_if_fail (connection != NULL, FALSE); 03348 _dbus_return_val_if_fail (message != NULL, FALSE); 03349 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03350 03351 if (pending_return) 03352 *pending_return = NULL; 03353 03354 CONNECTION_LOCK (connection); 03355 03356 #ifdef HAVE_UNIX_FD_PASSING 03357 03358 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03359 message->n_unix_fds > 0) 03360 { 03361 /* Refuse to send fds on a connection that cannot handle 03362 them. Unfortunately we cannot return a proper error here, so 03363 the best we can do is return TRUE but leave *pending_return 03364 as NULL. */ 03365 CONNECTION_UNLOCK (connection); 03366 return TRUE; 03367 } 03368 03369 #endif 03370 03371 if (!_dbus_connection_get_is_connected_unlocked (connection)) 03372 { 03373 CONNECTION_UNLOCK (connection); 03374 03375 return TRUE; 03376 } 03377 03378 pending = _dbus_pending_call_new_unlocked (connection, 03379 timeout_milliseconds, 03380 reply_handler_timeout); 03381 03382 if (pending == NULL) 03383 { 03384 CONNECTION_UNLOCK (connection); 03385 return FALSE; 03386 } 03387 03388 /* Assign a serial to the message */ 03389 serial = dbus_message_get_serial (message); 03390 if (serial == 0) 03391 { 03392 serial = _dbus_connection_get_next_client_serial (connection); 03393 dbus_message_set_serial (message, serial); 03394 } 03395 03396 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial)) 03397 goto error; 03398 03399 /* Insert the serial in the pending replies hash; 03400 * hash takes a refcount on DBusPendingCall. 03401 * Also, add the timeout. 03402 */ 03403 if (!_dbus_connection_attach_pending_call_unlocked (connection, 03404 pending)) 03405 goto error; 03406 03407 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL)) 03408 { 03409 _dbus_connection_detach_pending_call_and_unlock (connection, 03410 pending); 03411 goto error_unlocked; 03412 } 03413 03414 if (pending_return) 03415 *pending_return = pending; /* hand off refcount */ 03416 else 03417 { 03418 _dbus_connection_detach_pending_call_unlocked (connection, pending); 03419 /* we still have a ref to the pending call in this case, we unref 03420 * after unlocking, below 03421 */ 03422 } 03423 03424 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03425 03426 /* this calls out to user code */ 03427 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03428 03429 if (pending_return == NULL) 03430 dbus_pending_call_unref (pending); 03431 03432 return TRUE; 03433 03434 error: 03435 CONNECTION_UNLOCK (connection); 03436 error_unlocked: 03437 dbus_pending_call_unref (pending); 03438 return FALSE; 03439 } 03440 03473 DBusMessage* 03474 dbus_connection_send_with_reply_and_block (DBusConnection *connection, 03475 DBusMessage *message, 03476 int timeout_milliseconds, 03477 DBusError *error) 03478 { 03479 DBusMessage *reply; 03480 DBusPendingCall *pending; 03481 03482 _dbus_return_val_if_fail (connection != NULL, NULL); 03483 _dbus_return_val_if_fail (message != NULL, NULL); 03484 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL); 03485 _dbus_return_val_if_error_is_set (error, NULL); 03486 03487 #ifdef HAVE_UNIX_FD_PASSING 03488 03489 CONNECTION_LOCK (connection); 03490 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03491 message->n_unix_fds > 0) 03492 { 03493 CONNECTION_UNLOCK (connection); 03494 dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection."); 03495 return NULL; 03496 } 03497 CONNECTION_UNLOCK (connection); 03498 03499 #endif 03500 03501 if (!dbus_connection_send_with_reply (connection, message, 03502 &pending, timeout_milliseconds)) 03503 { 03504 _DBUS_SET_OOM (error); 03505 return NULL; 03506 } 03507 03508 if (pending == NULL) 03509 { 03510 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed"); 03511 return NULL; 03512 } 03513 03514 dbus_pending_call_block (pending); 03515 03516 reply = dbus_pending_call_steal_reply (pending); 03517 dbus_pending_call_unref (pending); 03518 03519 /* call_complete_and_unlock() called from pending_call_block() should 03520 * always fill this in. 03521 */ 03522 _dbus_assert (reply != NULL); 03523 03524 if (dbus_set_error_from_message (error, reply)) 03525 { 03526 dbus_message_unref (reply); 03527 return NULL; 03528 } 03529 else 03530 return reply; 03531 } 03532 03541 static DBusDispatchStatus 03542 _dbus_connection_flush_unlocked (DBusConnection *connection) 03543 { 03544 /* We have to specify DBUS_ITERATION_DO_READING here because 03545 * otherwise we could have two apps deadlock if they are both doing 03546 * a flush(), and the kernel buffers fill up. This could change the 03547 * dispatch status. 03548 */ 03549 DBusDispatchStatus status; 03550 03551 HAVE_LOCK_CHECK (connection); 03552 03553 while (connection->n_outgoing > 0 && 03554 _dbus_connection_get_is_connected_unlocked (connection)) 03555 { 03556 _dbus_verbose ("doing iteration in\n"); 03557 HAVE_LOCK_CHECK (connection); 03558 _dbus_connection_do_iteration_unlocked (connection, 03559 NULL, 03560 DBUS_ITERATION_DO_READING | 03561 DBUS_ITERATION_DO_WRITING | 03562 DBUS_ITERATION_BLOCK, 03563 -1); 03564 } 03565 03566 HAVE_LOCK_CHECK (connection); 03567 _dbus_verbose ("middle\n"); 03568 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03569 03570 HAVE_LOCK_CHECK (connection); 03571 return status; 03572 } 03573 03579 void 03580 dbus_connection_flush (DBusConnection *connection) 03581 { 03582 /* We have to specify DBUS_ITERATION_DO_READING here because 03583 * otherwise we could have two apps deadlock if they are both doing 03584 * a flush(), and the kernel buffers fill up. This could change the 03585 * dispatch status. 03586 */ 03587 DBusDispatchStatus status; 03588 03589 _dbus_return_if_fail (connection != NULL); 03590 03591 CONNECTION_LOCK (connection); 03592 03593 status = _dbus_connection_flush_unlocked (connection); 03594 03595 HAVE_LOCK_CHECK (connection); 03596 /* Unlocks and calls out to user code */ 03597 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03598 03599 _dbus_verbose ("end\n"); 03600 } 03601 03612 static dbus_bool_t 03613 _dbus_connection_read_write_dispatch (DBusConnection *connection, 03614 int timeout_milliseconds, 03615 dbus_bool_t dispatch) 03616 { 03617 DBusDispatchStatus dstatus; 03618 dbus_bool_t progress_possible; 03619 03620 /* Need to grab a ref here in case we're a private connection and 03621 * the user drops the last ref in a handler we call; see bug 03622 * https://bugs.freedesktop.org/show_bug.cgi?id=15635 03623 */ 03624 dbus_connection_ref (connection); 03625 dstatus = dbus_connection_get_dispatch_status (connection); 03626 03627 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS) 03628 { 03629 _dbus_verbose ("doing dispatch\n"); 03630 dbus_connection_dispatch (connection); 03631 CONNECTION_LOCK (connection); 03632 } 03633 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY) 03634 { 03635 _dbus_verbose ("pausing for memory\n"); 03636 _dbus_memory_pause_based_on_timeout (timeout_milliseconds); 03637 CONNECTION_LOCK (connection); 03638 } 03639 else 03640 { 03641 CONNECTION_LOCK (connection); 03642 if (_dbus_connection_get_is_connected_unlocked (connection)) 03643 { 03644 _dbus_verbose ("doing iteration\n"); 03645 _dbus_connection_do_iteration_unlocked (connection, 03646 NULL, 03647 DBUS_ITERATION_DO_READING | 03648 DBUS_ITERATION_DO_WRITING | 03649 DBUS_ITERATION_BLOCK, 03650 timeout_milliseconds); 03651 } 03652 } 03653 03654 HAVE_LOCK_CHECK (connection); 03655 /* If we can dispatch, we can make progress until the Disconnected message 03656 * has been processed; if we can only read/write, we can make progress 03657 * as long as the transport is open. 03658 */ 03659 if (dispatch) 03660 progress_possible = connection->n_incoming != 0 || 03661 connection->disconnect_message_link != NULL; 03662 else 03663 progress_possible = _dbus_connection_get_is_connected_unlocked (connection); 03664 03665 CONNECTION_UNLOCK (connection); 03666 03667 dbus_connection_unref (connection); 03668 03669 return progress_possible; /* TRUE if we can make more progress */ 03670 } 03671 03672 03707 dbus_bool_t 03708 dbus_connection_read_write_dispatch (DBusConnection *connection, 03709 int timeout_milliseconds) 03710 { 03711 _dbus_return_val_if_fail (connection != NULL, FALSE); 03712 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03713 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE); 03714 } 03715 03739 dbus_bool_t 03740 dbus_connection_read_write (DBusConnection *connection, 03741 int timeout_milliseconds) 03742 { 03743 _dbus_return_val_if_fail (connection != NULL, FALSE); 03744 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03745 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE); 03746 } 03747 03748 /* We need to call this anytime we pop the head of the queue, and then 03749 * update_dispatch_status_and_unlock needs to be called afterward 03750 * which will "process" the disconnected message and set 03751 * disconnected_message_processed. 03752 */ 03753 static void 03754 check_disconnected_message_arrived_unlocked (DBusConnection *connection, 03755 DBusMessage *head_of_queue) 03756 { 03757 HAVE_LOCK_CHECK (connection); 03758 03759 /* checking that the link is NULL is an optimization to avoid the is_signal call */ 03760 if (connection->disconnect_message_link == NULL && 03761 dbus_message_is_signal (head_of_queue, 03762 DBUS_INTERFACE_LOCAL, 03763 "Disconnected")) 03764 { 03765 connection->disconnected_message_arrived = TRUE; 03766 } 03767 } 03768 03788 DBusMessage* 03789 dbus_connection_borrow_message (DBusConnection *connection) 03790 { 03791 DBusDispatchStatus status; 03792 DBusMessage *message; 03793 03794 _dbus_return_val_if_fail (connection != NULL, NULL); 03795 03796 _dbus_verbose ("start\n"); 03797 03798 /* this is called for the side effect that it queues 03799 * up any messages from the transport 03800 */ 03801 status = dbus_connection_get_dispatch_status (connection); 03802 if (status != DBUS_DISPATCH_DATA_REMAINS) 03803 return NULL; 03804 03805 CONNECTION_LOCK (connection); 03806 03807 _dbus_connection_acquire_dispatch (connection); 03808 03809 /* While a message is outstanding, the dispatch lock is held */ 03810 _dbus_assert (connection->message_borrowed == NULL); 03811 03812 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages); 03813 03814 message = connection->message_borrowed; 03815 03816 check_disconnected_message_arrived_unlocked (connection, message); 03817 03818 /* Note that we KEEP the dispatch lock until the message is returned */ 03819 if (message == NULL) 03820 _dbus_connection_release_dispatch (connection); 03821 03822 CONNECTION_UNLOCK (connection); 03823 03824 /* We don't update dispatch status until it's returned or stolen */ 03825 03826 return message; 03827 } 03828 03837 void 03838 dbus_connection_return_message (DBusConnection *connection, 03839 DBusMessage *message) 03840 { 03841 DBusDispatchStatus status; 03842 03843 _dbus_return_if_fail (connection != NULL); 03844 _dbus_return_if_fail (message != NULL); 03845 _dbus_return_if_fail (message == connection->message_borrowed); 03846 _dbus_return_if_fail (connection->dispatch_acquired); 03847 03848 CONNECTION_LOCK (connection); 03849 03850 _dbus_assert (message == connection->message_borrowed); 03851 03852 connection->message_borrowed = NULL; 03853 03854 _dbus_connection_release_dispatch (connection); 03855 03856 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03857 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03858 } 03859 03869 void 03870 dbus_connection_steal_borrowed_message (DBusConnection *connection, 03871 DBusMessage *message) 03872 { 03873 DBusMessage *pop_message; 03874 DBusDispatchStatus status; 03875 03876 _dbus_return_if_fail (connection != NULL); 03877 _dbus_return_if_fail (message != NULL); 03878 _dbus_return_if_fail (message == connection->message_borrowed); 03879 _dbus_return_if_fail (connection->dispatch_acquired); 03880 03881 CONNECTION_LOCK (connection); 03882 03883 _dbus_assert (message == connection->message_borrowed); 03884 03885 pop_message = _dbus_list_pop_first (&connection->incoming_messages); 03886 _dbus_assert (message == pop_message); 03887 (void) pop_message; /* unused unless asserting */ 03888 03889 connection->n_incoming -= 1; 03890 03891 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n", 03892 message, connection->n_incoming); 03893 03894 connection->message_borrowed = NULL; 03895 03896 _dbus_connection_release_dispatch (connection); 03897 03898 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03899 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03900 } 03901 03902 /* See dbus_connection_pop_message, but requires the caller to own 03903 * the lock before calling. May drop the lock while running. 03904 */ 03905 static DBusList* 03906 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection) 03907 { 03908 HAVE_LOCK_CHECK (connection); 03909 03910 _dbus_assert (connection->message_borrowed == NULL); 03911 03912 if (connection->n_incoming > 0) 03913 { 03914 DBusList *link; 03915 03916 link = _dbus_list_pop_first_link (&connection->incoming_messages); 03917 connection->n_incoming -= 1; 03918 03919 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from incoming queue %p, %d incoming\n", 03920 link->data, 03921 dbus_message_type_to_string (dbus_message_get_type (link->data)), 03922 dbus_message_get_path (link->data) ? 03923 dbus_message_get_path (link->data) : 03924 "no path", 03925 dbus_message_get_interface (link->data) ? 03926 dbus_message_get_interface (link->data) : 03927 "no interface", 03928 dbus_message_get_member (link->data) ? 03929 dbus_message_get_member (link->data) : 03930 "no member", 03931 dbus_message_get_signature (link->data), 03932 connection, connection->n_incoming); 03933 03934 check_disconnected_message_arrived_unlocked (connection, link->data); 03935 03936 return link; 03937 } 03938 else 03939 return NULL; 03940 } 03941 03942 /* See dbus_connection_pop_message, but requires the caller to own 03943 * the lock before calling. May drop the lock while running. 03944 */ 03945 static DBusMessage* 03946 _dbus_connection_pop_message_unlocked (DBusConnection *connection) 03947 { 03948 DBusList *link; 03949 03950 HAVE_LOCK_CHECK (connection); 03951 03952 link = _dbus_connection_pop_message_link_unlocked (connection); 03953 03954 if (link != NULL) 03955 { 03956 DBusMessage *message; 03957 03958 message = link->data; 03959 03960 _dbus_list_free_link (link); 03961 03962 return message; 03963 } 03964 else 03965 return NULL; 03966 } 03967 03968 static void 03969 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection, 03970 DBusList *message_link) 03971 { 03972 HAVE_LOCK_CHECK (connection); 03973 03974 _dbus_assert (message_link != NULL); 03975 /* You can't borrow a message while a link is outstanding */ 03976 _dbus_assert (connection->message_borrowed == NULL); 03977 /* We had to have the dispatch lock across the pop/putback */ 03978 _dbus_assert (connection->dispatch_acquired); 03979 03980 _dbus_list_prepend_link (&connection->incoming_messages, 03981 message_link); 03982 connection->n_incoming += 1; 03983 03984 _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n", 03985 message_link->data, 03986 dbus_message_type_to_string (dbus_message_get_type (message_link->data)), 03987 dbus_message_get_interface (message_link->data) ? 03988 dbus_message_get_interface (message_link->data) : 03989 "no interface", 03990 dbus_message_get_member (message_link->data) ? 03991 dbus_message_get_member (message_link->data) : 03992 "no member", 03993 dbus_message_get_signature (message_link->data), 03994 connection, connection->n_incoming); 03995 } 03996 04016 DBusMessage* 04017 dbus_connection_pop_message (DBusConnection *connection) 04018 { 04019 DBusMessage *message; 04020 DBusDispatchStatus status; 04021 04022 _dbus_verbose ("start\n"); 04023 04024 /* this is called for the side effect that it queues 04025 * up any messages from the transport 04026 */ 04027 status = dbus_connection_get_dispatch_status (connection); 04028 if (status != DBUS_DISPATCH_DATA_REMAINS) 04029 return NULL; 04030 04031 CONNECTION_LOCK (connection); 04032 _dbus_connection_acquire_dispatch (connection); 04033 HAVE_LOCK_CHECK (connection); 04034 04035 message = _dbus_connection_pop_message_unlocked (connection); 04036 04037 _dbus_verbose ("Returning popped message %p\n", message); 04038 04039 _dbus_connection_release_dispatch (connection); 04040 04041 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04042 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04043 04044 return message; 04045 } 04046 04054 static void 04055 _dbus_connection_acquire_dispatch (DBusConnection *connection) 04056 { 04057 HAVE_LOCK_CHECK (connection); 04058 04059 _dbus_connection_ref_unlocked (connection); 04060 CONNECTION_UNLOCK (connection); 04061 04062 _dbus_verbose ("locking dispatch_mutex\n"); 04063 _dbus_mutex_lock (connection->dispatch_mutex); 04064 04065 while (connection->dispatch_acquired) 04066 { 04067 _dbus_verbose ("waiting for dispatch to be acquirable\n"); 04068 _dbus_condvar_wait (connection->dispatch_cond, 04069 connection->dispatch_mutex); 04070 } 04071 04072 _dbus_assert (!connection->dispatch_acquired); 04073 04074 connection->dispatch_acquired = TRUE; 04075 04076 _dbus_verbose ("unlocking dispatch_mutex\n"); 04077 _dbus_mutex_unlock (connection->dispatch_mutex); 04078 04079 CONNECTION_LOCK (connection); 04080 _dbus_connection_unref_unlocked (connection); 04081 } 04082 04090 static void 04091 _dbus_connection_release_dispatch (DBusConnection *connection) 04092 { 04093 HAVE_LOCK_CHECK (connection); 04094 04095 _dbus_verbose ("locking dispatch_mutex\n"); 04096 _dbus_mutex_lock (connection->dispatch_mutex); 04097 04098 _dbus_assert (connection->dispatch_acquired); 04099 04100 connection->dispatch_acquired = FALSE; 04101 _dbus_condvar_wake_one (connection->dispatch_cond); 04102 04103 _dbus_verbose ("unlocking dispatch_mutex\n"); 04104 _dbus_mutex_unlock (connection->dispatch_mutex); 04105 } 04106 04107 static void 04108 _dbus_connection_failed_pop (DBusConnection *connection, 04109 DBusList *message_link) 04110 { 04111 _dbus_list_prepend_link (&connection->incoming_messages, 04112 message_link); 04113 connection->n_incoming += 1; 04114 } 04115 04116 /* Note this may be called multiple times since we don't track whether we already did it */ 04117 static void 04118 notify_disconnected_unlocked (DBusConnection *connection) 04119 { 04120 HAVE_LOCK_CHECK (connection); 04121 04122 /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected 04123 * connection from dbus_bus_get(). We make the same guarantee for 04124 * dbus_connection_open() but in a different way since we don't want to 04125 * unref right here; we instead check for connectedness before returning 04126 * the connection from the hash. 04127 */ 04128 _dbus_bus_notify_shared_connection_disconnected_unlocked (connection); 04129 04130 /* Dump the outgoing queue, we aren't going to be able to 04131 * send it now, and we'd like accessors like 04132 * dbus_connection_get_outgoing_size() to be accurate. 04133 */ 04134 if (connection->n_outgoing > 0) 04135 { 04136 DBusList *link; 04137 04138 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n", 04139 connection->n_outgoing); 04140 04141 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages))) 04142 { 04143 _dbus_connection_message_sent_unlocked (connection, link->data); 04144 } 04145 } 04146 } 04147 04148 /* Note this may be called multiple times since we don't track whether we already did it */ 04149 static DBusDispatchStatus 04150 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection) 04151 { 04152 HAVE_LOCK_CHECK (connection); 04153 04154 if (connection->disconnect_message_link != NULL) 04155 { 04156 _dbus_verbose ("Sending disconnect message\n"); 04157 04158 /* If we have pending calls, queue their timeouts - we want the Disconnected 04159 * to be the last message, after these timeouts. 04160 */ 04161 connection_timeout_and_complete_all_pending_calls_unlocked (connection); 04162 04163 /* We haven't sent the disconnect message already, 04164 * and all real messages have been queued up. 04165 */ 04166 _dbus_connection_queue_synthesized_message_link (connection, 04167 connection->disconnect_message_link); 04168 connection->disconnect_message_link = NULL; 04169 04170 return DBUS_DISPATCH_DATA_REMAINS; 04171 } 04172 04173 return DBUS_DISPATCH_COMPLETE; 04174 } 04175 04176 static DBusDispatchStatus 04177 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection) 04178 { 04179 HAVE_LOCK_CHECK (connection); 04180 04181 if (connection->n_incoming > 0) 04182 return DBUS_DISPATCH_DATA_REMAINS; 04183 else if (!_dbus_transport_queue_messages (connection->transport)) 04184 return DBUS_DISPATCH_NEED_MEMORY; 04185 else 04186 { 04187 DBusDispatchStatus status; 04188 dbus_bool_t is_connected; 04189 04190 status = _dbus_transport_get_dispatch_status (connection->transport); 04191 is_connected = _dbus_transport_get_is_connected (connection->transport); 04192 04193 _dbus_verbose ("dispatch status = %s is_connected = %d\n", 04194 DISPATCH_STATUS_NAME (status), is_connected); 04195 04196 if (!is_connected) 04197 { 04198 /* It's possible this would be better done by having an explicit 04199 * notification from _dbus_transport_disconnect() that would 04200 * synchronously do this, instead of waiting for the next dispatch 04201 * status check. However, probably not good to change until it causes 04202 * a problem. 04203 */ 04204 notify_disconnected_unlocked (connection); 04205 04206 /* I'm not sure this is needed; the idea is that we want to 04207 * queue the Disconnected only after we've read all the 04208 * messages, but if we're disconnected maybe we are guaranteed 04209 * to have read them all ? 04210 */ 04211 if (status == DBUS_DISPATCH_COMPLETE) 04212 status = notify_disconnected_and_dispatch_complete_unlocked (connection); 04213 } 04214 04215 if (status != DBUS_DISPATCH_COMPLETE) 04216 return status; 04217 else if (connection->n_incoming > 0) 04218 return DBUS_DISPATCH_DATA_REMAINS; 04219 else 04220 return DBUS_DISPATCH_COMPLETE; 04221 } 04222 } 04223 04224 static void 04225 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection, 04226 DBusDispatchStatus new_status) 04227 { 04228 dbus_bool_t changed; 04229 DBusDispatchStatusFunction function; 04230 void *data; 04231 04232 HAVE_LOCK_CHECK (connection); 04233 04234 _dbus_connection_ref_unlocked (connection); 04235 04236 changed = new_status != connection->last_dispatch_status; 04237 04238 connection->last_dispatch_status = new_status; 04239 04240 function = connection->dispatch_status_function; 04241 data = connection->dispatch_status_data; 04242 04243 if (connection->disconnected_message_arrived && 04244 !connection->disconnected_message_processed) 04245 { 04246 connection->disconnected_message_processed = TRUE; 04247 04248 /* this does an unref, but we have a ref 04249 * so we should not run the finalizer here 04250 * inside the lock. 04251 */ 04252 connection_forget_shared_unlocked (connection); 04253 04254 if (connection->exit_on_disconnect) 04255 { 04256 CONNECTION_UNLOCK (connection); 04257 04258 _dbus_verbose ("Exiting on Disconnected signal\n"); 04259 _dbus_exit (1); 04260 _dbus_assert_not_reached ("Call to exit() returned"); 04261 } 04262 } 04263 04264 /* We drop the lock */ 04265 CONNECTION_UNLOCK (connection); 04266 04267 if (changed && function) 04268 { 04269 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n", 04270 connection, new_status, 04271 DISPATCH_STATUS_NAME (new_status)); 04272 (* function) (connection, new_status, data); 04273 } 04274 04275 dbus_connection_unref (connection); 04276 } 04277 04303 DBusDispatchStatus 04304 dbus_connection_get_dispatch_status (DBusConnection *connection) 04305 { 04306 DBusDispatchStatus status; 04307 04308 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE); 04309 04310 _dbus_verbose ("start\n"); 04311 04312 CONNECTION_LOCK (connection); 04313 04314 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04315 04316 CONNECTION_UNLOCK (connection); 04317 04318 return status; 04319 } 04320 04324 static DBusHandlerResult 04325 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection, 04326 DBusMessage *message) 04327 { 04328 dbus_bool_t sent = FALSE; 04329 DBusMessage *ret = NULL; 04330 DBusList *expire_link; 04331 04332 if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL) 04333 { 04334 /* This means we're letting the bus route this message */ 04335 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04336 } 04337 04338 if (!dbus_message_has_interface (message, DBUS_INTERFACE_PEER)) 04339 { 04340 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04341 } 04342 04343 /* Preallocate a linked-list link, so that if we need to dispose of a 04344 * message, we can attach it to the expired list */ 04345 expire_link = _dbus_list_alloc_link (NULL); 04346 04347 if (!expire_link) 04348 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04349 04350 if (dbus_message_is_method_call (message, 04351 DBUS_INTERFACE_PEER, 04352 "Ping")) 04353 { 04354 ret = dbus_message_new_method_return (message); 04355 if (ret == NULL) 04356 goto out; 04357 04358 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04359 } 04360 else if (dbus_message_is_method_call (message, 04361 DBUS_INTERFACE_PEER, 04362 "GetMachineId")) 04363 { 04364 DBusString uuid; 04365 04366 ret = dbus_message_new_method_return (message); 04367 if (ret == NULL) 04368 goto out; 04369 04370 _dbus_string_init (&uuid); 04371 if (_dbus_get_local_machine_uuid_encoded (&uuid)) 04372 { 04373 const char *v_STRING = _dbus_string_get_const_data (&uuid); 04374 if (dbus_message_append_args (ret, 04375 DBUS_TYPE_STRING, &v_STRING, 04376 DBUS_TYPE_INVALID)) 04377 { 04378 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04379 } 04380 } 04381 _dbus_string_free (&uuid); 04382 } 04383 else 04384 { 04385 /* We need to bounce anything else with this interface, otherwise apps 04386 * could start extending the interface and when we added extensions 04387 * here to DBusConnection we'd break those apps. 04388 */ 04389 ret = dbus_message_new_error (message, 04390 DBUS_ERROR_UNKNOWN_METHOD, 04391 "Unknown method invoked on org.freedesktop.DBus.Peer interface"); 04392 if (ret == NULL) 04393 goto out; 04394 04395 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04396 } 04397 04398 out: 04399 if (ret == NULL) 04400 { 04401 _dbus_list_free_link (expire_link); 04402 } 04403 else 04404 { 04405 /* It'll be safe to unref the reply when we unlock */ 04406 expire_link->data = ret; 04407 _dbus_list_prepend_link (&connection->expired_messages, expire_link); 04408 } 04409 04410 if (!sent) 04411 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04412 04413 return DBUS_HANDLER_RESULT_HANDLED; 04414 } 04415 04422 static DBusHandlerResult 04423 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection, 04424 DBusMessage *message) 04425 { 04426 /* We just run one filter for now but have the option to run more 04427 if the spec calls for it in the future */ 04428 04429 return _dbus_connection_peer_filter_unlocked_no_update (connection, message); 04430 } 04431 04474 DBusDispatchStatus 04475 dbus_connection_dispatch (DBusConnection *connection) 04476 { 04477 DBusMessage *message; 04478 DBusList *link, *filter_list_copy, *message_link; 04479 DBusHandlerResult result; 04480 DBusPendingCall *pending; 04481 dbus_int32_t reply_serial; 04482 DBusDispatchStatus status; 04483 dbus_bool_t found_object; 04484 04485 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE); 04486 04487 _dbus_verbose ("\n"); 04488 04489 CONNECTION_LOCK (connection); 04490 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04491 if (status != DBUS_DISPATCH_DATA_REMAINS) 04492 { 04493 /* unlocks and calls out to user code */ 04494 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04495 return status; 04496 } 04497 04498 /* We need to ref the connection since the callback could potentially 04499 * drop the last ref to it 04500 */ 04501 _dbus_connection_ref_unlocked (connection); 04502 04503 _dbus_connection_acquire_dispatch (connection); 04504 HAVE_LOCK_CHECK (connection); 04505 04506 message_link = _dbus_connection_pop_message_link_unlocked (connection); 04507 if (message_link == NULL) 04508 { 04509 /* another thread dispatched our stuff */ 04510 04511 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n"); 04512 04513 _dbus_connection_release_dispatch (connection); 04514 04515 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04516 04517 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04518 04519 dbus_connection_unref (connection); 04520 04521 return status; 04522 } 04523 04524 message = message_link->data; 04525 04526 _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n", 04527 message, 04528 dbus_message_type_to_string (dbus_message_get_type (message)), 04529 dbus_message_get_interface (message) ? 04530 dbus_message_get_interface (message) : 04531 "no interface", 04532 dbus_message_get_member (message) ? 04533 dbus_message_get_member (message) : 04534 "no member", 04535 dbus_message_get_signature (message)); 04536 04537 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04538 04539 /* Pending call handling must be first, because if you do 04540 * dbus_connection_send_with_reply_and_block() or 04541 * dbus_pending_call_block() then no handlers/filters will be run on 04542 * the reply. We want consistent semantics in the case where we 04543 * dbus_connection_dispatch() the reply. 04544 */ 04545 04546 reply_serial = dbus_message_get_reply_serial (message); 04547 pending = _dbus_hash_table_lookup_int (connection->pending_replies, 04548 reply_serial); 04549 if (pending) 04550 { 04551 _dbus_verbose ("Dispatching a pending reply\n"); 04552 complete_pending_call_and_unlock (connection, pending, message); 04553 pending = NULL; /* it's probably unref'd */ 04554 04555 CONNECTION_LOCK (connection); 04556 _dbus_verbose ("pending call completed in dispatch\n"); 04557 result = DBUS_HANDLER_RESULT_HANDLED; 04558 goto out; 04559 } 04560 04561 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message); 04562 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04563 goto out; 04564 04565 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy)) 04566 { 04567 _dbus_connection_release_dispatch (connection); 04568 HAVE_LOCK_CHECK (connection); 04569 04570 _dbus_connection_failed_pop (connection, message_link); 04571 04572 /* unlocks and calls user code */ 04573 _dbus_connection_update_dispatch_status_and_unlock (connection, 04574 DBUS_DISPATCH_NEED_MEMORY); 04575 dbus_connection_unref (connection); 04576 04577 return DBUS_DISPATCH_NEED_MEMORY; 04578 } 04579 04580 _dbus_list_foreach (&filter_list_copy, 04581 (DBusForeachFunction)_dbus_message_filter_ref, 04582 NULL); 04583 04584 /* We're still protected from dispatch() reentrancy here 04585 * since we acquired the dispatcher 04586 */ 04587 CONNECTION_UNLOCK (connection); 04588 04589 link = _dbus_list_get_first_link (&filter_list_copy); 04590 while (link != NULL) 04591 { 04592 DBusMessageFilter *filter = link->data; 04593 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link); 04594 04595 if (filter->function == NULL) 04596 { 04597 _dbus_verbose (" filter was removed in a callback function\n"); 04598 link = next; 04599 continue; 04600 } 04601 04602 _dbus_verbose (" running filter on message %p\n", message); 04603 result = (* filter->function) (connection, message, filter->user_data); 04604 04605 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04606 break; 04607 04608 link = next; 04609 } 04610 04611 _dbus_list_foreach (&filter_list_copy, 04612 (DBusForeachFunction)_dbus_message_filter_unref, 04613 NULL); 04614 _dbus_list_clear (&filter_list_copy); 04615 04616 CONNECTION_LOCK (connection); 04617 04618 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) 04619 { 04620 _dbus_verbose ("No memory\n"); 04621 goto out; 04622 } 04623 else if (result == DBUS_HANDLER_RESULT_HANDLED) 04624 { 04625 _dbus_verbose ("filter handled message in dispatch\n"); 04626 goto out; 04627 } 04628 04629 /* We're still protected from dispatch() reentrancy here 04630 * since we acquired the dispatcher 04631 */ 04632 _dbus_verbose (" running object path dispatch on message %p (%s %s %s '%s')\n", 04633 message, 04634 dbus_message_type_to_string (dbus_message_get_type (message)), 04635 dbus_message_get_interface (message) ? 04636 dbus_message_get_interface (message) : 04637 "no interface", 04638 dbus_message_get_member (message) ? 04639 dbus_message_get_member (message) : 04640 "no member", 04641 dbus_message_get_signature (message)); 04642 04643 HAVE_LOCK_CHECK (connection); 04644 result = _dbus_object_tree_dispatch_and_unlock (connection->objects, 04645 message, 04646 &found_object); 04647 04648 CONNECTION_LOCK (connection); 04649 04650 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04651 { 04652 _dbus_verbose ("object tree handled message in dispatch\n"); 04653 goto out; 04654 } 04655 04656 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL) 04657 { 04658 DBusMessage *reply; 04659 DBusString str; 04660 DBusPreallocatedSend *preallocated; 04661 DBusList *expire_link; 04662 04663 _dbus_verbose (" sending error %s\n", 04664 DBUS_ERROR_UNKNOWN_METHOD); 04665 04666 if (!_dbus_string_init (&str)) 04667 { 04668 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04669 _dbus_verbose ("no memory for error string in dispatch\n"); 04670 goto out; 04671 } 04672 04673 if (!_dbus_string_append_printf (&str, 04674 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n", 04675 dbus_message_get_member (message), 04676 dbus_message_get_signature (message), 04677 dbus_message_get_interface (message))) 04678 { 04679 _dbus_string_free (&str); 04680 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04681 _dbus_verbose ("no memory for error string in dispatch\n"); 04682 goto out; 04683 } 04684 04685 reply = dbus_message_new_error (message, 04686 found_object ? DBUS_ERROR_UNKNOWN_METHOD : DBUS_ERROR_UNKNOWN_OBJECT, 04687 _dbus_string_get_const_data (&str)); 04688 _dbus_string_free (&str); 04689 04690 if (reply == NULL) 04691 { 04692 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04693 _dbus_verbose ("no memory for error reply in dispatch\n"); 04694 goto out; 04695 } 04696 04697 expire_link = _dbus_list_alloc_link (reply); 04698 04699 if (expire_link == NULL) 04700 { 04701 dbus_message_unref (reply); 04702 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04703 _dbus_verbose ("no memory for error send in dispatch\n"); 04704 goto out; 04705 } 04706 04707 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 04708 04709 if (preallocated == NULL) 04710 { 04711 _dbus_list_free_link (expire_link); 04712 /* It's OK that this is finalized, because it hasn't been seen by 04713 * anything that could attach user callbacks */ 04714 dbus_message_unref (reply); 04715 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04716 _dbus_verbose ("no memory for error send in dispatch\n"); 04717 goto out; 04718 } 04719 04720 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated, 04721 reply, NULL); 04722 /* reply will be freed when we release the lock */ 04723 _dbus_list_prepend_link (&connection->expired_messages, expire_link); 04724 04725 result = DBUS_HANDLER_RESULT_HANDLED; 04726 } 04727 04728 _dbus_verbose (" done dispatching %p (%s %s %s '%s') on connection %p\n", message, 04729 dbus_message_type_to_string (dbus_message_get_type (message)), 04730 dbus_message_get_interface (message) ? 04731 dbus_message_get_interface (message) : 04732 "no interface", 04733 dbus_message_get_member (message) ? 04734 dbus_message_get_member (message) : 04735 "no member", 04736 dbus_message_get_signature (message), 04737 connection); 04738 04739 out: 04740 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) 04741 { 04742 _dbus_verbose ("out of memory\n"); 04743 04744 /* Put message back, and we'll start over. 04745 * Yes this means handlers must be idempotent if they 04746 * don't return HANDLED; c'est la vie. 04747 */ 04748 _dbus_connection_putback_message_link_unlocked (connection, 04749 message_link); 04750 /* now we don't want to free them */ 04751 message_link = NULL; 04752 message = NULL; 04753 } 04754 else 04755 { 04756 _dbus_verbose (" ... done dispatching\n"); 04757 } 04758 04759 _dbus_connection_release_dispatch (connection); 04760 HAVE_LOCK_CHECK (connection); 04761 04762 if (message != NULL) 04763 { 04764 /* We don't want this message to count in maximum message limits when 04765 * computing the dispatch status, below. We have to drop the lock 04766 * temporarily, because finalizing a message can trigger callbacks. 04767 * 04768 * We have a reference to the connection, and we don't use any cached 04769 * pointers to the connection's internals below this point, so it should 04770 * be safe to drop the lock and take it back. */ 04771 CONNECTION_UNLOCK (connection); 04772 dbus_message_unref (message); 04773 CONNECTION_LOCK (connection); 04774 } 04775 04776 if (message_link != NULL) 04777 _dbus_list_free_link (message_link); 04778 04779 _dbus_verbose ("before final status update\n"); 04780 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04781 04782 /* unlocks and calls user code */ 04783 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04784 04785 dbus_connection_unref (connection); 04786 04787 return status; 04788 } 04789 04851 dbus_bool_t 04852 dbus_connection_set_watch_functions (DBusConnection *connection, 04853 DBusAddWatchFunction add_function, 04854 DBusRemoveWatchFunction remove_function, 04855 DBusWatchToggledFunction toggled_function, 04856 void *data, 04857 DBusFreeFunction free_data_function) 04858 { 04859 dbus_bool_t retval; 04860 04861 _dbus_return_val_if_fail (connection != NULL, FALSE); 04862 04863 CONNECTION_LOCK (connection); 04864 04865 retval = _dbus_watch_list_set_functions (connection->watches, 04866 add_function, remove_function, 04867 toggled_function, 04868 data, free_data_function); 04869 04870 CONNECTION_UNLOCK (connection); 04871 04872 return retval; 04873 } 04874 04914 dbus_bool_t 04915 dbus_connection_set_timeout_functions (DBusConnection *connection, 04916 DBusAddTimeoutFunction add_function, 04917 DBusRemoveTimeoutFunction remove_function, 04918 DBusTimeoutToggledFunction toggled_function, 04919 void *data, 04920 DBusFreeFunction free_data_function) 04921 { 04922 dbus_bool_t retval; 04923 04924 _dbus_return_val_if_fail (connection != NULL, FALSE); 04925 04926 CONNECTION_LOCK (connection); 04927 04928 retval = _dbus_timeout_list_set_functions (connection->timeouts, 04929 add_function, remove_function, 04930 toggled_function, 04931 data, free_data_function); 04932 04933 CONNECTION_UNLOCK (connection); 04934 04935 return retval; 04936 } 04937 04952 void 04953 dbus_connection_set_wakeup_main_function (DBusConnection *connection, 04954 DBusWakeupMainFunction wakeup_main_function, 04955 void *data, 04956 DBusFreeFunction free_data_function) 04957 { 04958 void *old_data; 04959 DBusFreeFunction old_free_data; 04960 04961 _dbus_return_if_fail (connection != NULL); 04962 04963 CONNECTION_LOCK (connection); 04964 old_data = connection->wakeup_main_data; 04965 old_free_data = connection->free_wakeup_main_data; 04966 04967 connection->wakeup_main_function = wakeup_main_function; 04968 connection->wakeup_main_data = data; 04969 connection->free_wakeup_main_data = free_data_function; 04970 04971 CONNECTION_UNLOCK (connection); 04972 04973 /* Callback outside the lock */ 04974 if (old_free_data) 04975 (*old_free_data) (old_data); 04976 } 04977 04998 void 04999 dbus_connection_set_dispatch_status_function (DBusConnection *connection, 05000 DBusDispatchStatusFunction function, 05001 void *data, 05002 DBusFreeFunction free_data_function) 05003 { 05004 void *old_data; 05005 DBusFreeFunction old_free_data; 05006 05007 _dbus_return_if_fail (connection != NULL); 05008 05009 CONNECTION_LOCK (connection); 05010 old_data = connection->dispatch_status_data; 05011 old_free_data = connection->free_dispatch_status_data; 05012 05013 connection->dispatch_status_function = function; 05014 connection->dispatch_status_data = data; 05015 connection->free_dispatch_status_data = free_data_function; 05016 05017 CONNECTION_UNLOCK (connection); 05018 05019 /* Callback outside the lock */ 05020 if (old_free_data) 05021 (*old_free_data) (old_data); 05022 } 05023 05043 dbus_bool_t 05044 dbus_connection_get_unix_fd (DBusConnection *connection, 05045 int *fd) 05046 { 05047 _dbus_return_val_if_fail (connection != NULL, FALSE); 05048 _dbus_return_val_if_fail (connection->transport != NULL, FALSE); 05049 05050 #ifdef DBUS_WIN 05051 /* FIXME do this on a lower level */ 05052 return FALSE; 05053 #endif 05054 05055 return dbus_connection_get_socket(connection, fd); 05056 } 05057 05073 dbus_bool_t 05074 dbus_connection_get_socket(DBusConnection *connection, 05075 int *fd) 05076 { 05077 dbus_bool_t retval; 05078 05079 _dbus_return_val_if_fail (connection != NULL, FALSE); 05080 _dbus_return_val_if_fail (connection->transport != NULL, FALSE); 05081 05082 CONNECTION_LOCK (connection); 05083 05084 retval = _dbus_transport_get_socket_fd (connection->transport, 05085 fd); 05086 05087 CONNECTION_UNLOCK (connection); 05088 05089 return retval; 05090 } 05091 05092 05115 dbus_bool_t 05116 dbus_connection_get_unix_user (DBusConnection *connection, 05117 unsigned long *uid) 05118 { 05119 dbus_bool_t result; 05120 05121 _dbus_return_val_if_fail (connection != NULL, FALSE); 05122 _dbus_return_val_if_fail (uid != NULL, FALSE); 05123 05124 CONNECTION_LOCK (connection); 05125 05126 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05127 result = FALSE; 05128 else 05129 result = _dbus_transport_get_unix_user (connection->transport, 05130 uid); 05131 05132 #ifdef DBUS_WIN 05133 _dbus_assert (!result); 05134 #endif 05135 05136 CONNECTION_UNLOCK (connection); 05137 05138 return result; 05139 } 05140 05151 dbus_bool_t 05152 dbus_connection_get_unix_process_id (DBusConnection *connection, 05153 unsigned long *pid) 05154 { 05155 dbus_bool_t result; 05156 05157 _dbus_return_val_if_fail (connection != NULL, FALSE); 05158 _dbus_return_val_if_fail (pid != NULL, FALSE); 05159 05160 CONNECTION_LOCK (connection); 05161 05162 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05163 result = FALSE; 05164 else 05165 result = _dbus_transport_get_unix_process_id (connection->transport, 05166 pid); 05167 05168 CONNECTION_UNLOCK (connection); 05169 05170 return result; 05171 } 05172 05183 dbus_bool_t 05184 dbus_connection_get_adt_audit_session_data (DBusConnection *connection, 05185 void **data, 05186 dbus_int32_t *data_size) 05187 { 05188 dbus_bool_t result; 05189 05190 _dbus_return_val_if_fail (connection != NULL, FALSE); 05191 _dbus_return_val_if_fail (data != NULL, FALSE); 05192 _dbus_return_val_if_fail (data_size != NULL, FALSE); 05193 05194 CONNECTION_LOCK (connection); 05195 05196 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05197 result = FALSE; 05198 else 05199 result = _dbus_transport_get_adt_audit_session_data (connection->transport, 05200 data, 05201 data_size); 05202 CONNECTION_UNLOCK (connection); 05203 05204 return result; 05205 } 05206 05229 void 05230 dbus_connection_set_unix_user_function (DBusConnection *connection, 05231 DBusAllowUnixUserFunction function, 05232 void *data, 05233 DBusFreeFunction free_data_function) 05234 { 05235 void *old_data = NULL; 05236 DBusFreeFunction old_free_function = NULL; 05237 05238 _dbus_return_if_fail (connection != NULL); 05239 05240 CONNECTION_LOCK (connection); 05241 _dbus_transport_set_unix_user_function (connection->transport, 05242 function, data, free_data_function, 05243 &old_data, &old_free_function); 05244 CONNECTION_UNLOCK (connection); 05245 05246 if (old_free_function != NULL) 05247 (* old_free_function) (old_data); 05248 } 05249 05281 dbus_bool_t 05282 dbus_connection_get_windows_user (DBusConnection *connection, 05283 char **windows_sid_p) 05284 { 05285 dbus_bool_t result; 05286 05287 _dbus_return_val_if_fail (connection != NULL, FALSE); 05288 _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE); 05289 05290 CONNECTION_LOCK (connection); 05291 05292 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05293 result = FALSE; 05294 else 05295 result = _dbus_transport_get_windows_user (connection->transport, 05296 windows_sid_p); 05297 05298 #ifdef DBUS_UNIX 05299 _dbus_assert (!result); 05300 #endif 05301 05302 CONNECTION_UNLOCK (connection); 05303 05304 return result; 05305 } 05306 05328 void 05329 dbus_connection_set_windows_user_function (DBusConnection *connection, 05330 DBusAllowWindowsUserFunction function, 05331 void *data, 05332 DBusFreeFunction free_data_function) 05333 { 05334 void *old_data = NULL; 05335 DBusFreeFunction old_free_function = NULL; 05336 05337 _dbus_return_if_fail (connection != NULL); 05338 05339 CONNECTION_LOCK (connection); 05340 _dbus_transport_set_windows_user_function (connection->transport, 05341 function, data, free_data_function, 05342 &old_data, &old_free_function); 05343 CONNECTION_UNLOCK (connection); 05344 05345 if (old_free_function != NULL) 05346 (* old_free_function) (old_data); 05347 } 05348 05375 void 05376 dbus_connection_set_allow_anonymous (DBusConnection *connection, 05377 dbus_bool_t value) 05378 { 05379 _dbus_return_if_fail (connection != NULL); 05380 05381 CONNECTION_LOCK (connection); 05382 _dbus_transport_set_allow_anonymous (connection->transport, value); 05383 CONNECTION_UNLOCK (connection); 05384 } 05385 05403 void 05404 dbus_connection_set_route_peer_messages (DBusConnection *connection, 05405 dbus_bool_t value) 05406 { 05407 _dbus_return_if_fail (connection != NULL); 05408 05409 CONNECTION_LOCK (connection); 05410 connection->route_peer_messages = TRUE; 05411 CONNECTION_UNLOCK (connection); 05412 } 05413 05435 dbus_bool_t 05436 dbus_connection_add_filter (DBusConnection *connection, 05437 DBusHandleMessageFunction function, 05438 void *user_data, 05439 DBusFreeFunction free_data_function) 05440 { 05441 DBusMessageFilter *filter; 05442 05443 _dbus_return_val_if_fail (connection != NULL, FALSE); 05444 _dbus_return_val_if_fail (function != NULL, FALSE); 05445 05446 filter = dbus_new0 (DBusMessageFilter, 1); 05447 if (filter == NULL) 05448 return FALSE; 05449 05450 _dbus_atomic_inc (&filter->refcount); 05451 05452 CONNECTION_LOCK (connection); 05453 05454 if (!_dbus_list_append (&connection->filter_list, 05455 filter)) 05456 { 05457 _dbus_message_filter_unref (filter); 05458 CONNECTION_UNLOCK (connection); 05459 return FALSE; 05460 } 05461 05462 /* Fill in filter after all memory allocated, 05463 * so we don't run the free_user_data_function 05464 * if the add_filter() fails 05465 */ 05466 05467 filter->function = function; 05468 filter->user_data = user_data; 05469 filter->free_user_data_function = free_data_function; 05470 05471 CONNECTION_UNLOCK (connection); 05472 return TRUE; 05473 } 05474 05487 void 05488 dbus_connection_remove_filter (DBusConnection *connection, 05489 DBusHandleMessageFunction function, 05490 void *user_data) 05491 { 05492 DBusList *link; 05493 DBusMessageFilter *filter; 05494 05495 _dbus_return_if_fail (connection != NULL); 05496 _dbus_return_if_fail (function != NULL); 05497 05498 CONNECTION_LOCK (connection); 05499 05500 filter = NULL; 05501 05502 link = _dbus_list_get_last_link (&connection->filter_list); 05503 while (link != NULL) 05504 { 05505 filter = link->data; 05506 05507 if (filter->function == function && 05508 filter->user_data == user_data) 05509 { 05510 _dbus_list_remove_link (&connection->filter_list, link); 05511 filter->function = NULL; 05512 05513 break; 05514 } 05515 05516 link = _dbus_list_get_prev_link (&connection->filter_list, link); 05517 filter = NULL; 05518 } 05519 05520 CONNECTION_UNLOCK (connection); 05521 05522 #ifndef DBUS_DISABLE_CHECKS 05523 if (filter == NULL) 05524 { 05525 _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n", 05526 function, user_data); 05527 return; 05528 } 05529 #endif 05530 05531 /* Call application code */ 05532 if (filter->free_user_data_function) 05533 (* filter->free_user_data_function) (filter->user_data); 05534 05535 filter->free_user_data_function = NULL; 05536 filter->user_data = NULL; 05537 05538 _dbus_message_filter_unref (filter); 05539 } 05540 05556 static dbus_bool_t 05557 _dbus_connection_register_object_path (DBusConnection *connection, 05558 dbus_bool_t fallback, 05559 const char *path, 05560 const DBusObjectPathVTable *vtable, 05561 void *user_data, 05562 DBusError *error) 05563 { 05564 char **decomposed_path; 05565 dbus_bool_t retval; 05566 05567 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05568 return FALSE; 05569 05570 CONNECTION_LOCK (connection); 05571 05572 retval = _dbus_object_tree_register (connection->objects, 05573 fallback, 05574 (const char **) decomposed_path, vtable, 05575 user_data, error); 05576 05577 CONNECTION_UNLOCK (connection); 05578 05579 dbus_free_string_array (decomposed_path); 05580 05581 return retval; 05582 } 05583 05596 dbus_bool_t 05597 dbus_connection_try_register_object_path (DBusConnection *connection, 05598 const char *path, 05599 const DBusObjectPathVTable *vtable, 05600 void *user_data, 05601 DBusError *error) 05602 { 05603 _dbus_return_val_if_fail (connection != NULL, FALSE); 05604 _dbus_return_val_if_fail (path != NULL, FALSE); 05605 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05606 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05607 05608 return _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, error); 05609 } 05610 05626 dbus_bool_t 05627 dbus_connection_register_object_path (DBusConnection *connection, 05628 const char *path, 05629 const DBusObjectPathVTable *vtable, 05630 void *user_data) 05631 { 05632 dbus_bool_t retval; 05633 DBusError error = DBUS_ERROR_INIT; 05634 05635 _dbus_return_val_if_fail (connection != NULL, FALSE); 05636 _dbus_return_val_if_fail (path != NULL, FALSE); 05637 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05638 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05639 05640 retval = _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, &error); 05641 05642 if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE)) 05643 { 05644 _dbus_warn ("%s\n", error.message); 05645 dbus_error_free (&error); 05646 return FALSE; 05647 } 05648 05649 return retval; 05650 } 05651 05666 dbus_bool_t 05667 dbus_connection_try_register_fallback (DBusConnection *connection, 05668 const char *path, 05669 const DBusObjectPathVTable *vtable, 05670 void *user_data, 05671 DBusError *error) 05672 { 05673 _dbus_return_val_if_fail (connection != NULL, FALSE); 05674 _dbus_return_val_if_fail (path != NULL, FALSE); 05675 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05676 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05677 05678 return _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, error); 05679 } 05680 05698 dbus_bool_t 05699 dbus_connection_register_fallback (DBusConnection *connection, 05700 const char *path, 05701 const DBusObjectPathVTable *vtable, 05702 void *user_data) 05703 { 05704 dbus_bool_t retval; 05705 DBusError error = DBUS_ERROR_INIT; 05706 05707 _dbus_return_val_if_fail (connection != NULL, FALSE); 05708 _dbus_return_val_if_fail (path != NULL, FALSE); 05709 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05710 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05711 05712 retval = _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, &error); 05713 05714 if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE)) 05715 { 05716 _dbus_warn ("%s\n", error.message); 05717 dbus_error_free (&error); 05718 return FALSE; 05719 } 05720 05721 return retval; 05722 } 05723 05733 dbus_bool_t 05734 dbus_connection_unregister_object_path (DBusConnection *connection, 05735 const char *path) 05736 { 05737 char **decomposed_path; 05738 05739 _dbus_return_val_if_fail (connection != NULL, FALSE); 05740 _dbus_return_val_if_fail (path != NULL, FALSE); 05741 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05742 05743 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05744 return FALSE; 05745 05746 CONNECTION_LOCK (connection); 05747 05748 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path); 05749 05750 dbus_free_string_array (decomposed_path); 05751 05752 return TRUE; 05753 } 05754 05765 dbus_bool_t 05766 dbus_connection_get_object_path_data (DBusConnection *connection, 05767 const char *path, 05768 void **data_p) 05769 { 05770 char **decomposed_path; 05771 05772 _dbus_return_val_if_fail (connection != NULL, FALSE); 05773 _dbus_return_val_if_fail (path != NULL, FALSE); 05774 _dbus_return_val_if_fail (data_p != NULL, FALSE); 05775 05776 *data_p = NULL; 05777 05778 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05779 return FALSE; 05780 05781 CONNECTION_LOCK (connection); 05782 05783 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path); 05784 05785 CONNECTION_UNLOCK (connection); 05786 05787 dbus_free_string_array (decomposed_path); 05788 05789 return TRUE; 05790 } 05791 05802 dbus_bool_t 05803 dbus_connection_list_registered (DBusConnection *connection, 05804 const char *parent_path, 05805 char ***child_entries) 05806 { 05807 char **decomposed_path; 05808 dbus_bool_t retval; 05809 _dbus_return_val_if_fail (connection != NULL, FALSE); 05810 _dbus_return_val_if_fail (parent_path != NULL, FALSE); 05811 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE); 05812 _dbus_return_val_if_fail (child_entries != NULL, FALSE); 05813 05814 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL)) 05815 return FALSE; 05816 05817 CONNECTION_LOCK (connection); 05818 05819 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects, 05820 (const char **) decomposed_path, 05821 child_entries); 05822 dbus_free_string_array (decomposed_path); 05823 05824 return retval; 05825 } 05826 05827 static DBusDataSlotAllocator slot_allocator; 05828 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots); 05829 05844 dbus_bool_t 05845 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p) 05846 { 05847 return _dbus_data_slot_allocator_alloc (&slot_allocator, 05848 &_DBUS_LOCK_NAME (connection_slots), 05849 slot_p); 05850 } 05851 05863 void 05864 dbus_connection_free_data_slot (dbus_int32_t *slot_p) 05865 { 05866 _dbus_return_if_fail (*slot_p >= 0); 05867 05868 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 05869 } 05870 05893 dbus_bool_t 05894 dbus_connection_set_data (DBusConnection *connection, 05895 dbus_int32_t slot, 05896 void *data, 05897 DBusFreeFunction free_data_func) 05898 { 05899 DBusFreeFunction old_free_func; 05900 void *old_data; 05901 dbus_bool_t retval; 05902 05903 _dbus_return_val_if_fail (connection != NULL, FALSE); 05904 _dbus_return_val_if_fail (slot >= 0, FALSE); 05905 05906 SLOTS_LOCK (connection); 05907 05908 retval = _dbus_data_slot_list_set (&slot_allocator, 05909 &connection->slot_list, 05910 slot, data, free_data_func, 05911 &old_free_func, &old_data); 05912 05913 SLOTS_UNLOCK (connection); 05914 05915 if (retval) 05916 { 05917 /* Do the actual free outside the connection lock */ 05918 if (old_free_func) 05919 (* old_free_func) (old_data); 05920 } 05921 05922 return retval; 05923 } 05924 05942 void* 05943 dbus_connection_get_data (DBusConnection *connection, 05944 dbus_int32_t slot) 05945 { 05946 void *res; 05947 05948 _dbus_return_val_if_fail (connection != NULL, NULL); 05949 05950 SLOTS_LOCK (connection); 05951 05952 res = _dbus_data_slot_list_get (&slot_allocator, 05953 &connection->slot_list, 05954 slot); 05955 05956 SLOTS_UNLOCK (connection); 05957 05958 return res; 05959 } 05960 05967 void 05968 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe) 05969 { 05970 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE; 05971 } 05972 05981 void 05982 dbus_connection_set_max_message_size (DBusConnection *connection, 05983 long size) 05984 { 05985 _dbus_return_if_fail (connection != NULL); 05986 05987 CONNECTION_LOCK (connection); 05988 _dbus_transport_set_max_message_size (connection->transport, 05989 size); 05990 CONNECTION_UNLOCK (connection); 05991 } 05992 05999 long 06000 dbus_connection_get_max_message_size (DBusConnection *connection) 06001 { 06002 long res; 06003 06004 _dbus_return_val_if_fail (connection != NULL, 0); 06005 06006 CONNECTION_LOCK (connection); 06007 res = _dbus_transport_get_max_message_size (connection->transport); 06008 CONNECTION_UNLOCK (connection); 06009 return res; 06010 } 06011 06020 void 06021 dbus_connection_set_max_message_unix_fds (DBusConnection *connection, 06022 long n) 06023 { 06024 _dbus_return_if_fail (connection != NULL); 06025 06026 CONNECTION_LOCK (connection); 06027 _dbus_transport_set_max_message_unix_fds (connection->transport, 06028 n); 06029 CONNECTION_UNLOCK (connection); 06030 } 06031 06038 long 06039 dbus_connection_get_max_message_unix_fds (DBusConnection *connection) 06040 { 06041 long res; 06042 06043 _dbus_return_val_if_fail (connection != NULL, 0); 06044 06045 CONNECTION_LOCK (connection); 06046 res = _dbus_transport_get_max_message_unix_fds (connection->transport); 06047 CONNECTION_UNLOCK (connection); 06048 return res; 06049 } 06050 06076 void 06077 dbus_connection_set_max_received_size (DBusConnection *connection, 06078 long size) 06079 { 06080 _dbus_return_if_fail (connection != NULL); 06081 06082 CONNECTION_LOCK (connection); 06083 _dbus_transport_set_max_received_size (connection->transport, 06084 size); 06085 CONNECTION_UNLOCK (connection); 06086 } 06087 06094 long 06095 dbus_connection_get_max_received_size (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_received_size (connection->transport); 06103 CONNECTION_UNLOCK (connection); 06104 return res; 06105 } 06106 06118 void 06119 dbus_connection_set_max_received_unix_fds (DBusConnection *connection, 06120 long n) 06121 { 06122 _dbus_return_if_fail (connection != NULL); 06123 06124 CONNECTION_LOCK (connection); 06125 _dbus_transport_set_max_received_unix_fds (connection->transport, 06126 n); 06127 CONNECTION_UNLOCK (connection); 06128 } 06129 06136 long 06137 dbus_connection_get_max_received_unix_fds (DBusConnection *connection) 06138 { 06139 long res; 06140 06141 _dbus_return_val_if_fail (connection != NULL, 0); 06142 06143 CONNECTION_LOCK (connection); 06144 res = _dbus_transport_get_max_received_unix_fds (connection->transport); 06145 CONNECTION_UNLOCK (connection); 06146 return res; 06147 } 06148 06159 long 06160 dbus_connection_get_outgoing_size (DBusConnection *connection) 06161 { 06162 long res; 06163 06164 _dbus_return_val_if_fail (connection != NULL, 0); 06165 06166 CONNECTION_LOCK (connection); 06167 res = _dbus_counter_get_size_value (connection->outgoing_counter); 06168 CONNECTION_UNLOCK (connection); 06169 return res; 06170 } 06171 06172 #ifdef DBUS_ENABLE_STATS 06173 void 06174 _dbus_connection_get_stats (DBusConnection *connection, 06175 dbus_uint32_t *in_messages, 06176 dbus_uint32_t *in_bytes, 06177 dbus_uint32_t *in_fds, 06178 dbus_uint32_t *in_peak_bytes, 06179 dbus_uint32_t *in_peak_fds, 06180 dbus_uint32_t *out_messages, 06181 dbus_uint32_t *out_bytes, 06182 dbus_uint32_t *out_fds, 06183 dbus_uint32_t *out_peak_bytes, 06184 dbus_uint32_t *out_peak_fds) 06185 { 06186 CONNECTION_LOCK (connection); 06187 06188 if (in_messages != NULL) 06189 *in_messages = connection->n_incoming; 06190 06191 _dbus_transport_get_stats (connection->transport, 06192 in_bytes, in_fds, in_peak_bytes, in_peak_fds); 06193 06194 if (out_messages != NULL) 06195 *out_messages = connection->n_outgoing; 06196 06197 if (out_bytes != NULL) 06198 *out_bytes = _dbus_counter_get_size_value (connection->outgoing_counter); 06199 06200 if (out_fds != NULL) 06201 *out_fds = _dbus_counter_get_unix_fd_value (connection->outgoing_counter); 06202 06203 if (out_peak_bytes != NULL) 06204 *out_peak_bytes = _dbus_counter_get_peak_size_value (connection->outgoing_counter); 06205 06206 if (out_peak_fds != NULL) 06207 *out_peak_fds = _dbus_counter_get_peak_unix_fd_value (connection->outgoing_counter); 06208 06209 CONNECTION_UNLOCK (connection); 06210 } 06211 #endif /* DBUS_ENABLE_STATS */ 06212 06220 long 06221 dbus_connection_get_outgoing_unix_fds (DBusConnection *connection) 06222 { 06223 long res; 06224 06225 _dbus_return_val_if_fail (connection != NULL, 0); 06226 06227 CONNECTION_LOCK (connection); 06228 res = _dbus_counter_get_unix_fd_value (connection->outgoing_counter); 06229 CONNECTION_UNLOCK (connection); 06230 return res; 06231 } 06232
1.7.5.1