|
D-Bus 1.4.12
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-connection.c DBusConnection object 00003 * 00004 * Copyright (C) 2002-2006 Red Hat Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 * 00022 */ 00023 00024 #include <config.h> 00025 #include "dbus-shared.h" 00026 #include "dbus-connection.h" 00027 #include "dbus-list.h" 00028 #include "dbus-timeout.h" 00029 #include "dbus-transport.h" 00030 #include "dbus-watch.h" 00031 #include "dbus-connection-internal.h" 00032 #include "dbus-pending-call-internal.h" 00033 #include "dbus-list.h" 00034 #include "dbus-hash.h" 00035 #include "dbus-message-internal.h" 00036 #include "dbus-message-private.h" 00037 #include "dbus-threads.h" 00038 #include "dbus-protocol.h" 00039 #include "dbus-dataslot.h" 00040 #include "dbus-string.h" 00041 #include "dbus-pending-call.h" 00042 #include "dbus-object-tree.h" 00043 #include "dbus-threads-internal.h" 00044 #include "dbus-bus.h" 00045 #include "dbus-marshal-basic.h" 00046 00047 #ifdef DBUS_DISABLE_CHECKS 00048 #define TOOK_LOCK_CHECK(connection) 00049 #define RELEASING_LOCK_CHECK(connection) 00050 #define HAVE_LOCK_CHECK(connection) 00051 #else 00052 #define TOOK_LOCK_CHECK(connection) do { \ 00053 _dbus_assert (!(connection)->have_connection_lock); \ 00054 (connection)->have_connection_lock = TRUE; \ 00055 } while (0) 00056 #define RELEASING_LOCK_CHECK(connection) do { \ 00057 _dbus_assert ((connection)->have_connection_lock); \ 00058 (connection)->have_connection_lock = FALSE; \ 00059 } while (0) 00060 #define HAVE_LOCK_CHECK(connection) _dbus_assert ((connection)->have_connection_lock) 00061 /* A "DO_NOT_HAVE_LOCK_CHECK" is impossible since we need the lock to check the flag */ 00062 #endif 00063 00064 #define TRACE_LOCKS 1 00065 00066 #define CONNECTION_LOCK(connection) do { \ 00067 if (TRACE_LOCKS) { _dbus_verbose ("LOCK\n"); } \ 00068 _dbus_mutex_lock ((connection)->mutex); \ 00069 TOOK_LOCK_CHECK (connection); \ 00070 } while (0) 00071 00072 #define CONNECTION_UNLOCK(connection) do { \ 00073 if (TRACE_LOCKS) { _dbus_verbose ("UNLOCK\n"); } \ 00074 RELEASING_LOCK_CHECK (connection); \ 00075 _dbus_mutex_unlock ((connection)->mutex); \ 00076 } while (0) 00077 00078 #define SLOTS_LOCK(connection) do { \ 00079 _dbus_mutex_lock ((connection)->slot_mutex); \ 00080 } while (0) 00081 00082 #define SLOTS_UNLOCK(connection) do { \ 00083 _dbus_mutex_unlock ((connection)->slot_mutex); \ 00084 } while (0) 00085 00086 #define DISPATCH_STATUS_NAME(s) \ 00087 ((s) == DBUS_DISPATCH_COMPLETE ? "complete" : \ 00088 (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \ 00089 (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" : \ 00090 "???") 00091 00212 typedef struct DBusMessageFilter DBusMessageFilter; 00213 00217 struct DBusMessageFilter 00218 { 00219 DBusAtomic refcount; 00220 DBusHandleMessageFunction function; 00221 void *user_data; 00222 DBusFreeFunction free_user_data_function; 00223 }; 00224 00225 00229 struct DBusPreallocatedSend 00230 { 00231 DBusConnection *connection; 00232 DBusList *queue_link; 00233 DBusList *counter_link; 00234 }; 00235 00236 #if HAVE_DECL_MSG_NOSIGNAL 00237 static dbus_bool_t _dbus_modify_sigpipe = FALSE; 00238 #else 00239 static dbus_bool_t _dbus_modify_sigpipe = TRUE; 00240 #endif 00241 00245 struct DBusConnection 00246 { 00247 DBusAtomic refcount; 00249 DBusMutex *mutex; 00251 DBusMutex *dispatch_mutex; 00252 DBusCondVar *dispatch_cond; 00253 DBusMutex *io_path_mutex; 00254 DBusCondVar *io_path_cond; 00256 DBusList *outgoing_messages; 00257 DBusList *incoming_messages; 00259 DBusMessage *message_borrowed; 00263 int n_outgoing; 00264 int n_incoming; 00266 DBusCounter *outgoing_counter; 00268 DBusTransport *transport; 00269 DBusWatchList *watches; 00270 DBusTimeoutList *timeouts; 00272 DBusList *filter_list; 00274 DBusMutex *slot_mutex; 00275 DBusDataSlotList slot_list; 00277 DBusHashTable *pending_replies; 00279 dbus_uint32_t client_serial; 00280 DBusList *disconnect_message_link; 00282 DBusWakeupMainFunction wakeup_main_function; 00283 void *wakeup_main_data; 00284 DBusFreeFunction free_wakeup_main_data; 00286 DBusDispatchStatusFunction dispatch_status_function; 00287 void *dispatch_status_data; 00288 DBusFreeFunction free_dispatch_status_data; 00290 DBusDispatchStatus last_dispatch_status; 00292 DBusList *link_cache; 00295 DBusObjectTree *objects; 00297 char *server_guid; 00299 /* These two MUST be bools and not bitfields, because they are protected by a separate lock 00300 * from connection->mutex and all bitfields in a word have to be read/written together. 00301 * So you can't have a different lock for different bitfields in the same word. 00302 */ 00303 dbus_bool_t dispatch_acquired; 00304 dbus_bool_t io_path_acquired; 00306 unsigned int shareable : 1; 00308 unsigned int exit_on_disconnect : 1; 00310 unsigned int route_peer_messages : 1; 00312 unsigned int disconnected_message_arrived : 1; 00316 unsigned int disconnected_message_processed : 1; 00320 #ifndef DBUS_DISABLE_CHECKS 00321 unsigned int have_connection_lock : 1; 00322 #endif 00323 00324 #ifndef DBUS_DISABLE_CHECKS 00325 int generation; 00326 #endif 00327 }; 00328 00329 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection); 00330 static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection, 00331 DBusDispatchStatus new_status); 00332 static void _dbus_connection_last_unref (DBusConnection *connection); 00333 static void _dbus_connection_acquire_dispatch (DBusConnection *connection); 00334 static void _dbus_connection_release_dispatch (DBusConnection *connection); 00335 static DBusDispatchStatus _dbus_connection_flush_unlocked (DBusConnection *connection); 00336 static void _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection); 00337 static dbus_bool_t _dbus_connection_get_is_connected_unlocked (DBusConnection *connection); 00338 static dbus_bool_t _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection, 00339 dbus_uint32_t client_serial); 00340 00341 static DBusMessageFilter * 00342 _dbus_message_filter_ref (DBusMessageFilter *filter) 00343 { 00344 _dbus_assert (filter->refcount.value > 0); 00345 _dbus_atomic_inc (&filter->refcount); 00346 00347 return filter; 00348 } 00349 00350 static void 00351 _dbus_message_filter_unref (DBusMessageFilter *filter) 00352 { 00353 _dbus_assert (filter->refcount.value > 0); 00354 00355 if (_dbus_atomic_dec (&filter->refcount) == 1) 00356 { 00357 if (filter->free_user_data_function) 00358 (* filter->free_user_data_function) (filter->user_data); 00359 00360 dbus_free (filter); 00361 } 00362 } 00363 00369 void 00370 _dbus_connection_lock (DBusConnection *connection) 00371 { 00372 CONNECTION_LOCK (connection); 00373 } 00374 00380 void 00381 _dbus_connection_unlock (DBusConnection *connection) 00382 { 00383 CONNECTION_UNLOCK (connection); 00384 } 00385 00393 static void 00394 _dbus_connection_wakeup_mainloop (DBusConnection *connection) 00395 { 00396 if (connection->wakeup_main_function) 00397 (*connection->wakeup_main_function) (connection->wakeup_main_data); 00398 } 00399 00400 #ifdef DBUS_BUILD_TESTS 00401 /* For now this function isn't used */ 00411 dbus_bool_t 00412 _dbus_connection_queue_received_message (DBusConnection *connection, 00413 DBusMessage *message) 00414 { 00415 DBusList *link; 00416 00417 link = _dbus_list_alloc_link (message); 00418 if (link == NULL) 00419 return FALSE; 00420 00421 dbus_message_ref (message); 00422 _dbus_connection_queue_received_message_link (connection, link); 00423 00424 return TRUE; 00425 } 00426 00439 void 00440 _dbus_connection_test_get_locks (DBusConnection *connection, 00441 DBusMutex **mutex_loc, 00442 DBusMutex **dispatch_mutex_loc, 00443 DBusMutex **io_path_mutex_loc, 00444 DBusCondVar **dispatch_cond_loc, 00445 DBusCondVar **io_path_cond_loc) 00446 { 00447 *mutex_loc = connection->mutex; 00448 *dispatch_mutex_loc = connection->dispatch_mutex; 00449 *io_path_mutex_loc = connection->io_path_mutex; 00450 *dispatch_cond_loc = connection->dispatch_cond; 00451 *io_path_cond_loc = connection->io_path_cond; 00452 } 00453 #endif 00454 00463 void 00464 _dbus_connection_queue_received_message_link (DBusConnection *connection, 00465 DBusList *link) 00466 { 00467 DBusPendingCall *pending; 00468 dbus_uint32_t reply_serial; 00469 DBusMessage *message; 00470 00471 _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport)); 00472 00473 _dbus_list_append_link (&connection->incoming_messages, 00474 link); 00475 message = link->data; 00476 00477 /* If this is a reply we're waiting on, remove timeout for it */ 00478 reply_serial = dbus_message_get_reply_serial (message); 00479 if (reply_serial != 0) 00480 { 00481 pending = _dbus_hash_table_lookup_int (connection->pending_replies, 00482 reply_serial); 00483 if (pending != NULL) 00484 { 00485 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 00486 _dbus_connection_remove_timeout_unlocked (connection, 00487 _dbus_pending_call_get_timeout_unlocked (pending)); 00488 00489 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 00490 } 00491 } 00492 00493 00494 00495 connection->n_incoming += 1; 00496 00497 _dbus_connection_wakeup_mainloop (connection); 00498 00499 _dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n", 00500 message, 00501 dbus_message_type_to_string (dbus_message_get_type (message)), 00502 dbus_message_get_path (message) ? 00503 dbus_message_get_path (message) : 00504 "no path", 00505 dbus_message_get_interface (message) ? 00506 dbus_message_get_interface (message) : 00507 "no interface", 00508 dbus_message_get_member (message) ? 00509 dbus_message_get_member (message) : 00510 "no member", 00511 dbus_message_get_signature (message), 00512 dbus_message_get_reply_serial (message), 00513 connection, 00514 connection->n_incoming);} 00515 00524 void 00525 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection, 00526 DBusList *link) 00527 { 00528 HAVE_LOCK_CHECK (connection); 00529 00530 _dbus_list_append_link (&connection->incoming_messages, link); 00531 00532 connection->n_incoming += 1; 00533 00534 _dbus_connection_wakeup_mainloop (connection); 00535 00536 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n", 00537 link->data, connection, connection->n_incoming); 00538 } 00539 00540 00548 dbus_bool_t 00549 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection) 00550 { 00551 HAVE_LOCK_CHECK (connection); 00552 return connection->outgoing_messages != NULL; 00553 } 00554 00564 dbus_bool_t 00565 dbus_connection_has_messages_to_send (DBusConnection *connection) 00566 { 00567 dbus_bool_t v; 00568 00569 _dbus_return_val_if_fail (connection != NULL, FALSE); 00570 00571 CONNECTION_LOCK (connection); 00572 v = _dbus_connection_has_messages_to_send_unlocked (connection); 00573 CONNECTION_UNLOCK (connection); 00574 00575 return v; 00576 } 00577 00585 DBusMessage* 00586 _dbus_connection_get_message_to_send (DBusConnection *connection) 00587 { 00588 HAVE_LOCK_CHECK (connection); 00589 00590 return _dbus_list_get_last (&connection->outgoing_messages); 00591 } 00592 00601 void 00602 _dbus_connection_message_sent (DBusConnection *connection, 00603 DBusMessage *message) 00604 { 00605 DBusList *link; 00606 00607 HAVE_LOCK_CHECK (connection); 00608 00609 /* This can be called before we even complete authentication, since 00610 * it's called on disconnect to clean up the outgoing queue. 00611 * It's also called as we successfully send each message. 00612 */ 00613 00614 link = _dbus_list_get_last_link (&connection->outgoing_messages); 00615 _dbus_assert (link != NULL); 00616 _dbus_assert (link->data == message); 00617 00618 /* Save this link in the link cache */ 00619 _dbus_list_unlink (&connection->outgoing_messages, 00620 link); 00621 _dbus_list_prepend_link (&connection->link_cache, link); 00622 00623 connection->n_outgoing -= 1; 00624 00625 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n", 00626 message, 00627 dbus_message_type_to_string (dbus_message_get_type (message)), 00628 dbus_message_get_path (message) ? 00629 dbus_message_get_path (message) : 00630 "no path", 00631 dbus_message_get_interface (message) ? 00632 dbus_message_get_interface (message) : 00633 "no interface", 00634 dbus_message_get_member (message) ? 00635 dbus_message_get_member (message) : 00636 "no member", 00637 dbus_message_get_signature (message), 00638 connection, connection->n_outgoing); 00639 00640 /* Save this link in the link cache also */ 00641 _dbus_message_remove_counter (message, connection->outgoing_counter, 00642 &link); 00643 _dbus_list_prepend_link (&connection->link_cache, link); 00644 00645 dbus_message_unref (message); 00646 } 00647 00649 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list, 00650 DBusWatch *watch); 00652 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list, 00653 DBusWatch *watch); 00655 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list, 00656 DBusWatch *watch, 00657 dbus_bool_t enabled); 00658 00659 static dbus_bool_t 00660 protected_change_watch (DBusConnection *connection, 00661 DBusWatch *watch, 00662 DBusWatchAddFunction add_function, 00663 DBusWatchRemoveFunction remove_function, 00664 DBusWatchToggleFunction toggle_function, 00665 dbus_bool_t enabled) 00666 { 00667 dbus_bool_t retval; 00668 00669 HAVE_LOCK_CHECK (connection); 00670 00671 /* The original purpose of protected_change_watch() was to hold a 00672 * ref on the connection while dropping the connection lock, then 00673 * calling out to the app. This was a broken hack that did not 00674 * work, since the connection was in a hosed state (no WatchList 00675 * field) while calling out. 00676 * 00677 * So for now we'll just keep the lock while calling out. This means 00678 * apps are not allowed to call DBusConnection methods inside a 00679 * watch function or they will deadlock. 00680 * 00681 * The "real fix" is to use the _and_unlock() pattern found 00682 * elsewhere in the code, to defer calling out to the app until 00683 * we're about to drop locks and return flow of control to the app 00684 * anyway. 00685 * 00686 * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144 00687 */ 00688 00689 if (connection->watches) 00690 { 00691 if (add_function) 00692 retval = (* add_function) (connection->watches, watch); 00693 else if (remove_function) 00694 { 00695 retval = TRUE; 00696 (* remove_function) (connection->watches, watch); 00697 } 00698 else 00699 { 00700 retval = TRUE; 00701 (* toggle_function) (connection->watches, watch, enabled); 00702 } 00703 return retval; 00704 } 00705 else 00706 return FALSE; 00707 } 00708 00709 00721 dbus_bool_t 00722 _dbus_connection_add_watch_unlocked (DBusConnection *connection, 00723 DBusWatch *watch) 00724 { 00725 return protected_change_watch (connection, watch, 00726 _dbus_watch_list_add_watch, 00727 NULL, NULL, FALSE); 00728 } 00729 00739 void 00740 _dbus_connection_remove_watch_unlocked (DBusConnection *connection, 00741 DBusWatch *watch) 00742 { 00743 protected_change_watch (connection, watch, 00744 NULL, 00745 _dbus_watch_list_remove_watch, 00746 NULL, FALSE); 00747 } 00748 00759 void 00760 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection, 00761 DBusWatch *watch, 00762 dbus_bool_t enabled) 00763 { 00764 _dbus_assert (watch != NULL); 00765 00766 protected_change_watch (connection, watch, 00767 NULL, NULL, 00768 _dbus_watch_list_toggle_watch, 00769 enabled); 00770 } 00771 00773 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list, 00774 DBusTimeout *timeout); 00776 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list, 00777 DBusTimeout *timeout); 00779 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list, 00780 DBusTimeout *timeout, 00781 dbus_bool_t enabled); 00782 00783 static dbus_bool_t 00784 protected_change_timeout (DBusConnection *connection, 00785 DBusTimeout *timeout, 00786 DBusTimeoutAddFunction add_function, 00787 DBusTimeoutRemoveFunction remove_function, 00788 DBusTimeoutToggleFunction toggle_function, 00789 dbus_bool_t enabled) 00790 { 00791 dbus_bool_t retval; 00792 00793 HAVE_LOCK_CHECK (connection); 00794 00795 /* The original purpose of protected_change_timeout() was to hold a 00796 * ref on the connection while dropping the connection lock, then 00797 * calling out to the app. This was a broken hack that did not 00798 * work, since the connection was in a hosed state (no TimeoutList 00799 * field) while calling out. 00800 * 00801 * So for now we'll just keep the lock while calling out. This means 00802 * apps are not allowed to call DBusConnection methods inside a 00803 * timeout function or they will deadlock. 00804 * 00805 * The "real fix" is to use the _and_unlock() pattern found 00806 * elsewhere in the code, to defer calling out to the app until 00807 * we're about to drop locks and return flow of control to the app 00808 * anyway. 00809 * 00810 * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144 00811 */ 00812 00813 if (connection->timeouts) 00814 { 00815 if (add_function) 00816 retval = (* add_function) (connection->timeouts, timeout); 00817 else if (remove_function) 00818 { 00819 retval = TRUE; 00820 (* remove_function) (connection->timeouts, timeout); 00821 } 00822 else 00823 { 00824 retval = TRUE; 00825 (* toggle_function) (connection->timeouts, timeout, enabled); 00826 } 00827 return retval; 00828 } 00829 else 00830 return FALSE; 00831 } 00832 00845 dbus_bool_t 00846 _dbus_connection_add_timeout_unlocked (DBusConnection *connection, 00847 DBusTimeout *timeout) 00848 { 00849 return protected_change_timeout (connection, timeout, 00850 _dbus_timeout_list_add_timeout, 00851 NULL, NULL, FALSE); 00852 } 00853 00863 void 00864 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection, 00865 DBusTimeout *timeout) 00866 { 00867 protected_change_timeout (connection, timeout, 00868 NULL, 00869 _dbus_timeout_list_remove_timeout, 00870 NULL, FALSE); 00871 } 00872 00883 void 00884 _dbus_connection_toggle_timeout_unlocked (DBusConnection *connection, 00885 DBusTimeout *timeout, 00886 dbus_bool_t enabled) 00887 { 00888 protected_change_timeout (connection, timeout, 00889 NULL, NULL, 00890 _dbus_timeout_list_toggle_timeout, 00891 enabled); 00892 } 00893 00894 static dbus_bool_t 00895 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection, 00896 DBusPendingCall *pending) 00897 { 00898 dbus_uint32_t reply_serial; 00899 DBusTimeout *timeout; 00900 00901 HAVE_LOCK_CHECK (connection); 00902 00903 reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending); 00904 00905 _dbus_assert (reply_serial != 0); 00906 00907 timeout = _dbus_pending_call_get_timeout_unlocked (pending); 00908 00909 if (timeout) 00910 { 00911 if (!_dbus_connection_add_timeout_unlocked (connection, timeout)) 00912 return FALSE; 00913 00914 if (!_dbus_hash_table_insert_int (connection->pending_replies, 00915 reply_serial, 00916 pending)) 00917 { 00918 _dbus_connection_remove_timeout_unlocked (connection, timeout); 00919 00920 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 00921 HAVE_LOCK_CHECK (connection); 00922 return FALSE; 00923 } 00924 00925 _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE); 00926 } 00927 else 00928 { 00929 if (!_dbus_hash_table_insert_int (connection->pending_replies, 00930 reply_serial, 00931 pending)) 00932 { 00933 HAVE_LOCK_CHECK (connection); 00934 return FALSE; 00935 } 00936 } 00937 00938 _dbus_pending_call_ref_unlocked (pending); 00939 00940 HAVE_LOCK_CHECK (connection); 00941 00942 return TRUE; 00943 } 00944 00945 static void 00946 free_pending_call_on_hash_removal (void *data) 00947 { 00948 DBusPendingCall *pending; 00949 DBusConnection *connection; 00950 00951 if (data == NULL) 00952 return; 00953 00954 pending = data; 00955 00956 connection = _dbus_pending_call_get_connection_unlocked (pending); 00957 00958 HAVE_LOCK_CHECK (connection); 00959 00960 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 00961 { 00962 _dbus_connection_remove_timeout_unlocked (connection, 00963 _dbus_pending_call_get_timeout_unlocked (pending)); 00964 00965 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 00966 } 00967 00968 /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock 00969 * here, but the pending call finalizer could in principle call out to 00970 * application code so we pretty much have to... some larger code reorg 00971 * might be needed. 00972 */ 00973 _dbus_connection_ref_unlocked (connection); 00974 _dbus_pending_call_unref_and_unlock (pending); 00975 CONNECTION_LOCK (connection); 00976 _dbus_connection_unref_unlocked (connection); 00977 } 00978 00979 static void 00980 _dbus_connection_detach_pending_call_unlocked (DBusConnection *connection, 00981 DBusPendingCall *pending) 00982 { 00983 /* This ends up unlocking to call the pending call finalizer, which is unexpected to 00984 * say the least. 00985 */ 00986 _dbus_hash_table_remove_int (connection->pending_replies, 00987 _dbus_pending_call_get_reply_serial_unlocked (pending)); 00988 } 00989 00990 static void 00991 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection, 00992 DBusPendingCall *pending) 00993 { 00994 /* The idea here is to avoid finalizing the pending call 00995 * with the lock held, since there's a destroy notifier 00996 * in pending call that goes out to application code. 00997 * 00998 * There's an extra unlock inside the hash table 00999 * "free pending call" function FIXME... 01000 */ 01001 _dbus_pending_call_ref_unlocked (pending); 01002 _dbus_hash_table_remove_int (connection->pending_replies, 01003 _dbus_pending_call_get_reply_serial_unlocked (pending)); 01004 01005 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 01006 _dbus_connection_remove_timeout_unlocked (connection, 01007 _dbus_pending_call_get_timeout_unlocked (pending)); 01008 01009 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 01010 01011 _dbus_pending_call_unref_and_unlock (pending); 01012 } 01013 01022 void 01023 _dbus_connection_remove_pending_call (DBusConnection *connection, 01024 DBusPendingCall *pending) 01025 { 01026 CONNECTION_LOCK (connection); 01027 _dbus_connection_detach_pending_call_and_unlock (connection, pending); 01028 } 01029 01039 static dbus_bool_t 01040 _dbus_connection_acquire_io_path (DBusConnection *connection, 01041 int timeout_milliseconds) 01042 { 01043 dbus_bool_t we_acquired; 01044 01045 HAVE_LOCK_CHECK (connection); 01046 01047 /* We don't want the connection to vanish */ 01048 _dbus_connection_ref_unlocked (connection); 01049 01050 /* We will only touch io_path_acquired which is protected by our mutex */ 01051 CONNECTION_UNLOCK (connection); 01052 01053 _dbus_verbose ("locking io_path_mutex\n"); 01054 _dbus_mutex_lock (connection->io_path_mutex); 01055 01056 _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n", 01057 connection->io_path_acquired, timeout_milliseconds); 01058 01059 we_acquired = FALSE; 01060 01061 if (connection->io_path_acquired) 01062 { 01063 if (timeout_milliseconds != -1) 01064 { 01065 _dbus_verbose ("waiting %d for IO path to be acquirable\n", 01066 timeout_milliseconds); 01067 01068 if (!_dbus_condvar_wait_timeout (connection->io_path_cond, 01069 connection->io_path_mutex, 01070 timeout_milliseconds)) 01071 { 01072 /* We timed out before anyone signaled. */ 01073 /* (writing the loop to handle the !timedout case by 01074 * waiting longer if needed is a pain since dbus 01075 * wraps pthread_cond_timedwait to take a relative 01076 * time instead of absolute, something kind of stupid 01077 * on our part. for now it doesn't matter, we will just 01078 * end up back here eventually.) 01079 */ 01080 } 01081 } 01082 else 01083 { 01084 while (connection->io_path_acquired) 01085 { 01086 _dbus_verbose ("waiting for IO path to be acquirable\n"); 01087 _dbus_condvar_wait (connection->io_path_cond, 01088 connection->io_path_mutex); 01089 } 01090 } 01091 } 01092 01093 if (!connection->io_path_acquired) 01094 { 01095 we_acquired = TRUE; 01096 connection->io_path_acquired = TRUE; 01097 } 01098 01099 _dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n", 01100 connection->io_path_acquired, we_acquired); 01101 01102 _dbus_verbose ("unlocking io_path_mutex\n"); 01103 _dbus_mutex_unlock (connection->io_path_mutex); 01104 01105 CONNECTION_LOCK (connection); 01106 01107 HAVE_LOCK_CHECK (connection); 01108 01109 _dbus_connection_unref_unlocked (connection); 01110 01111 return we_acquired; 01112 } 01113 01121 static void 01122 _dbus_connection_release_io_path (DBusConnection *connection) 01123 { 01124 HAVE_LOCK_CHECK (connection); 01125 01126 _dbus_verbose ("locking io_path_mutex\n"); 01127 _dbus_mutex_lock (connection->io_path_mutex); 01128 01129 _dbus_assert (connection->io_path_acquired); 01130 01131 _dbus_verbose ("start connection->io_path_acquired = %d\n", 01132 connection->io_path_acquired); 01133 01134 connection->io_path_acquired = FALSE; 01135 _dbus_condvar_wake_one (connection->io_path_cond); 01136 01137 _dbus_verbose ("unlocking io_path_mutex\n"); 01138 _dbus_mutex_unlock (connection->io_path_mutex); 01139 } 01140 01176 void 01177 _dbus_connection_do_iteration_unlocked (DBusConnection *connection, 01178 DBusPendingCall *pending, 01179 unsigned int flags, 01180 int timeout_milliseconds) 01181 { 01182 _dbus_verbose ("start\n"); 01183 01184 HAVE_LOCK_CHECK (connection); 01185 01186 if (connection->n_outgoing == 0) 01187 flags &= ~DBUS_ITERATION_DO_WRITING; 01188 01189 if (_dbus_connection_acquire_io_path (connection, 01190 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0)) 01191 { 01192 HAVE_LOCK_CHECK (connection); 01193 01194 if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending)) 01195 { 01196 _dbus_verbose ("pending call completed while acquiring I/O path"); 01197 } 01198 else if ( (pending != NULL) && 01199 _dbus_connection_peek_for_reply_unlocked (connection, 01200 _dbus_pending_call_get_reply_serial_unlocked (pending))) 01201 { 01202 _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)"); 01203 } 01204 else 01205 { 01206 _dbus_transport_do_iteration (connection->transport, 01207 flags, timeout_milliseconds); 01208 } 01209 01210 _dbus_connection_release_io_path (connection); 01211 } 01212 01213 HAVE_LOCK_CHECK (connection); 01214 01215 _dbus_verbose ("end\n"); 01216 } 01217 01227 DBusConnection* 01228 _dbus_connection_new_for_transport (DBusTransport *transport) 01229 { 01230 DBusConnection *connection; 01231 DBusWatchList *watch_list; 01232 DBusTimeoutList *timeout_list; 01233 DBusHashTable *pending_replies; 01234 DBusList *disconnect_link; 01235 DBusMessage *disconnect_message; 01236 DBusCounter *outgoing_counter; 01237 DBusObjectTree *objects; 01238 01239 watch_list = NULL; 01240 connection = NULL; 01241 pending_replies = NULL; 01242 timeout_list = NULL; 01243 disconnect_link = NULL; 01244 disconnect_message = NULL; 01245 outgoing_counter = NULL; 01246 objects = NULL; 01247 01248 watch_list = _dbus_watch_list_new (); 01249 if (watch_list == NULL) 01250 goto error; 01251 01252 timeout_list = _dbus_timeout_list_new (); 01253 if (timeout_list == NULL) 01254 goto error; 01255 01256 pending_replies = 01257 _dbus_hash_table_new (DBUS_HASH_INT, 01258 NULL, 01259 (DBusFreeFunction)free_pending_call_on_hash_removal); 01260 if (pending_replies == NULL) 01261 goto error; 01262 01263 connection = dbus_new0 (DBusConnection, 1); 01264 if (connection == NULL) 01265 goto error; 01266 01267 _dbus_mutex_new_at_location (&connection->mutex); 01268 if (connection->mutex == NULL) 01269 goto error; 01270 01271 _dbus_mutex_new_at_location (&connection->io_path_mutex); 01272 if (connection->io_path_mutex == NULL) 01273 goto error; 01274 01275 _dbus_mutex_new_at_location (&connection->dispatch_mutex); 01276 if (connection->dispatch_mutex == NULL) 01277 goto error; 01278 01279 _dbus_condvar_new_at_location (&connection->dispatch_cond); 01280 if (connection->dispatch_cond == NULL) 01281 goto error; 01282 01283 _dbus_condvar_new_at_location (&connection->io_path_cond); 01284 if (connection->io_path_cond == NULL) 01285 goto error; 01286 01287 _dbus_mutex_new_at_location (&connection->slot_mutex); 01288 if (connection->slot_mutex == NULL) 01289 goto error; 01290 01291 disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL, 01292 DBUS_INTERFACE_LOCAL, 01293 "Disconnected"); 01294 01295 if (disconnect_message == NULL) 01296 goto error; 01297 01298 disconnect_link = _dbus_list_alloc_link (disconnect_message); 01299 if (disconnect_link == NULL) 01300 goto error; 01301 01302 outgoing_counter = _dbus_counter_new (); 01303 if (outgoing_counter == NULL) 01304 goto error; 01305 01306 objects = _dbus_object_tree_new (connection); 01307 if (objects == NULL) 01308 goto error; 01309 01310 if (_dbus_modify_sigpipe) 01311 _dbus_disable_sigpipe (); 01312 01313 connection->refcount.value = 1; 01314 connection->transport = transport; 01315 connection->watches = watch_list; 01316 connection->timeouts = timeout_list; 01317 connection->pending_replies = pending_replies; 01318 connection->outgoing_counter = outgoing_counter; 01319 connection->filter_list = NULL; 01320 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */ 01321 connection->objects = objects; 01322 connection->exit_on_disconnect = FALSE; 01323 connection->shareable = FALSE; 01324 connection->route_peer_messages = FALSE; 01325 connection->disconnected_message_arrived = FALSE; 01326 connection->disconnected_message_processed = FALSE; 01327 01328 #ifndef DBUS_DISABLE_CHECKS 01329 connection->generation = _dbus_current_generation; 01330 #endif 01331 01332 _dbus_data_slot_list_init (&connection->slot_list); 01333 01334 connection->client_serial = 1; 01335 01336 connection->disconnect_message_link = disconnect_link; 01337 01338 CONNECTION_LOCK (connection); 01339 01340 if (!_dbus_transport_set_connection (transport, connection)) 01341 { 01342 CONNECTION_UNLOCK (connection); 01343 01344 goto error; 01345 } 01346 01347 _dbus_transport_ref (transport); 01348 01349 CONNECTION_UNLOCK (connection); 01350 01351 return connection; 01352 01353 error: 01354 if (disconnect_message != NULL) 01355 dbus_message_unref (disconnect_message); 01356 01357 if (disconnect_link != NULL) 01358 _dbus_list_free_link (disconnect_link); 01359 01360 if (connection != NULL) 01361 { 01362 _dbus_condvar_free_at_location (&connection->io_path_cond); 01363 _dbus_condvar_free_at_location (&connection->dispatch_cond); 01364 _dbus_mutex_free_at_location (&connection->mutex); 01365 _dbus_mutex_free_at_location (&connection->io_path_mutex); 01366 _dbus_mutex_free_at_location (&connection->dispatch_mutex); 01367 _dbus_mutex_free_at_location (&connection->slot_mutex); 01368 dbus_free (connection); 01369 } 01370 if (pending_replies) 01371 _dbus_hash_table_unref (pending_replies); 01372 01373 if (watch_list) 01374 _dbus_watch_list_free (watch_list); 01375 01376 if (timeout_list) 01377 _dbus_timeout_list_free (timeout_list); 01378 01379 if (outgoing_counter) 01380 _dbus_counter_unref (outgoing_counter); 01381 01382 if (objects) 01383 _dbus_object_tree_unref (objects); 01384 01385 return NULL; 01386 } 01387 01395 DBusConnection * 01396 _dbus_connection_ref_unlocked (DBusConnection *connection) 01397 { 01398 _dbus_assert (connection != NULL); 01399 _dbus_assert (connection->generation == _dbus_current_generation); 01400 01401 HAVE_LOCK_CHECK (connection); 01402 01403 _dbus_atomic_inc (&connection->refcount); 01404 01405 return connection; 01406 } 01407 01414 void 01415 _dbus_connection_unref_unlocked (DBusConnection *connection) 01416 { 01417 dbus_bool_t last_unref; 01418 01419 HAVE_LOCK_CHECK (connection); 01420 01421 _dbus_assert (connection != NULL); 01422 01423 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1); 01424 01425 if (last_unref) 01426 _dbus_connection_last_unref (connection); 01427 } 01428 01429 static dbus_uint32_t 01430 _dbus_connection_get_next_client_serial (DBusConnection *connection) 01431 { 01432 dbus_uint32_t serial; 01433 01434 serial = connection->client_serial++; 01435 01436 if (connection->client_serial == 0) 01437 connection->client_serial = 1; 01438 01439 return serial; 01440 } 01441 01455 dbus_bool_t 01456 _dbus_connection_handle_watch (DBusWatch *watch, 01457 unsigned int condition, 01458 void *data) 01459 { 01460 DBusConnection *connection; 01461 dbus_bool_t retval; 01462 DBusDispatchStatus status; 01463 01464 connection = data; 01465 01466 _dbus_verbose ("start\n"); 01467 01468 CONNECTION_LOCK (connection); 01469 01470 if (!_dbus_connection_acquire_io_path (connection, 1)) 01471 { 01472 /* another thread is handling the message */ 01473 CONNECTION_UNLOCK (connection); 01474 return TRUE; 01475 } 01476 01477 HAVE_LOCK_CHECK (connection); 01478 retval = _dbus_transport_handle_watch (connection->transport, 01479 watch, condition); 01480 01481 _dbus_connection_release_io_path (connection); 01482 01483 HAVE_LOCK_CHECK (connection); 01484 01485 _dbus_verbose ("middle\n"); 01486 01487 status = _dbus_connection_get_dispatch_status_unlocked (connection); 01488 01489 /* this calls out to user code */ 01490 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 01491 01492 _dbus_verbose ("end\n"); 01493 01494 return retval; 01495 } 01496 01497 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections); 01498 static DBusHashTable *shared_connections = NULL; 01499 static DBusList *shared_connections_no_guid = NULL; 01500 01501 static void 01502 close_connection_on_shutdown (DBusConnection *connection) 01503 { 01504 DBusMessage *message; 01505 01506 dbus_connection_ref (connection); 01507 _dbus_connection_close_possibly_shared (connection); 01508 01509 /* Churn through to the Disconnected message */ 01510 while ((message = dbus_connection_pop_message (connection))) 01511 { 01512 dbus_message_unref (message); 01513 } 01514 dbus_connection_unref (connection); 01515 } 01516 01517 static void 01518 shared_connections_shutdown (void *data) 01519 { 01520 int n_entries; 01521 01522 _DBUS_LOCK (shared_connections); 01523 01524 /* This is a little bit unpleasant... better ideas? */ 01525 while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0) 01526 { 01527 DBusConnection *connection; 01528 DBusHashIter iter; 01529 01530 _dbus_hash_iter_init (shared_connections, &iter); 01531 _dbus_hash_iter_next (&iter); 01532 01533 connection = _dbus_hash_iter_get_value (&iter); 01534 01535 _DBUS_UNLOCK (shared_connections); 01536 close_connection_on_shutdown (connection); 01537 _DBUS_LOCK (shared_connections); 01538 01539 /* The connection should now be dead and not in our hash ... */ 01540 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries); 01541 } 01542 01543 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0); 01544 01545 _dbus_hash_table_unref (shared_connections); 01546 shared_connections = NULL; 01547 01548 if (shared_connections_no_guid != NULL) 01549 { 01550 DBusConnection *connection; 01551 connection = _dbus_list_pop_first (&shared_connections_no_guid); 01552 while (connection != NULL) 01553 { 01554 _DBUS_UNLOCK (shared_connections); 01555 close_connection_on_shutdown (connection); 01556 _DBUS_LOCK (shared_connections); 01557 connection = _dbus_list_pop_first (&shared_connections_no_guid); 01558 } 01559 } 01560 01561 shared_connections_no_guid = NULL; 01562 01563 _DBUS_UNLOCK (shared_connections); 01564 } 01565 01566 static dbus_bool_t 01567 connection_lookup_shared (DBusAddressEntry *entry, 01568 DBusConnection **result) 01569 { 01570 _dbus_verbose ("checking for existing connection\n"); 01571 01572 *result = NULL; 01573 01574 _DBUS_LOCK (shared_connections); 01575 01576 if (shared_connections == NULL) 01577 { 01578 _dbus_verbose ("creating shared_connections hash table\n"); 01579 01580 shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING, 01581 dbus_free, 01582 NULL); 01583 if (shared_connections == NULL) 01584 { 01585 _DBUS_UNLOCK (shared_connections); 01586 return FALSE; 01587 } 01588 01589 if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL)) 01590 { 01591 _dbus_hash_table_unref (shared_connections); 01592 shared_connections = NULL; 01593 _DBUS_UNLOCK (shared_connections); 01594 return FALSE; 01595 } 01596 01597 _dbus_verbose (" successfully created shared_connections\n"); 01598 01599 _DBUS_UNLOCK (shared_connections); 01600 return TRUE; /* no point looking up in the hash we just made */ 01601 } 01602 else 01603 { 01604 const char *guid; 01605 01606 guid = dbus_address_entry_get_value (entry, "guid"); 01607 01608 if (guid != NULL) 01609 { 01610 DBusConnection *connection; 01611 01612 connection = _dbus_hash_table_lookup_string (shared_connections, 01613 guid); 01614 01615 if (connection) 01616 { 01617 /* The DBusConnection can't be finalized without taking 01618 * the shared_connections lock to remove it from the 01619 * hash. So it's safe to ref the connection here. 01620 * However, it may be disconnected if the Disconnected 01621 * message hasn't been processed yet, in which case we 01622 * want to pretend it isn't in the hash and avoid 01623 * returning it. 01624 * 01625 * The idea is to avoid ever returning a disconnected connection 01626 * from dbus_connection_open(). We could just synchronously 01627 * drop our shared ref to the connection on connection disconnect, 01628 * and then assert here that the connection is connected, but 01629 * that causes reentrancy headaches. 01630 */ 01631 CONNECTION_LOCK (connection); 01632 if (_dbus_connection_get_is_connected_unlocked (connection)) 01633 { 01634 _dbus_connection_ref_unlocked (connection); 01635 *result = connection; 01636 _dbus_verbose ("looked up existing connection to server guid %s\n", 01637 guid); 01638 } 01639 else 01640 { 01641 _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n", 01642 guid); 01643 } 01644 CONNECTION_UNLOCK (connection); 01645 } 01646 } 01647 01648 _DBUS_UNLOCK (shared_connections); 01649 return TRUE; 01650 } 01651 } 01652 01653 static dbus_bool_t 01654 connection_record_shared_unlocked (DBusConnection *connection, 01655 const char *guid) 01656 { 01657 char *guid_key; 01658 char *guid_in_connection; 01659 01660 HAVE_LOCK_CHECK (connection); 01661 _dbus_assert (connection->server_guid == NULL); 01662 _dbus_assert (connection->shareable); 01663 01664 /* get a hard ref on this connection, even if 01665 * we won't in fact store it in the hash, we still 01666 * need to hold a ref on it until it's disconnected. 01667 */ 01668 _dbus_connection_ref_unlocked (connection); 01669 01670 if (guid == NULL) 01671 { 01672 _DBUS_LOCK (shared_connections); 01673 01674 if (!_dbus_list_prepend (&shared_connections_no_guid, connection)) 01675 { 01676 _DBUS_UNLOCK (shared_connections); 01677 return FALSE; 01678 } 01679 01680 _DBUS_UNLOCK (shared_connections); 01681 return TRUE; /* don't store in the hash */ 01682 } 01683 01684 /* A separate copy of the key is required in the hash table, because 01685 * we don't have a lock on the connection when we are doing a hash 01686 * lookup. 01687 */ 01688 01689 guid_key = _dbus_strdup (guid); 01690 if (guid_key == NULL) 01691 return FALSE; 01692 01693 guid_in_connection = _dbus_strdup (guid); 01694 if (guid_in_connection == NULL) 01695 { 01696 dbus_free (guid_key); 01697 return FALSE; 01698 } 01699 01700 _DBUS_LOCK (shared_connections); 01701 _dbus_assert (shared_connections != NULL); 01702 01703 if (!_dbus_hash_table_insert_string (shared_connections, 01704 guid_key, connection)) 01705 { 01706 dbus_free (guid_key); 01707 dbus_free (guid_in_connection); 01708 _DBUS_UNLOCK (shared_connections); 01709 return FALSE; 01710 } 01711 01712 connection->server_guid = guid_in_connection; 01713 01714 _dbus_verbose ("stored connection to %s to be shared\n", 01715 connection->server_guid); 01716 01717 _DBUS_UNLOCK (shared_connections); 01718 01719 _dbus_assert (connection->server_guid != NULL); 01720 01721 return TRUE; 01722 } 01723 01724 static void 01725 connection_forget_shared_unlocked (DBusConnection *connection) 01726 { 01727 HAVE_LOCK_CHECK (connection); 01728 01729 if (!connection->shareable) 01730 return; 01731 01732 _DBUS_LOCK (shared_connections); 01733 01734 if (connection->server_guid != NULL) 01735 { 01736 _dbus_verbose ("dropping connection to %s out of the shared table\n", 01737 connection->server_guid); 01738 01739 if (!_dbus_hash_table_remove_string (shared_connections, 01740 connection->server_guid)) 01741 _dbus_assert_not_reached ("connection was not in the shared table"); 01742 01743 dbus_free (connection->server_guid); 01744 connection->server_guid = NULL; 01745 } 01746 else 01747 { 01748 _dbus_list_remove (&shared_connections_no_guid, connection); 01749 } 01750 01751 _DBUS_UNLOCK (shared_connections); 01752 01753 /* remove our reference held on all shareable connections */ 01754 _dbus_connection_unref_unlocked (connection); 01755 } 01756 01757 static DBusConnection* 01758 connection_try_from_address_entry (DBusAddressEntry *entry, 01759 DBusError *error) 01760 { 01761 DBusTransport *transport; 01762 DBusConnection *connection; 01763 01764 transport = _dbus_transport_open (entry, error); 01765 01766 if (transport == NULL) 01767 { 01768 _DBUS_ASSERT_ERROR_IS_SET (error); 01769 return NULL; 01770 } 01771 01772 connection = _dbus_connection_new_for_transport (transport); 01773 01774 _dbus_transport_unref (transport); 01775 01776 if (connection == NULL) 01777 { 01778 _DBUS_SET_OOM (error); 01779 return NULL; 01780 } 01781 01782 #ifndef DBUS_DISABLE_CHECKS 01783 _dbus_assert (!connection->have_connection_lock); 01784 #endif 01785 return connection; 01786 } 01787 01788 /* 01789 * If the shared parameter is true, then any existing connection will 01790 * be used (and if a new connection is created, it will be available 01791 * for use by others). If the shared parameter is false, a new 01792 * connection will always be created, and the new connection will 01793 * never be returned to other callers. 01794 * 01795 * @param address the address 01796 * @param shared whether the connection is shared or private 01797 * @param error error return 01798 * @returns the connection or #NULL on error 01799 */ 01800 static DBusConnection* 01801 _dbus_connection_open_internal (const char *address, 01802 dbus_bool_t shared, 01803 DBusError *error) 01804 { 01805 DBusConnection *connection; 01806 DBusAddressEntry **entries; 01807 DBusError tmp_error = DBUS_ERROR_INIT; 01808 DBusError first_error = DBUS_ERROR_INIT; 01809 int len, i; 01810 01811 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01812 01813 _dbus_verbose ("opening %s connection to: %s\n", 01814 shared ? "shared" : "private", address); 01815 01816 if (!dbus_parse_address (address, &entries, &len, error)) 01817 return NULL; 01818 01819 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01820 01821 connection = NULL; 01822 01823 for (i = 0; i < len; i++) 01824 { 01825 if (shared) 01826 { 01827 if (!connection_lookup_shared (entries[i], &connection)) 01828 _DBUS_SET_OOM (&tmp_error); 01829 } 01830 01831 if (connection == NULL) 01832 { 01833 connection = connection_try_from_address_entry (entries[i], 01834 &tmp_error); 01835 01836 if (connection != NULL && shared) 01837 { 01838 const char *guid; 01839 01840 connection->shareable = TRUE; 01841 01842 /* guid may be NULL */ 01843 guid = dbus_address_entry_get_value (entries[i], "guid"); 01844 01845 CONNECTION_LOCK (connection); 01846 01847 if (!connection_record_shared_unlocked (connection, guid)) 01848 { 01849 _DBUS_SET_OOM (&tmp_error); 01850 _dbus_connection_close_possibly_shared_and_unlock (connection); 01851 dbus_connection_unref (connection); 01852 connection = NULL; 01853 } 01854 else 01855 CONNECTION_UNLOCK (connection); 01856 } 01857 } 01858 01859 if (connection) 01860 break; 01861 01862 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); 01863 01864 if (i == 0) 01865 dbus_move_error (&tmp_error, &first_error); 01866 else 01867 dbus_error_free (&tmp_error); 01868 } 01869 01870 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 01871 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error); 01872 01873 if (connection == NULL) 01874 { 01875 _DBUS_ASSERT_ERROR_IS_SET (&first_error); 01876 dbus_move_error (&first_error, error); 01877 } 01878 else 01879 dbus_error_free (&first_error); 01880 01881 dbus_address_entries_free (entries); 01882 return connection; 01883 } 01884 01893 void 01894 _dbus_connection_close_possibly_shared (DBusConnection *connection) 01895 { 01896 _dbus_assert (connection != NULL); 01897 _dbus_assert (connection->generation == _dbus_current_generation); 01898 01899 CONNECTION_LOCK (connection); 01900 _dbus_connection_close_possibly_shared_and_unlock (connection); 01901 } 01902 01903 static DBusPreallocatedSend* 01904 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection) 01905 { 01906 DBusPreallocatedSend *preallocated; 01907 01908 HAVE_LOCK_CHECK (connection); 01909 01910 _dbus_assert (connection != NULL); 01911 01912 preallocated = dbus_new (DBusPreallocatedSend, 1); 01913 if (preallocated == NULL) 01914 return NULL; 01915 01916 if (connection->link_cache != NULL) 01917 { 01918 preallocated->queue_link = 01919 _dbus_list_pop_first_link (&connection->link_cache); 01920 preallocated->queue_link->data = NULL; 01921 } 01922 else 01923 { 01924 preallocated->queue_link = _dbus_list_alloc_link (NULL); 01925 if (preallocated->queue_link == NULL) 01926 goto failed_0; 01927 } 01928 01929 if (connection->link_cache != NULL) 01930 { 01931 preallocated->counter_link = 01932 _dbus_list_pop_first_link (&connection->link_cache); 01933 preallocated->counter_link->data = connection->outgoing_counter; 01934 } 01935 else 01936 { 01937 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter); 01938 if (preallocated->counter_link == NULL) 01939 goto failed_1; 01940 } 01941 01942 _dbus_counter_ref (preallocated->counter_link->data); 01943 01944 preallocated->connection = connection; 01945 01946 return preallocated; 01947 01948 failed_1: 01949 _dbus_list_free_link (preallocated->queue_link); 01950 failed_0: 01951 dbus_free (preallocated); 01952 01953 return NULL; 01954 } 01955 01956 /* Called with lock held, does not update dispatch status */ 01957 static void 01958 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection, 01959 DBusPreallocatedSend *preallocated, 01960 DBusMessage *message, 01961 dbus_uint32_t *client_serial) 01962 { 01963 dbus_uint32_t serial; 01964 01965 preallocated->queue_link->data = message; 01966 _dbus_list_prepend_link (&connection->outgoing_messages, 01967 preallocated->queue_link); 01968 01969 _dbus_message_add_counter_link (message, 01970 preallocated->counter_link); 01971 01972 dbus_free (preallocated); 01973 preallocated = NULL; 01974 01975 dbus_message_ref (message); 01976 01977 connection->n_outgoing += 1; 01978 01979 _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n", 01980 message, 01981 dbus_message_type_to_string (dbus_message_get_type (message)), 01982 dbus_message_get_path (message) ? 01983 dbus_message_get_path (message) : 01984 "no path", 01985 dbus_message_get_interface (message) ? 01986 dbus_message_get_interface (message) : 01987 "no interface", 01988 dbus_message_get_member (message) ? 01989 dbus_message_get_member (message) : 01990 "no member", 01991 dbus_message_get_signature (message), 01992 dbus_message_get_destination (message) ? 01993 dbus_message_get_destination (message) : 01994 "null", 01995 connection, 01996 connection->n_outgoing); 01997 01998 if (dbus_message_get_serial (message) == 0) 01999 { 02000 serial = _dbus_connection_get_next_client_serial (connection); 02001 dbus_message_set_serial (message, serial); 02002 if (client_serial) 02003 *client_serial = serial; 02004 } 02005 else 02006 { 02007 if (client_serial) 02008 *client_serial = dbus_message_get_serial (message); 02009 } 02010 02011 _dbus_verbose ("Message %p serial is %u\n", 02012 message, dbus_message_get_serial (message)); 02013 02014 dbus_message_lock (message); 02015 02016 /* Now we need to run an iteration to hopefully just write the messages 02017 * out immediately, and otherwise get them queued up 02018 */ 02019 _dbus_connection_do_iteration_unlocked (connection, 02020 NULL, 02021 DBUS_ITERATION_DO_WRITING, 02022 -1); 02023 02024 /* If stuff is still queued up, be sure we wake up the main loop */ 02025 if (connection->n_outgoing > 0) 02026 _dbus_connection_wakeup_mainloop (connection); 02027 } 02028 02029 static void 02030 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection, 02031 DBusPreallocatedSend *preallocated, 02032 DBusMessage *message, 02033 dbus_uint32_t *client_serial) 02034 { 02035 DBusDispatchStatus status; 02036 02037 HAVE_LOCK_CHECK (connection); 02038 02039 _dbus_connection_send_preallocated_unlocked_no_update (connection, 02040 preallocated, 02041 message, client_serial); 02042 02043 _dbus_verbose ("middle\n"); 02044 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02045 02046 /* this calls out to user code */ 02047 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02048 } 02049 02059 dbus_bool_t 02060 _dbus_connection_send_and_unlock (DBusConnection *connection, 02061 DBusMessage *message, 02062 dbus_uint32_t *client_serial) 02063 { 02064 DBusPreallocatedSend *preallocated; 02065 02066 _dbus_assert (connection != NULL); 02067 _dbus_assert (message != NULL); 02068 02069 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 02070 if (preallocated == NULL) 02071 { 02072 CONNECTION_UNLOCK (connection); 02073 return FALSE; 02074 } 02075 02076 _dbus_connection_send_preallocated_and_unlock (connection, 02077 preallocated, 02078 message, 02079 client_serial); 02080 return TRUE; 02081 } 02082 02107 void 02108 _dbus_connection_close_if_only_one_ref (DBusConnection *connection) 02109 { 02110 dbus_int32_t tmp_refcount; 02111 02112 CONNECTION_LOCK (connection); 02113 02114 /* We increment and then decrement the refcount, because there is no 02115 * _dbus_atomic_get (mirroring the fact that there's no InterlockedGet 02116 * on Windows). */ 02117 _dbus_atomic_inc (&connection->refcount); 02118 tmp_refcount = _dbus_atomic_dec (&connection->refcount); 02119 02120 /* The caller should have one ref, and this function temporarily took 02121 * one more, which is reflected in this count even though we already 02122 * released it (relying on the caller's ref) due to _dbus_atomic_dec 02123 * semantics */ 02124 _dbus_assert (tmp_refcount >= 2); 02125 02126 if (tmp_refcount == 2) 02127 _dbus_connection_close_possibly_shared_and_unlock (connection); 02128 else 02129 CONNECTION_UNLOCK (connection); 02130 } 02131 02132 02142 static void 02143 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds) 02144 { 02145 if (timeout_milliseconds == -1) 02146 _dbus_sleep_milliseconds (1000); 02147 else if (timeout_milliseconds < 100) 02148 ; /* just busy loop */ 02149 else if (timeout_milliseconds <= 1000) 02150 _dbus_sleep_milliseconds (timeout_milliseconds / 3); 02151 else 02152 _dbus_sleep_milliseconds (1000); 02153 } 02154 02155 static DBusMessage * 02156 generate_local_error_message (dbus_uint32_t serial, 02157 char *error_name, 02158 char *error_msg) 02159 { 02160 DBusMessage *message; 02161 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR); 02162 if (!message) 02163 goto out; 02164 02165 if (!dbus_message_set_error_name (message, error_name)) 02166 { 02167 dbus_message_unref (message); 02168 message = NULL; 02169 goto out; 02170 } 02171 02172 dbus_message_set_no_reply (message, TRUE); 02173 02174 if (!dbus_message_set_reply_serial (message, 02175 serial)) 02176 { 02177 dbus_message_unref (message); 02178 message = NULL; 02179 goto out; 02180 } 02181 02182 if (error_msg != NULL) 02183 { 02184 DBusMessageIter iter; 02185 02186 dbus_message_iter_init_append (message, &iter); 02187 if (!dbus_message_iter_append_basic (&iter, 02188 DBUS_TYPE_STRING, 02189 &error_msg)) 02190 { 02191 dbus_message_unref (message); 02192 message = NULL; 02193 goto out; 02194 } 02195 } 02196 02197 out: 02198 return message; 02199 } 02200 02201 /* 02202 * Peek the incoming queue to see if we got reply for a specific serial 02203 */ 02204 static dbus_bool_t 02205 _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection, 02206 dbus_uint32_t client_serial) 02207 { 02208 DBusList *link; 02209 HAVE_LOCK_CHECK (connection); 02210 02211 link = _dbus_list_get_first_link (&connection->incoming_messages); 02212 02213 while (link != NULL) 02214 { 02215 DBusMessage *reply = link->data; 02216 02217 if (dbus_message_get_reply_serial (reply) == client_serial) 02218 { 02219 _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial); 02220 return TRUE; 02221 } 02222 link = _dbus_list_get_next_link (&connection->incoming_messages, link); 02223 } 02224 02225 return FALSE; 02226 } 02227 02228 /* This is slightly strange since we can pop a message here without 02229 * the dispatch lock. 02230 */ 02231 static DBusMessage* 02232 check_for_reply_unlocked (DBusConnection *connection, 02233 dbus_uint32_t client_serial) 02234 { 02235 DBusList *link; 02236 02237 HAVE_LOCK_CHECK (connection); 02238 02239 link = _dbus_list_get_first_link (&connection->incoming_messages); 02240 02241 while (link != NULL) 02242 { 02243 DBusMessage *reply = link->data; 02244 02245 if (dbus_message_get_reply_serial (reply) == client_serial) 02246 { 02247 _dbus_list_remove_link (&connection->incoming_messages, link); 02248 connection->n_incoming -= 1; 02249 return reply; 02250 } 02251 link = _dbus_list_get_next_link (&connection->incoming_messages, link); 02252 } 02253 02254 return NULL; 02255 } 02256 02257 static void 02258 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection) 02259 { 02260 /* We can't iterate over the hash in the normal way since we'll be 02261 * dropping the lock for each item. So we restart the 02262 * iter each time as we drain the hash table. 02263 */ 02264 02265 while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0) 02266 { 02267 DBusPendingCall *pending; 02268 DBusHashIter iter; 02269 02270 _dbus_hash_iter_init (connection->pending_replies, &iter); 02271 _dbus_hash_iter_next (&iter); 02272 02273 pending = _dbus_hash_iter_get_value (&iter); 02274 _dbus_pending_call_ref_unlocked (pending); 02275 02276 _dbus_pending_call_queue_timeout_error_unlocked (pending, 02277 connection); 02278 02279 if (_dbus_pending_call_is_timeout_added_unlocked (pending)) 02280 _dbus_connection_remove_timeout_unlocked (connection, 02281 _dbus_pending_call_get_timeout_unlocked (pending)); 02282 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE); 02283 _dbus_hash_iter_remove_entry (&iter); 02284 02285 _dbus_pending_call_unref_and_unlock (pending); 02286 CONNECTION_LOCK (connection); 02287 } 02288 HAVE_LOCK_CHECK (connection); 02289 } 02290 02291 static void 02292 complete_pending_call_and_unlock (DBusConnection *connection, 02293 DBusPendingCall *pending, 02294 DBusMessage *message) 02295 { 02296 _dbus_pending_call_set_reply_unlocked (pending, message); 02297 _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */ 02298 _dbus_connection_detach_pending_call_and_unlock (connection, pending); 02299 02300 /* Must be called unlocked since it invokes app callback */ 02301 _dbus_pending_call_complete (pending); 02302 dbus_pending_call_unref (pending); 02303 } 02304 02305 static dbus_bool_t 02306 check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection, 02307 DBusPendingCall *pending) 02308 { 02309 DBusMessage *reply; 02310 DBusDispatchStatus status; 02311 02312 reply = check_for_reply_unlocked (connection, 02313 _dbus_pending_call_get_reply_serial_unlocked (pending)); 02314 if (reply != NULL) 02315 { 02316 _dbus_verbose ("checked for reply\n"); 02317 02318 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n"); 02319 02320 complete_pending_call_and_unlock (connection, pending, reply); 02321 dbus_message_unref (reply); 02322 02323 CONNECTION_LOCK (connection); 02324 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02325 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02326 dbus_pending_call_unref (pending); 02327 02328 return TRUE; 02329 } 02330 02331 return FALSE; 02332 } 02333 02348 void 02349 _dbus_connection_block_pending_call (DBusPendingCall *pending) 02350 { 02351 long start_tv_sec, start_tv_usec; 02352 long tv_sec, tv_usec; 02353 DBusDispatchStatus status; 02354 DBusConnection *connection; 02355 dbus_uint32_t client_serial; 02356 DBusTimeout *timeout; 02357 int timeout_milliseconds, elapsed_milliseconds; 02358 02359 _dbus_assert (pending != NULL); 02360 02361 if (dbus_pending_call_get_completed (pending)) 02362 return; 02363 02364 dbus_pending_call_ref (pending); /* necessary because the call could be canceled */ 02365 02366 connection = _dbus_pending_call_get_connection_and_lock (pending); 02367 02368 /* Flush message queue - note, can affect dispatch status */ 02369 _dbus_connection_flush_unlocked (connection); 02370 02371 client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending); 02372 02373 /* note that timeout_milliseconds is limited to a smallish value 02374 * in _dbus_pending_call_new() so overflows aren't possible 02375 * below 02376 */ 02377 timeout = _dbus_pending_call_get_timeout_unlocked (pending); 02378 _dbus_get_current_time (&start_tv_sec, &start_tv_usec); 02379 if (timeout) 02380 { 02381 timeout_milliseconds = dbus_timeout_get_interval (timeout); 02382 02383 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n", 02384 timeout_milliseconds, 02385 client_serial, 02386 start_tv_sec, start_tv_usec); 02387 } 02388 else 02389 { 02390 timeout_milliseconds = -1; 02391 02392 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial); 02393 } 02394 02395 /* check to see if we already got the data off the socket */ 02396 /* from another blocked pending call */ 02397 if (check_for_reply_and_update_dispatch_unlocked (connection, pending)) 02398 return; 02399 02400 /* Now we wait... */ 02401 /* always block at least once as we know we don't have the reply yet */ 02402 _dbus_connection_do_iteration_unlocked (connection, 02403 pending, 02404 DBUS_ITERATION_DO_READING | 02405 DBUS_ITERATION_BLOCK, 02406 timeout_milliseconds); 02407 02408 recheck_status: 02409 02410 _dbus_verbose ("top of recheck\n"); 02411 02412 HAVE_LOCK_CHECK (connection); 02413 02414 /* queue messages and get status */ 02415 02416 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02417 02418 /* the get_completed() is in case a dispatch() while we were blocking 02419 * got the reply instead of us. 02420 */ 02421 if (_dbus_pending_call_get_completed_unlocked (pending)) 02422 { 02423 _dbus_verbose ("Pending call completed by dispatch\n"); 02424 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02425 dbus_pending_call_unref (pending); 02426 return; 02427 } 02428 02429 if (status == DBUS_DISPATCH_DATA_REMAINS) 02430 { 02431 if (check_for_reply_and_update_dispatch_unlocked (connection, pending)) 02432 return; 02433 } 02434 02435 _dbus_get_current_time (&tv_sec, &tv_usec); 02436 elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 + 02437 (tv_usec - start_tv_usec) / 1000; 02438 02439 if (!_dbus_connection_get_is_connected_unlocked (connection)) 02440 { 02441 DBusMessage *error_msg; 02442 02443 error_msg = generate_local_error_message (client_serial, 02444 DBUS_ERROR_DISCONNECTED, 02445 "Connection was disconnected before a reply was received"); 02446 02447 /* on OOM error_msg is set to NULL */ 02448 complete_pending_call_and_unlock (connection, pending, error_msg); 02449 dbus_pending_call_unref (pending); 02450 return; 02451 } 02452 else if (connection->disconnect_message_link == NULL) 02453 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n"); 02454 else if (timeout == NULL) 02455 { 02456 if (status == DBUS_DISPATCH_NEED_MEMORY) 02457 { 02458 /* Try sleeping a bit, as we aren't sure we need to block for reading, 02459 * we may already have a reply in the buffer and just can't process 02460 * it. 02461 */ 02462 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n"); 02463 02464 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds); 02465 } 02466 else 02467 { 02468 /* block again, we don't have the reply buffered yet. */ 02469 _dbus_connection_do_iteration_unlocked (connection, 02470 pending, 02471 DBUS_ITERATION_DO_READING | 02472 DBUS_ITERATION_BLOCK, 02473 timeout_milliseconds - elapsed_milliseconds); 02474 } 02475 02476 goto recheck_status; 02477 } 02478 else if (tv_sec < start_tv_sec) 02479 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n"); 02480 else if (elapsed_milliseconds < timeout_milliseconds) 02481 { 02482 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds); 02483 02484 if (status == DBUS_DISPATCH_NEED_MEMORY) 02485 { 02486 /* Try sleeping a bit, as we aren't sure we need to block for reading, 02487 * we may already have a reply in the buffer and just can't process 02488 * it. 02489 */ 02490 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n"); 02491 02492 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds); 02493 } 02494 else 02495 { 02496 /* block again, we don't have the reply buffered yet. */ 02497 _dbus_connection_do_iteration_unlocked (connection, 02498 NULL, 02499 DBUS_ITERATION_DO_READING | 02500 DBUS_ITERATION_BLOCK, 02501 timeout_milliseconds - elapsed_milliseconds); 02502 } 02503 02504 goto recheck_status; 02505 } 02506 02507 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n", 02508 elapsed_milliseconds); 02509 02510 _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending)); 02511 02512 /* unlock and call user code */ 02513 complete_pending_call_and_unlock (connection, pending, NULL); 02514 02515 /* update user code on dispatch status */ 02516 CONNECTION_LOCK (connection); 02517 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02518 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02519 dbus_pending_call_unref (pending); 02520 } 02521 02558 DBusConnection* 02559 dbus_connection_open (const char *address, 02560 DBusError *error) 02561 { 02562 DBusConnection *connection; 02563 02564 _dbus_return_val_if_fail (address != NULL, NULL); 02565 _dbus_return_val_if_error_is_set (error, NULL); 02566 02567 connection = _dbus_connection_open_internal (address, 02568 TRUE, 02569 error); 02570 02571 return connection; 02572 } 02573 02601 DBusConnection* 02602 dbus_connection_open_private (const char *address, 02603 DBusError *error) 02604 { 02605 DBusConnection *connection; 02606 02607 _dbus_return_val_if_fail (address != NULL, NULL); 02608 _dbus_return_val_if_error_is_set (error, NULL); 02609 02610 connection = _dbus_connection_open_internal (address, 02611 FALSE, 02612 error); 02613 02614 return connection; 02615 } 02616 02623 DBusConnection * 02624 dbus_connection_ref (DBusConnection *connection) 02625 { 02626 _dbus_return_val_if_fail (connection != NULL, NULL); 02627 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL); 02628 02629 _dbus_atomic_inc (&connection->refcount); 02630 02631 return connection; 02632 } 02633 02634 static void 02635 free_outgoing_message (void *element, 02636 void *data) 02637 { 02638 DBusMessage *message = element; 02639 DBusConnection *connection = data; 02640 02641 _dbus_message_remove_counter (message, 02642 connection->outgoing_counter, 02643 NULL); 02644 dbus_message_unref (message); 02645 } 02646 02647 /* This is run without the mutex held, but after the last reference 02648 * to the connection has been dropped we should have no thread-related 02649 * problems 02650 */ 02651 static void 02652 _dbus_connection_last_unref (DBusConnection *connection) 02653 { 02654 DBusList *link; 02655 02656 _dbus_verbose ("Finalizing connection %p\n", connection); 02657 02658 _dbus_assert (connection->refcount.value == 0); 02659 02660 /* You have to disconnect the connection before unref:ing it. Otherwise 02661 * you won't get the disconnected message. 02662 */ 02663 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport)); 02664 _dbus_assert (connection->server_guid == NULL); 02665 02666 /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */ 02667 _dbus_object_tree_free_all_unlocked (connection->objects); 02668 02669 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL); 02670 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL); 02671 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL); 02672 02673 _dbus_watch_list_free (connection->watches); 02674 connection->watches = NULL; 02675 02676 _dbus_timeout_list_free (connection->timeouts); 02677 connection->timeouts = NULL; 02678 02679 _dbus_data_slot_list_free (&connection->slot_list); 02680 02681 link = _dbus_list_get_first_link (&connection->filter_list); 02682 while (link != NULL) 02683 { 02684 DBusMessageFilter *filter = link->data; 02685 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link); 02686 02687 filter->function = NULL; 02688 _dbus_message_filter_unref (filter); /* calls app callback */ 02689 link->data = NULL; 02690 02691 link = next; 02692 } 02693 _dbus_list_clear (&connection->filter_list); 02694 02695 /* ---- Done with stuff that invokes application callbacks */ 02696 02697 _dbus_object_tree_unref (connection->objects); 02698 02699 _dbus_hash_table_unref (connection->pending_replies); 02700 connection->pending_replies = NULL; 02701 02702 _dbus_list_clear (&connection->filter_list); 02703 02704 _dbus_list_foreach (&connection->outgoing_messages, 02705 free_outgoing_message, 02706 connection); 02707 _dbus_list_clear (&connection->outgoing_messages); 02708 02709 _dbus_list_foreach (&connection->incoming_messages, 02710 (DBusForeachFunction) dbus_message_unref, 02711 NULL); 02712 _dbus_list_clear (&connection->incoming_messages); 02713 02714 _dbus_counter_unref (connection->outgoing_counter); 02715 02716 _dbus_transport_unref (connection->transport); 02717 02718 if (connection->disconnect_message_link) 02719 { 02720 DBusMessage *message = connection->disconnect_message_link->data; 02721 dbus_message_unref (message); 02722 _dbus_list_free_link (connection->disconnect_message_link); 02723 } 02724 02725 _dbus_list_clear (&connection->link_cache); 02726 02727 _dbus_condvar_free_at_location (&connection->dispatch_cond); 02728 _dbus_condvar_free_at_location (&connection->io_path_cond); 02729 02730 _dbus_mutex_free_at_location (&connection->io_path_mutex); 02731 _dbus_mutex_free_at_location (&connection->dispatch_mutex); 02732 02733 _dbus_mutex_free_at_location (&connection->slot_mutex); 02734 02735 _dbus_mutex_free_at_location (&connection->mutex); 02736 02737 dbus_free (connection); 02738 } 02739 02759 void 02760 dbus_connection_unref (DBusConnection *connection) 02761 { 02762 dbus_bool_t last_unref; 02763 02764 _dbus_return_if_fail (connection != NULL); 02765 _dbus_return_if_fail (connection->generation == _dbus_current_generation); 02766 02767 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1); 02768 02769 if (last_unref) 02770 { 02771 #ifndef DBUS_DISABLE_CHECKS 02772 if (_dbus_transport_get_is_connected (connection->transport)) 02773 { 02774 _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", 02775 connection->shareable ? 02776 "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" : 02777 "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n"); 02778 return; 02779 } 02780 #endif 02781 _dbus_connection_last_unref (connection); 02782 } 02783 } 02784 02785 /* 02786 * Note that the transport can disconnect itself (other end drops us) 02787 * and in that case this function never runs. So this function must 02788 * not do anything more than disconnect the transport and update the 02789 * dispatch status. 02790 * 02791 * If the transport self-disconnects, then we assume someone will 02792 * dispatch the connection to cause the dispatch status update. 02793 */ 02794 static void 02795 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection) 02796 { 02797 DBusDispatchStatus status; 02798 02799 HAVE_LOCK_CHECK (connection); 02800 02801 _dbus_verbose ("Disconnecting %p\n", connection); 02802 02803 /* We need to ref because update_dispatch_status_and_unlock will unref 02804 * the connection if it was shared and libdbus was the only remaining 02805 * refcount holder. 02806 */ 02807 _dbus_connection_ref_unlocked (connection); 02808 02809 _dbus_transport_disconnect (connection->transport); 02810 02811 /* This has the side effect of queuing the disconnect message link 02812 * (unless we don't have enough memory, possibly, so don't assert it). 02813 * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open 02814 * should never again return the newly-disconnected connection. 02815 * 02816 * However, we only unref the shared connection and exit_on_disconnect when 02817 * the disconnect message reaches the head of the message queue, 02818 * NOT when it's first queued. 02819 */ 02820 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02821 02822 /* This calls out to user code */ 02823 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02824 02825 /* Could also call out to user code */ 02826 dbus_connection_unref (connection); 02827 } 02828 02871 void 02872 dbus_connection_close (DBusConnection *connection) 02873 { 02874 _dbus_return_if_fail (connection != NULL); 02875 _dbus_return_if_fail (connection->generation == _dbus_current_generation); 02876 02877 CONNECTION_LOCK (connection); 02878 02879 #ifndef DBUS_DISABLE_CHECKS 02880 if (connection->shareable) 02881 { 02882 CONNECTION_UNLOCK (connection); 02883 02884 _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n"); 02885 return; 02886 } 02887 #endif 02888 02889 _dbus_connection_close_possibly_shared_and_unlock (connection); 02890 } 02891 02892 static dbus_bool_t 02893 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection) 02894 { 02895 HAVE_LOCK_CHECK (connection); 02896 return _dbus_transport_get_is_connected (connection->transport); 02897 } 02898 02912 dbus_bool_t 02913 dbus_connection_get_is_connected (DBusConnection *connection) 02914 { 02915 dbus_bool_t res; 02916 02917 _dbus_return_val_if_fail (connection != NULL, FALSE); 02918 02919 CONNECTION_LOCK (connection); 02920 res = _dbus_connection_get_is_connected_unlocked (connection); 02921 CONNECTION_UNLOCK (connection); 02922 02923 return res; 02924 } 02925 02934 dbus_bool_t 02935 dbus_connection_get_is_authenticated (DBusConnection *connection) 02936 { 02937 dbus_bool_t res; 02938 02939 _dbus_return_val_if_fail (connection != NULL, FALSE); 02940 02941 CONNECTION_LOCK (connection); 02942 res = _dbus_transport_get_is_authenticated (connection->transport); 02943 CONNECTION_UNLOCK (connection); 02944 02945 return res; 02946 } 02947 02968 dbus_bool_t 02969 dbus_connection_get_is_anonymous (DBusConnection *connection) 02970 { 02971 dbus_bool_t res; 02972 02973 _dbus_return_val_if_fail (connection != NULL, FALSE); 02974 02975 CONNECTION_LOCK (connection); 02976 res = _dbus_transport_get_is_anonymous (connection->transport); 02977 CONNECTION_UNLOCK (connection); 02978 02979 return res; 02980 } 02981 03013 char* 03014 dbus_connection_get_server_id (DBusConnection *connection) 03015 { 03016 char *id; 03017 03018 _dbus_return_val_if_fail (connection != NULL, NULL); 03019 03020 CONNECTION_LOCK (connection); 03021 id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport)); 03022 CONNECTION_UNLOCK (connection); 03023 03024 return id; 03025 } 03026 03044 dbus_bool_t 03045 dbus_connection_can_send_type(DBusConnection *connection, 03046 int type) 03047 { 03048 _dbus_return_val_if_fail (connection != NULL, FALSE); 03049 03050 if (!_dbus_type_is_valid(type)) 03051 return FALSE; 03052 03053 if (type != DBUS_TYPE_UNIX_FD) 03054 return TRUE; 03055 03056 #ifdef HAVE_UNIX_FD_PASSING 03057 { 03058 dbus_bool_t b; 03059 03060 CONNECTION_LOCK(connection); 03061 b = _dbus_transport_can_pass_unix_fd(connection->transport); 03062 CONNECTION_UNLOCK(connection); 03063 03064 return b; 03065 } 03066 #endif 03067 03068 return FALSE; 03069 } 03070 03084 void 03085 dbus_connection_set_exit_on_disconnect (DBusConnection *connection, 03086 dbus_bool_t exit_on_disconnect) 03087 { 03088 _dbus_return_if_fail (connection != NULL); 03089 03090 CONNECTION_LOCK (connection); 03091 connection->exit_on_disconnect = exit_on_disconnect != FALSE; 03092 CONNECTION_UNLOCK (connection); 03093 } 03094 03104 DBusPreallocatedSend* 03105 dbus_connection_preallocate_send (DBusConnection *connection) 03106 { 03107 DBusPreallocatedSend *preallocated; 03108 03109 _dbus_return_val_if_fail (connection != NULL, NULL); 03110 03111 CONNECTION_LOCK (connection); 03112 03113 preallocated = 03114 _dbus_connection_preallocate_send_unlocked (connection); 03115 03116 CONNECTION_UNLOCK (connection); 03117 03118 return preallocated; 03119 } 03120 03130 void 03131 dbus_connection_free_preallocated_send (DBusConnection *connection, 03132 DBusPreallocatedSend *preallocated) 03133 { 03134 _dbus_return_if_fail (connection != NULL); 03135 _dbus_return_if_fail (preallocated != NULL); 03136 _dbus_return_if_fail (connection == preallocated->connection); 03137 03138 _dbus_list_free_link (preallocated->queue_link); 03139 _dbus_counter_unref (preallocated->counter_link->data); 03140 _dbus_list_free_link (preallocated->counter_link); 03141 dbus_free (preallocated); 03142 } 03143 03156 void 03157 dbus_connection_send_preallocated (DBusConnection *connection, 03158 DBusPreallocatedSend *preallocated, 03159 DBusMessage *message, 03160 dbus_uint32_t *client_serial) 03161 { 03162 _dbus_return_if_fail (connection != NULL); 03163 _dbus_return_if_fail (preallocated != NULL); 03164 _dbus_return_if_fail (message != NULL); 03165 _dbus_return_if_fail (preallocated->connection == connection); 03166 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL || 03167 dbus_message_get_member (message) != NULL); 03168 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL || 03169 (dbus_message_get_interface (message) != NULL && 03170 dbus_message_get_member (message) != NULL)); 03171 03172 CONNECTION_LOCK (connection); 03173 03174 #ifdef HAVE_UNIX_FD_PASSING 03175 03176 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03177 message->n_unix_fds > 0) 03178 { 03179 /* Refuse to send fds on a connection that cannot handle 03180 them. Unfortunately we cannot return a proper error here, so 03181 the best we can is just return. */ 03182 CONNECTION_UNLOCK (connection); 03183 return; 03184 } 03185 03186 #endif 03187 03188 _dbus_connection_send_preallocated_and_unlock (connection, 03189 preallocated, 03190 message, client_serial); 03191 } 03192 03193 static dbus_bool_t 03194 _dbus_connection_send_unlocked_no_update (DBusConnection *connection, 03195 DBusMessage *message, 03196 dbus_uint32_t *client_serial) 03197 { 03198 DBusPreallocatedSend *preallocated; 03199 03200 _dbus_assert (connection != NULL); 03201 _dbus_assert (message != NULL); 03202 03203 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 03204 if (preallocated == NULL) 03205 return FALSE; 03206 03207 _dbus_connection_send_preallocated_unlocked_no_update (connection, 03208 preallocated, 03209 message, 03210 client_serial); 03211 return TRUE; 03212 } 03213 03241 dbus_bool_t 03242 dbus_connection_send (DBusConnection *connection, 03243 DBusMessage *message, 03244 dbus_uint32_t *serial) 03245 { 03246 _dbus_return_val_if_fail (connection != NULL, FALSE); 03247 _dbus_return_val_if_fail (message != NULL, FALSE); 03248 03249 CONNECTION_LOCK (connection); 03250 03251 #ifdef HAVE_UNIX_FD_PASSING 03252 03253 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03254 message->n_unix_fds > 0) 03255 { 03256 /* Refuse to send fds on a connection that cannot handle 03257 them. Unfortunately we cannot return a proper error here, so 03258 the best we can is just return. */ 03259 CONNECTION_UNLOCK (connection); 03260 return FALSE; 03261 } 03262 03263 #endif 03264 03265 return _dbus_connection_send_and_unlock (connection, 03266 message, 03267 serial); 03268 } 03269 03270 static dbus_bool_t 03271 reply_handler_timeout (void *data) 03272 { 03273 DBusConnection *connection; 03274 DBusDispatchStatus status; 03275 DBusPendingCall *pending = data; 03276 03277 connection = _dbus_pending_call_get_connection_and_lock (pending); 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 03291 return TRUE; 03292 } 03293 03336 dbus_bool_t 03337 dbus_connection_send_with_reply (DBusConnection *connection, 03338 DBusMessage *message, 03339 DBusPendingCall **pending_return, 03340 int timeout_milliseconds) 03341 { 03342 DBusPendingCall *pending; 03343 dbus_int32_t serial = -1; 03344 DBusDispatchStatus status; 03345 03346 _dbus_return_val_if_fail (connection != NULL, FALSE); 03347 _dbus_return_val_if_fail (message != NULL, FALSE); 03348 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03349 03350 if (pending_return) 03351 *pending_return = NULL; 03352 03353 CONNECTION_LOCK (connection); 03354 03355 #ifdef HAVE_UNIX_FD_PASSING 03356 03357 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03358 message->n_unix_fds > 0) 03359 { 03360 /* Refuse to send fds on a connection that cannot handle 03361 them. Unfortunately we cannot return a proper error here, so 03362 the best we can do is return TRUE but leave *pending_return 03363 as NULL. */ 03364 CONNECTION_UNLOCK (connection); 03365 return TRUE; 03366 } 03367 03368 #endif 03369 03370 if (!_dbus_connection_get_is_connected_unlocked (connection)) 03371 { 03372 CONNECTION_UNLOCK (connection); 03373 03374 return TRUE; 03375 } 03376 03377 pending = _dbus_pending_call_new_unlocked (connection, 03378 timeout_milliseconds, 03379 reply_handler_timeout); 03380 03381 if (pending == NULL) 03382 { 03383 CONNECTION_UNLOCK (connection); 03384 return FALSE; 03385 } 03386 03387 /* Assign a serial to the message */ 03388 serial = dbus_message_get_serial (message); 03389 if (serial == 0) 03390 { 03391 serial = _dbus_connection_get_next_client_serial (connection); 03392 dbus_message_set_serial (message, serial); 03393 } 03394 03395 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial)) 03396 goto error; 03397 03398 /* Insert the serial in the pending replies hash; 03399 * hash takes a refcount on DBusPendingCall. 03400 * Also, add the timeout. 03401 */ 03402 if (!_dbus_connection_attach_pending_call_unlocked (connection, 03403 pending)) 03404 goto error; 03405 03406 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL)) 03407 { 03408 _dbus_connection_detach_pending_call_and_unlock (connection, 03409 pending); 03410 goto error_unlocked; 03411 } 03412 03413 if (pending_return) 03414 *pending_return = pending; /* hand off refcount */ 03415 else 03416 { 03417 _dbus_connection_detach_pending_call_unlocked (connection, pending); 03418 /* we still have a ref to the pending call in this case, we unref 03419 * after unlocking, below 03420 */ 03421 } 03422 03423 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03424 03425 /* this calls out to user code */ 03426 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03427 03428 if (pending_return == NULL) 03429 dbus_pending_call_unref (pending); 03430 03431 return TRUE; 03432 03433 error: 03434 CONNECTION_UNLOCK (connection); 03435 error_unlocked: 03436 dbus_pending_call_unref (pending); 03437 return FALSE; 03438 } 03439 03472 DBusMessage* 03473 dbus_connection_send_with_reply_and_block (DBusConnection *connection, 03474 DBusMessage *message, 03475 int timeout_milliseconds, 03476 DBusError *error) 03477 { 03478 DBusMessage *reply; 03479 DBusPendingCall *pending; 03480 03481 _dbus_return_val_if_fail (connection != NULL, NULL); 03482 _dbus_return_val_if_fail (message != NULL, NULL); 03483 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL); 03484 _dbus_return_val_if_error_is_set (error, NULL); 03485 03486 #ifdef HAVE_UNIX_FD_PASSING 03487 03488 CONNECTION_LOCK (connection); 03489 if (!_dbus_transport_can_pass_unix_fd(connection->transport) && 03490 message->n_unix_fds > 0) 03491 { 03492 CONNECTION_UNLOCK (connection); 03493 dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection."); 03494 return NULL; 03495 } 03496 CONNECTION_UNLOCK (connection); 03497 03498 #endif 03499 03500 if (!dbus_connection_send_with_reply (connection, message, 03501 &pending, timeout_milliseconds)) 03502 { 03503 _DBUS_SET_OOM (error); 03504 return NULL; 03505 } 03506 03507 if (pending == NULL) 03508 { 03509 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed"); 03510 return NULL; 03511 } 03512 03513 dbus_pending_call_block (pending); 03514 03515 reply = dbus_pending_call_steal_reply (pending); 03516 dbus_pending_call_unref (pending); 03517 03518 /* call_complete_and_unlock() called from pending_call_block() should 03519 * always fill this in. 03520 */ 03521 _dbus_assert (reply != NULL); 03522 03523 if (dbus_set_error_from_message (error, reply)) 03524 { 03525 dbus_message_unref (reply); 03526 return NULL; 03527 } 03528 else 03529 return reply; 03530 } 03531 03540 static DBusDispatchStatus 03541 _dbus_connection_flush_unlocked (DBusConnection *connection) 03542 { 03543 /* We have to specify DBUS_ITERATION_DO_READING here because 03544 * otherwise we could have two apps deadlock if they are both doing 03545 * a flush(), and the kernel buffers fill up. This could change the 03546 * dispatch status. 03547 */ 03548 DBusDispatchStatus status; 03549 03550 HAVE_LOCK_CHECK (connection); 03551 03552 while (connection->n_outgoing > 0 && 03553 _dbus_connection_get_is_connected_unlocked (connection)) 03554 { 03555 _dbus_verbose ("doing iteration in\n"); 03556 HAVE_LOCK_CHECK (connection); 03557 _dbus_connection_do_iteration_unlocked (connection, 03558 NULL, 03559 DBUS_ITERATION_DO_READING | 03560 DBUS_ITERATION_DO_WRITING | 03561 DBUS_ITERATION_BLOCK, 03562 -1); 03563 } 03564 03565 HAVE_LOCK_CHECK (connection); 03566 _dbus_verbose ("middle\n"); 03567 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03568 03569 HAVE_LOCK_CHECK (connection); 03570 return status; 03571 } 03572 03578 void 03579 dbus_connection_flush (DBusConnection *connection) 03580 { 03581 /* We have to specify DBUS_ITERATION_DO_READING here because 03582 * otherwise we could have two apps deadlock if they are both doing 03583 * a flush(), and the kernel buffers fill up. This could change the 03584 * dispatch status. 03585 */ 03586 DBusDispatchStatus status; 03587 03588 _dbus_return_if_fail (connection != NULL); 03589 03590 CONNECTION_LOCK (connection); 03591 03592 status = _dbus_connection_flush_unlocked (connection); 03593 03594 HAVE_LOCK_CHECK (connection); 03595 /* Unlocks and calls out to user code */ 03596 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03597 03598 _dbus_verbose ("end\n"); 03599 } 03600 03611 static dbus_bool_t 03612 _dbus_connection_read_write_dispatch (DBusConnection *connection, 03613 int timeout_milliseconds, 03614 dbus_bool_t dispatch) 03615 { 03616 DBusDispatchStatus dstatus; 03617 dbus_bool_t progress_possible; 03618 03619 /* Need to grab a ref here in case we're a private connection and 03620 * the user drops the last ref in a handler we call; see bug 03621 * https://bugs.freedesktop.org/show_bug.cgi?id=15635 03622 */ 03623 dbus_connection_ref (connection); 03624 dstatus = dbus_connection_get_dispatch_status (connection); 03625 03626 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS) 03627 { 03628 _dbus_verbose ("doing dispatch\n"); 03629 dbus_connection_dispatch (connection); 03630 CONNECTION_LOCK (connection); 03631 } 03632 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY) 03633 { 03634 _dbus_verbose ("pausing for memory\n"); 03635 _dbus_memory_pause_based_on_timeout (timeout_milliseconds); 03636 CONNECTION_LOCK (connection); 03637 } 03638 else 03639 { 03640 CONNECTION_LOCK (connection); 03641 if (_dbus_connection_get_is_connected_unlocked (connection)) 03642 { 03643 _dbus_verbose ("doing iteration\n"); 03644 _dbus_connection_do_iteration_unlocked (connection, 03645 NULL, 03646 DBUS_ITERATION_DO_READING | 03647 DBUS_ITERATION_DO_WRITING | 03648 DBUS_ITERATION_BLOCK, 03649 timeout_milliseconds); 03650 } 03651 } 03652 03653 HAVE_LOCK_CHECK (connection); 03654 /* If we can dispatch, we can make progress until the Disconnected message 03655 * has been processed; if we can only read/write, we can make progress 03656 * as long as the transport is open. 03657 */ 03658 if (dispatch) 03659 progress_possible = connection->n_incoming != 0 || 03660 connection->disconnect_message_link != NULL; 03661 else 03662 progress_possible = _dbus_connection_get_is_connected_unlocked (connection); 03663 03664 CONNECTION_UNLOCK (connection); 03665 03666 dbus_connection_unref (connection); 03667 03668 return progress_possible; /* TRUE if we can make more progress */ 03669 } 03670 03671 03706 dbus_bool_t 03707 dbus_connection_read_write_dispatch (DBusConnection *connection, 03708 int timeout_milliseconds) 03709 { 03710 _dbus_return_val_if_fail (connection != NULL, FALSE); 03711 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03712 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE); 03713 } 03714 03738 dbus_bool_t 03739 dbus_connection_read_write (DBusConnection *connection, 03740 int timeout_milliseconds) 03741 { 03742 _dbus_return_val_if_fail (connection != NULL, FALSE); 03743 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 03744 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE); 03745 } 03746 03747 /* We need to call this anytime we pop the head of the queue, and then 03748 * update_dispatch_status_and_unlock needs to be called afterward 03749 * which will "process" the disconnected message and set 03750 * disconnected_message_processed. 03751 */ 03752 static void 03753 check_disconnected_message_arrived_unlocked (DBusConnection *connection, 03754 DBusMessage *head_of_queue) 03755 { 03756 HAVE_LOCK_CHECK (connection); 03757 03758 /* checking that the link is NULL is an optimization to avoid the is_signal call */ 03759 if (connection->disconnect_message_link == NULL && 03760 dbus_message_is_signal (head_of_queue, 03761 DBUS_INTERFACE_LOCAL, 03762 "Disconnected")) 03763 { 03764 connection->disconnected_message_arrived = TRUE; 03765 } 03766 } 03767 03787 DBusMessage* 03788 dbus_connection_borrow_message (DBusConnection *connection) 03789 { 03790 DBusDispatchStatus status; 03791 DBusMessage *message; 03792 03793 _dbus_return_val_if_fail (connection != NULL, NULL); 03794 03795 _dbus_verbose ("start\n"); 03796 03797 /* this is called for the side effect that it queues 03798 * up any messages from the transport 03799 */ 03800 status = dbus_connection_get_dispatch_status (connection); 03801 if (status != DBUS_DISPATCH_DATA_REMAINS) 03802 return NULL; 03803 03804 CONNECTION_LOCK (connection); 03805 03806 _dbus_connection_acquire_dispatch (connection); 03807 03808 /* While a message is outstanding, the dispatch lock is held */ 03809 _dbus_assert (connection->message_borrowed == NULL); 03810 03811 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages); 03812 03813 message = connection->message_borrowed; 03814 03815 check_disconnected_message_arrived_unlocked (connection, message); 03816 03817 /* Note that we KEEP the dispatch lock until the message is returned */ 03818 if (message == NULL) 03819 _dbus_connection_release_dispatch (connection); 03820 03821 CONNECTION_UNLOCK (connection); 03822 03823 /* We don't update dispatch status until it's returned or stolen */ 03824 03825 return message; 03826 } 03827 03836 void 03837 dbus_connection_return_message (DBusConnection *connection, 03838 DBusMessage *message) 03839 { 03840 DBusDispatchStatus status; 03841 03842 _dbus_return_if_fail (connection != NULL); 03843 _dbus_return_if_fail (message != NULL); 03844 _dbus_return_if_fail (message == connection->message_borrowed); 03845 _dbus_return_if_fail (connection->dispatch_acquired); 03846 03847 CONNECTION_LOCK (connection); 03848 03849 _dbus_assert (message == connection->message_borrowed); 03850 03851 connection->message_borrowed = NULL; 03852 03853 _dbus_connection_release_dispatch (connection); 03854 03855 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03856 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03857 } 03858 03868 void 03869 dbus_connection_steal_borrowed_message (DBusConnection *connection, 03870 DBusMessage *message) 03871 { 03872 DBusMessage *pop_message; 03873 DBusDispatchStatus status; 03874 03875 _dbus_return_if_fail (connection != NULL); 03876 _dbus_return_if_fail (message != NULL); 03877 _dbus_return_if_fail (message == connection->message_borrowed); 03878 _dbus_return_if_fail (connection->dispatch_acquired); 03879 03880 CONNECTION_LOCK (connection); 03881 03882 _dbus_assert (message == connection->message_borrowed); 03883 03884 pop_message = _dbus_list_pop_first (&connection->incoming_messages); 03885 _dbus_assert (message == pop_message); 03886 03887 connection->n_incoming -= 1; 03888 03889 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n", 03890 message, connection->n_incoming); 03891 03892 connection->message_borrowed = NULL; 03893 03894 _dbus_connection_release_dispatch (connection); 03895 03896 status = _dbus_connection_get_dispatch_status_unlocked (connection); 03897 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 03898 } 03899 03900 /* See dbus_connection_pop_message, but requires the caller to own 03901 * the lock before calling. May drop the lock while running. 03902 */ 03903 static DBusList* 03904 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection) 03905 { 03906 HAVE_LOCK_CHECK (connection); 03907 03908 _dbus_assert (connection->message_borrowed == NULL); 03909 03910 if (connection->n_incoming > 0) 03911 { 03912 DBusList *link; 03913 03914 link = _dbus_list_pop_first_link (&connection->incoming_messages); 03915 connection->n_incoming -= 1; 03916 03917 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from incoming queue %p, %d incoming\n", 03918 link->data, 03919 dbus_message_type_to_string (dbus_message_get_type (link->data)), 03920 dbus_message_get_path (link->data) ? 03921 dbus_message_get_path (link->data) : 03922 "no path", 03923 dbus_message_get_interface (link->data) ? 03924 dbus_message_get_interface (link->data) : 03925 "no interface", 03926 dbus_message_get_member (link->data) ? 03927 dbus_message_get_member (link->data) : 03928 "no member", 03929 dbus_message_get_signature (link->data), 03930 connection, connection->n_incoming); 03931 03932 check_disconnected_message_arrived_unlocked (connection, link->data); 03933 03934 return link; 03935 } 03936 else 03937 return NULL; 03938 } 03939 03940 /* See dbus_connection_pop_message, but requires the caller to own 03941 * the lock before calling. May drop the lock while running. 03942 */ 03943 static DBusMessage* 03944 _dbus_connection_pop_message_unlocked (DBusConnection *connection) 03945 { 03946 DBusList *link; 03947 03948 HAVE_LOCK_CHECK (connection); 03949 03950 link = _dbus_connection_pop_message_link_unlocked (connection); 03951 03952 if (link != NULL) 03953 { 03954 DBusMessage *message; 03955 03956 message = link->data; 03957 03958 _dbus_list_free_link (link); 03959 03960 return message; 03961 } 03962 else 03963 return NULL; 03964 } 03965 03966 static void 03967 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection, 03968 DBusList *message_link) 03969 { 03970 HAVE_LOCK_CHECK (connection); 03971 03972 _dbus_assert (message_link != NULL); 03973 /* You can't borrow a message while a link is outstanding */ 03974 _dbus_assert (connection->message_borrowed == NULL); 03975 /* We had to have the dispatch lock across the pop/putback */ 03976 _dbus_assert (connection->dispatch_acquired); 03977 03978 _dbus_list_prepend_link (&connection->incoming_messages, 03979 message_link); 03980 connection->n_incoming += 1; 03981 03982 _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n", 03983 message_link->data, 03984 dbus_message_type_to_string (dbus_message_get_type (message_link->data)), 03985 dbus_message_get_interface (message_link->data) ? 03986 dbus_message_get_interface (message_link->data) : 03987 "no interface", 03988 dbus_message_get_member (message_link->data) ? 03989 dbus_message_get_member (message_link->data) : 03990 "no member", 03991 dbus_message_get_signature (message_link->data), 03992 connection, connection->n_incoming); 03993 } 03994 04014 DBusMessage* 04015 dbus_connection_pop_message (DBusConnection *connection) 04016 { 04017 DBusMessage *message; 04018 DBusDispatchStatus status; 04019 04020 _dbus_verbose ("start\n"); 04021 04022 /* this is called for the side effect that it queues 04023 * up any messages from the transport 04024 */ 04025 status = dbus_connection_get_dispatch_status (connection); 04026 if (status != DBUS_DISPATCH_DATA_REMAINS) 04027 return NULL; 04028 04029 CONNECTION_LOCK (connection); 04030 _dbus_connection_acquire_dispatch (connection); 04031 HAVE_LOCK_CHECK (connection); 04032 04033 message = _dbus_connection_pop_message_unlocked (connection); 04034 04035 _dbus_verbose ("Returning popped message %p\n", message); 04036 04037 _dbus_connection_release_dispatch (connection); 04038 04039 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04040 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04041 04042 return message; 04043 } 04044 04052 static void 04053 _dbus_connection_acquire_dispatch (DBusConnection *connection) 04054 { 04055 HAVE_LOCK_CHECK (connection); 04056 04057 _dbus_connection_ref_unlocked (connection); 04058 CONNECTION_UNLOCK (connection); 04059 04060 _dbus_verbose ("locking dispatch_mutex\n"); 04061 _dbus_mutex_lock (connection->dispatch_mutex); 04062 04063 while (connection->dispatch_acquired) 04064 { 04065 _dbus_verbose ("waiting for dispatch to be acquirable\n"); 04066 _dbus_condvar_wait (connection->dispatch_cond, 04067 connection->dispatch_mutex); 04068 } 04069 04070 _dbus_assert (!connection->dispatch_acquired); 04071 04072 connection->dispatch_acquired = TRUE; 04073 04074 _dbus_verbose ("unlocking dispatch_mutex\n"); 04075 _dbus_mutex_unlock (connection->dispatch_mutex); 04076 04077 CONNECTION_LOCK (connection); 04078 _dbus_connection_unref_unlocked (connection); 04079 } 04080 04088 static void 04089 _dbus_connection_release_dispatch (DBusConnection *connection) 04090 { 04091 HAVE_LOCK_CHECK (connection); 04092 04093 _dbus_verbose ("locking dispatch_mutex\n"); 04094 _dbus_mutex_lock (connection->dispatch_mutex); 04095 04096 _dbus_assert (connection->dispatch_acquired); 04097 04098 connection->dispatch_acquired = FALSE; 04099 _dbus_condvar_wake_one (connection->dispatch_cond); 04100 04101 _dbus_verbose ("unlocking dispatch_mutex\n"); 04102 _dbus_mutex_unlock (connection->dispatch_mutex); 04103 } 04104 04105 static void 04106 _dbus_connection_failed_pop (DBusConnection *connection, 04107 DBusList *message_link) 04108 { 04109 _dbus_list_prepend_link (&connection->incoming_messages, 04110 message_link); 04111 connection->n_incoming += 1; 04112 } 04113 04114 /* Note this may be called multiple times since we don't track whether we already did it */ 04115 static void 04116 notify_disconnected_unlocked (DBusConnection *connection) 04117 { 04118 HAVE_LOCK_CHECK (connection); 04119 04120 /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected 04121 * connection from dbus_bus_get(). We make the same guarantee for 04122 * dbus_connection_open() but in a different way since we don't want to 04123 * unref right here; we instead check for connectedness before returning 04124 * the connection from the hash. 04125 */ 04126 _dbus_bus_notify_shared_connection_disconnected_unlocked (connection); 04127 04128 /* Dump the outgoing queue, we aren't going to be able to 04129 * send it now, and we'd like accessors like 04130 * dbus_connection_get_outgoing_size() to be accurate. 04131 */ 04132 if (connection->n_outgoing > 0) 04133 { 04134 DBusList *link; 04135 04136 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n", 04137 connection->n_outgoing); 04138 04139 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages))) 04140 { 04141 _dbus_connection_message_sent (connection, link->data); 04142 } 04143 } 04144 } 04145 04146 /* Note this may be called multiple times since we don't track whether we already did it */ 04147 static DBusDispatchStatus 04148 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection) 04149 { 04150 HAVE_LOCK_CHECK (connection); 04151 04152 if (connection->disconnect_message_link != NULL) 04153 { 04154 _dbus_verbose ("Sending disconnect message\n"); 04155 04156 /* If we have pending calls, queue their timeouts - we want the Disconnected 04157 * to be the last message, after these timeouts. 04158 */ 04159 connection_timeout_and_complete_all_pending_calls_unlocked (connection); 04160 04161 /* We haven't sent the disconnect message already, 04162 * and all real messages have been queued up. 04163 */ 04164 _dbus_connection_queue_synthesized_message_link (connection, 04165 connection->disconnect_message_link); 04166 connection->disconnect_message_link = NULL; 04167 04168 return DBUS_DISPATCH_DATA_REMAINS; 04169 } 04170 04171 return DBUS_DISPATCH_COMPLETE; 04172 } 04173 04174 static DBusDispatchStatus 04175 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection) 04176 { 04177 HAVE_LOCK_CHECK (connection); 04178 04179 if (connection->n_incoming > 0) 04180 return DBUS_DISPATCH_DATA_REMAINS; 04181 else if (!_dbus_transport_queue_messages (connection->transport)) 04182 return DBUS_DISPATCH_NEED_MEMORY; 04183 else 04184 { 04185 DBusDispatchStatus status; 04186 dbus_bool_t is_connected; 04187 04188 status = _dbus_transport_get_dispatch_status (connection->transport); 04189 is_connected = _dbus_transport_get_is_connected (connection->transport); 04190 04191 _dbus_verbose ("dispatch status = %s is_connected = %d\n", 04192 DISPATCH_STATUS_NAME (status), is_connected); 04193 04194 if (!is_connected) 04195 { 04196 /* It's possible this would be better done by having an explicit 04197 * notification from _dbus_transport_disconnect() that would 04198 * synchronously do this, instead of waiting for the next dispatch 04199 * status check. However, probably not good to change until it causes 04200 * a problem. 04201 */ 04202 notify_disconnected_unlocked (connection); 04203 04204 /* I'm not sure this is needed; the idea is that we want to 04205 * queue the Disconnected only after we've read all the 04206 * messages, but if we're disconnected maybe we are guaranteed 04207 * to have read them all ? 04208 */ 04209 if (status == DBUS_DISPATCH_COMPLETE) 04210 status = notify_disconnected_and_dispatch_complete_unlocked (connection); 04211 } 04212 04213 if (status != DBUS_DISPATCH_COMPLETE) 04214 return status; 04215 else if (connection->n_incoming > 0) 04216 return DBUS_DISPATCH_DATA_REMAINS; 04217 else 04218 return DBUS_DISPATCH_COMPLETE; 04219 } 04220 } 04221 04222 static void 04223 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection, 04224 DBusDispatchStatus new_status) 04225 { 04226 dbus_bool_t changed; 04227 DBusDispatchStatusFunction function; 04228 void *data; 04229 04230 HAVE_LOCK_CHECK (connection); 04231 04232 _dbus_connection_ref_unlocked (connection); 04233 04234 changed = new_status != connection->last_dispatch_status; 04235 04236 connection->last_dispatch_status = new_status; 04237 04238 function = connection->dispatch_status_function; 04239 data = connection->dispatch_status_data; 04240 04241 if (connection->disconnected_message_arrived && 04242 !connection->disconnected_message_processed) 04243 { 04244 connection->disconnected_message_processed = TRUE; 04245 04246 /* this does an unref, but we have a ref 04247 * so we should not run the finalizer here 04248 * inside the lock. 04249 */ 04250 connection_forget_shared_unlocked (connection); 04251 04252 if (connection->exit_on_disconnect) 04253 { 04254 CONNECTION_UNLOCK (connection); 04255 04256 _dbus_verbose ("Exiting on Disconnected signal\n"); 04257 _dbus_exit (1); 04258 _dbus_assert_not_reached ("Call to exit() returned"); 04259 } 04260 } 04261 04262 /* We drop the lock */ 04263 CONNECTION_UNLOCK (connection); 04264 04265 if (changed && function) 04266 { 04267 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n", 04268 connection, new_status, 04269 DISPATCH_STATUS_NAME (new_status)); 04270 (* function) (connection, new_status, data); 04271 } 04272 04273 dbus_connection_unref (connection); 04274 } 04275 04301 DBusDispatchStatus 04302 dbus_connection_get_dispatch_status (DBusConnection *connection) 04303 { 04304 DBusDispatchStatus status; 04305 04306 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE); 04307 04308 _dbus_verbose ("start\n"); 04309 04310 CONNECTION_LOCK (connection); 04311 04312 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04313 04314 CONNECTION_UNLOCK (connection); 04315 04316 return status; 04317 } 04318 04322 static DBusHandlerResult 04323 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection, 04324 DBusMessage *message) 04325 { 04326 if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL) 04327 { 04328 /* This means we're letting the bus route this message */ 04329 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04330 } 04331 else if (dbus_message_is_method_call (message, 04332 DBUS_INTERFACE_PEER, 04333 "Ping")) 04334 { 04335 DBusMessage *ret; 04336 dbus_bool_t sent; 04337 04338 ret = dbus_message_new_method_return (message); 04339 if (ret == NULL) 04340 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04341 04342 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04343 04344 dbus_message_unref (ret); 04345 04346 if (!sent) 04347 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04348 04349 return DBUS_HANDLER_RESULT_HANDLED; 04350 } 04351 else if (dbus_message_is_method_call (message, 04352 DBUS_INTERFACE_PEER, 04353 "GetMachineId")) 04354 { 04355 DBusMessage *ret; 04356 dbus_bool_t sent; 04357 DBusString uuid; 04358 04359 ret = dbus_message_new_method_return (message); 04360 if (ret == NULL) 04361 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04362 04363 sent = FALSE; 04364 _dbus_string_init (&uuid); 04365 if (_dbus_get_local_machine_uuid_encoded (&uuid)) 04366 { 04367 const char *v_STRING = _dbus_string_get_const_data (&uuid); 04368 if (dbus_message_append_args (ret, 04369 DBUS_TYPE_STRING, &v_STRING, 04370 DBUS_TYPE_INVALID)) 04371 { 04372 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04373 } 04374 } 04375 _dbus_string_free (&uuid); 04376 04377 dbus_message_unref (ret); 04378 04379 if (!sent) 04380 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04381 04382 return DBUS_HANDLER_RESULT_HANDLED; 04383 } 04384 else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER)) 04385 { 04386 /* We need to bounce anything else with this interface, otherwise apps 04387 * could start extending the interface and when we added extensions 04388 * here to DBusConnection we'd break those apps. 04389 */ 04390 04391 DBusMessage *ret; 04392 dbus_bool_t sent; 04393 04394 ret = dbus_message_new_error (message, 04395 DBUS_ERROR_UNKNOWN_METHOD, 04396 "Unknown method invoked on org.freedesktop.DBus.Peer interface"); 04397 if (ret == NULL) 04398 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04399 04400 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL); 04401 04402 dbus_message_unref (ret); 04403 04404 if (!sent) 04405 return DBUS_HANDLER_RESULT_NEED_MEMORY; 04406 04407 return DBUS_HANDLER_RESULT_HANDLED; 04408 } 04409 else 04410 { 04411 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04412 } 04413 } 04414 04421 static DBusHandlerResult 04422 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection, 04423 DBusMessage *message) 04424 { 04425 /* We just run one filter for now but have the option to run more 04426 if the spec calls for it in the future */ 04427 04428 return _dbus_connection_peer_filter_unlocked_no_update (connection, message); 04429 } 04430 04473 DBusDispatchStatus 04474 dbus_connection_dispatch (DBusConnection *connection) 04475 { 04476 DBusMessage *message; 04477 DBusList *link, *filter_list_copy, *message_link; 04478 DBusHandlerResult result; 04479 DBusPendingCall *pending; 04480 dbus_int32_t reply_serial; 04481 DBusDispatchStatus status; 04482 04483 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE); 04484 04485 _dbus_verbose ("\n"); 04486 04487 CONNECTION_LOCK (connection); 04488 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04489 if (status != DBUS_DISPATCH_DATA_REMAINS) 04490 { 04491 /* unlocks and calls out to user code */ 04492 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04493 return status; 04494 } 04495 04496 /* We need to ref the connection since the callback could potentially 04497 * drop the last ref to it 04498 */ 04499 _dbus_connection_ref_unlocked (connection); 04500 04501 _dbus_connection_acquire_dispatch (connection); 04502 HAVE_LOCK_CHECK (connection); 04503 04504 message_link = _dbus_connection_pop_message_link_unlocked (connection); 04505 if (message_link == NULL) 04506 { 04507 /* another thread dispatched our stuff */ 04508 04509 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n"); 04510 04511 _dbus_connection_release_dispatch (connection); 04512 04513 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04514 04515 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04516 04517 dbus_connection_unref (connection); 04518 04519 return status; 04520 } 04521 04522 message = message_link->data; 04523 04524 _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n", 04525 message, 04526 dbus_message_type_to_string (dbus_message_get_type (message)), 04527 dbus_message_get_interface (message) ? 04528 dbus_message_get_interface (message) : 04529 "no interface", 04530 dbus_message_get_member (message) ? 04531 dbus_message_get_member (message) : 04532 "no member", 04533 dbus_message_get_signature (message)); 04534 04535 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 04536 04537 /* Pending call handling must be first, because if you do 04538 * dbus_connection_send_with_reply_and_block() or 04539 * dbus_pending_call_block() then no handlers/filters will be run on 04540 * the reply. We want consistent semantics in the case where we 04541 * dbus_connection_dispatch() the reply. 04542 */ 04543 04544 reply_serial = dbus_message_get_reply_serial (message); 04545 pending = _dbus_hash_table_lookup_int (connection->pending_replies, 04546 reply_serial); 04547 if (pending) 04548 { 04549 _dbus_verbose ("Dispatching a pending reply\n"); 04550 complete_pending_call_and_unlock (connection, pending, message); 04551 pending = NULL; /* it's probably unref'd */ 04552 04553 CONNECTION_LOCK (connection); 04554 _dbus_verbose ("pending call completed in dispatch\n"); 04555 result = DBUS_HANDLER_RESULT_HANDLED; 04556 goto out; 04557 } 04558 04559 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message); 04560 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04561 goto out; 04562 04563 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy)) 04564 { 04565 _dbus_connection_release_dispatch (connection); 04566 HAVE_LOCK_CHECK (connection); 04567 04568 _dbus_connection_failed_pop (connection, message_link); 04569 04570 /* unlocks and calls user code */ 04571 _dbus_connection_update_dispatch_status_and_unlock (connection, 04572 DBUS_DISPATCH_NEED_MEMORY); 04573 dbus_connection_unref (connection); 04574 04575 return DBUS_DISPATCH_NEED_MEMORY; 04576 } 04577 04578 _dbus_list_foreach (&filter_list_copy, 04579 (DBusForeachFunction)_dbus_message_filter_ref, 04580 NULL); 04581 04582 /* We're still protected from dispatch() reentrancy here 04583 * since we acquired the dispatcher 04584 */ 04585 CONNECTION_UNLOCK (connection); 04586 04587 link = _dbus_list_get_first_link (&filter_list_copy); 04588 while (link != NULL) 04589 { 04590 DBusMessageFilter *filter = link->data; 04591 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link); 04592 04593 if (filter->function == NULL) 04594 { 04595 _dbus_verbose (" filter was removed in a callback function\n"); 04596 link = next; 04597 continue; 04598 } 04599 04600 _dbus_verbose (" running filter on message %p\n", message); 04601 result = (* filter->function) (connection, message, filter->user_data); 04602 04603 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04604 break; 04605 04606 link = next; 04607 } 04608 04609 _dbus_list_foreach (&filter_list_copy, 04610 (DBusForeachFunction)_dbus_message_filter_unref, 04611 NULL); 04612 _dbus_list_clear (&filter_list_copy); 04613 04614 CONNECTION_LOCK (connection); 04615 04616 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) 04617 { 04618 _dbus_verbose ("No memory\n"); 04619 goto out; 04620 } 04621 else if (result == DBUS_HANDLER_RESULT_HANDLED) 04622 { 04623 _dbus_verbose ("filter handled message in dispatch\n"); 04624 goto out; 04625 } 04626 04627 /* We're still protected from dispatch() reentrancy here 04628 * since we acquired the dispatcher 04629 */ 04630 _dbus_verbose (" running object path dispatch on message %p (%s %s %s '%s')\n", 04631 message, 04632 dbus_message_type_to_string (dbus_message_get_type (message)), 04633 dbus_message_get_interface (message) ? 04634 dbus_message_get_interface (message) : 04635 "no interface", 04636 dbus_message_get_member (message) ? 04637 dbus_message_get_member (message) : 04638 "no member", 04639 dbus_message_get_signature (message)); 04640 04641 HAVE_LOCK_CHECK (connection); 04642 result = _dbus_object_tree_dispatch_and_unlock (connection->objects, 04643 message); 04644 04645 CONNECTION_LOCK (connection); 04646 04647 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 04648 { 04649 _dbus_verbose ("object tree handled message in dispatch\n"); 04650 goto out; 04651 } 04652 04653 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL) 04654 { 04655 DBusMessage *reply; 04656 DBusString str; 04657 DBusPreallocatedSend *preallocated; 04658 04659 _dbus_verbose (" sending error %s\n", 04660 DBUS_ERROR_UNKNOWN_METHOD); 04661 04662 if (!_dbus_string_init (&str)) 04663 { 04664 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04665 _dbus_verbose ("no memory for error string in dispatch\n"); 04666 goto out; 04667 } 04668 04669 if (!_dbus_string_append_printf (&str, 04670 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n", 04671 dbus_message_get_member (message), 04672 dbus_message_get_signature (message), 04673 dbus_message_get_interface (message))) 04674 { 04675 _dbus_string_free (&str); 04676 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04677 _dbus_verbose ("no memory for error string in dispatch\n"); 04678 goto out; 04679 } 04680 04681 reply = dbus_message_new_error (message, 04682 DBUS_ERROR_UNKNOWN_METHOD, 04683 _dbus_string_get_const_data (&str)); 04684 _dbus_string_free (&str); 04685 04686 if (reply == NULL) 04687 { 04688 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04689 _dbus_verbose ("no memory for error reply in dispatch\n"); 04690 goto out; 04691 } 04692 04693 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 04694 04695 if (preallocated == NULL) 04696 { 04697 dbus_message_unref (reply); 04698 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 04699 _dbus_verbose ("no memory for error send in dispatch\n"); 04700 goto out; 04701 } 04702 04703 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated, 04704 reply, NULL); 04705 04706 dbus_message_unref (reply); 04707 04708 result = DBUS_HANDLER_RESULT_HANDLED; 04709 } 04710 04711 _dbus_verbose (" done dispatching %p (%s %s %s '%s') on connection %p\n", message, 04712 dbus_message_type_to_string (dbus_message_get_type (message)), 04713 dbus_message_get_interface (message) ? 04714 dbus_message_get_interface (message) : 04715 "no interface", 04716 dbus_message_get_member (message) ? 04717 dbus_message_get_member (message) : 04718 "no member", 04719 dbus_message_get_signature (message), 04720 connection); 04721 04722 out: 04723 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) 04724 { 04725 _dbus_verbose ("out of memory\n"); 04726 04727 /* Put message back, and we'll start over. 04728 * Yes this means handlers must be idempotent if they 04729 * don't return HANDLED; c'est la vie. 04730 */ 04731 _dbus_connection_putback_message_link_unlocked (connection, 04732 message_link); 04733 } 04734 else 04735 { 04736 _dbus_verbose (" ... done dispatching\n"); 04737 04738 _dbus_list_free_link (message_link); 04739 dbus_message_unref (message); /* don't want the message to count in max message limits 04740 * in computing dispatch status below 04741 */ 04742 } 04743 04744 _dbus_connection_release_dispatch (connection); 04745 HAVE_LOCK_CHECK (connection); 04746 04747 _dbus_verbose ("before final status update\n"); 04748 status = _dbus_connection_get_dispatch_status_unlocked (connection); 04749 04750 /* unlocks and calls user code */ 04751 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 04752 04753 dbus_connection_unref (connection); 04754 04755 return status; 04756 } 04757 04819 dbus_bool_t 04820 dbus_connection_set_watch_functions (DBusConnection *connection, 04821 DBusAddWatchFunction add_function, 04822 DBusRemoveWatchFunction remove_function, 04823 DBusWatchToggledFunction toggled_function, 04824 void *data, 04825 DBusFreeFunction free_data_function) 04826 { 04827 dbus_bool_t retval; 04828 04829 _dbus_return_val_if_fail (connection != NULL, FALSE); 04830 04831 CONNECTION_LOCK (connection); 04832 04833 retval = _dbus_watch_list_set_functions (connection->watches, 04834 add_function, remove_function, 04835 toggled_function, 04836 data, free_data_function); 04837 04838 CONNECTION_UNLOCK (connection); 04839 04840 return retval; 04841 } 04842 04882 dbus_bool_t 04883 dbus_connection_set_timeout_functions (DBusConnection *connection, 04884 DBusAddTimeoutFunction add_function, 04885 DBusRemoveTimeoutFunction remove_function, 04886 DBusTimeoutToggledFunction toggled_function, 04887 void *data, 04888 DBusFreeFunction free_data_function) 04889 { 04890 dbus_bool_t retval; 04891 04892 _dbus_return_val_if_fail (connection != NULL, FALSE); 04893 04894 CONNECTION_LOCK (connection); 04895 04896 retval = _dbus_timeout_list_set_functions (connection->timeouts, 04897 add_function, remove_function, 04898 toggled_function, 04899 data, free_data_function); 04900 04901 CONNECTION_UNLOCK (connection); 04902 04903 return retval; 04904 } 04905 04920 void 04921 dbus_connection_set_wakeup_main_function (DBusConnection *connection, 04922 DBusWakeupMainFunction wakeup_main_function, 04923 void *data, 04924 DBusFreeFunction free_data_function) 04925 { 04926 void *old_data; 04927 DBusFreeFunction old_free_data; 04928 04929 _dbus_return_if_fail (connection != NULL); 04930 04931 CONNECTION_LOCK (connection); 04932 old_data = connection->wakeup_main_data; 04933 old_free_data = connection->free_wakeup_main_data; 04934 04935 connection->wakeup_main_function = wakeup_main_function; 04936 connection->wakeup_main_data = data; 04937 connection->free_wakeup_main_data = free_data_function; 04938 04939 CONNECTION_UNLOCK (connection); 04940 04941 /* Callback outside the lock */ 04942 if (old_free_data) 04943 (*old_free_data) (old_data); 04944 } 04945 04966 void 04967 dbus_connection_set_dispatch_status_function (DBusConnection *connection, 04968 DBusDispatchStatusFunction function, 04969 void *data, 04970 DBusFreeFunction free_data_function) 04971 { 04972 void *old_data; 04973 DBusFreeFunction old_free_data; 04974 04975 _dbus_return_if_fail (connection != NULL); 04976 04977 CONNECTION_LOCK (connection); 04978 old_data = connection->dispatch_status_data; 04979 old_free_data = connection->free_dispatch_status_data; 04980 04981 connection->dispatch_status_function = function; 04982 connection->dispatch_status_data = data; 04983 connection->free_dispatch_status_data = free_data_function; 04984 04985 CONNECTION_UNLOCK (connection); 04986 04987 /* Callback outside the lock */ 04988 if (old_free_data) 04989 (*old_free_data) (old_data); 04990 } 04991 05011 dbus_bool_t 05012 dbus_connection_get_unix_fd (DBusConnection *connection, 05013 int *fd) 05014 { 05015 _dbus_return_val_if_fail (connection != NULL, FALSE); 05016 _dbus_return_val_if_fail (connection->transport != NULL, FALSE); 05017 05018 #ifdef DBUS_WIN 05019 /* FIXME do this on a lower level */ 05020 return FALSE; 05021 #endif 05022 05023 return dbus_connection_get_socket(connection, fd); 05024 } 05025 05041 dbus_bool_t 05042 dbus_connection_get_socket(DBusConnection *connection, 05043 int *fd) 05044 { 05045 dbus_bool_t retval; 05046 05047 _dbus_return_val_if_fail (connection != NULL, FALSE); 05048 _dbus_return_val_if_fail (connection->transport != NULL, FALSE); 05049 05050 CONNECTION_LOCK (connection); 05051 05052 retval = _dbus_transport_get_socket_fd (connection->transport, 05053 fd); 05054 05055 CONNECTION_UNLOCK (connection); 05056 05057 return retval; 05058 } 05059 05060 05083 dbus_bool_t 05084 dbus_connection_get_unix_user (DBusConnection *connection, 05085 unsigned long *uid) 05086 { 05087 dbus_bool_t result; 05088 05089 _dbus_return_val_if_fail (connection != NULL, FALSE); 05090 _dbus_return_val_if_fail (uid != NULL, FALSE); 05091 05092 CONNECTION_LOCK (connection); 05093 05094 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05095 result = FALSE; 05096 else 05097 result = _dbus_transport_get_unix_user (connection->transport, 05098 uid); 05099 05100 #ifdef DBUS_WIN 05101 _dbus_assert (!result); 05102 #endif 05103 05104 CONNECTION_UNLOCK (connection); 05105 05106 return result; 05107 } 05108 05119 dbus_bool_t 05120 dbus_connection_get_unix_process_id (DBusConnection *connection, 05121 unsigned long *pid) 05122 { 05123 dbus_bool_t result; 05124 05125 _dbus_return_val_if_fail (connection != NULL, FALSE); 05126 _dbus_return_val_if_fail (pid != NULL, FALSE); 05127 05128 CONNECTION_LOCK (connection); 05129 05130 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05131 result = FALSE; 05132 else 05133 result = _dbus_transport_get_unix_process_id (connection->transport, 05134 pid); 05135 05136 CONNECTION_UNLOCK (connection); 05137 05138 return result; 05139 } 05140 05151 dbus_bool_t 05152 dbus_connection_get_adt_audit_session_data (DBusConnection *connection, 05153 void **data, 05154 dbus_int32_t *data_size) 05155 { 05156 dbus_bool_t result; 05157 05158 _dbus_return_val_if_fail (connection != NULL, FALSE); 05159 _dbus_return_val_if_fail (data != NULL, FALSE); 05160 _dbus_return_val_if_fail (data_size != NULL, FALSE); 05161 05162 CONNECTION_LOCK (connection); 05163 05164 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05165 result = FALSE; 05166 else 05167 result = _dbus_transport_get_adt_audit_session_data (connection->transport, 05168 data, 05169 data_size); 05170 CONNECTION_UNLOCK (connection); 05171 05172 return result; 05173 } 05174 05197 void 05198 dbus_connection_set_unix_user_function (DBusConnection *connection, 05199 DBusAllowUnixUserFunction function, 05200 void *data, 05201 DBusFreeFunction free_data_function) 05202 { 05203 void *old_data = NULL; 05204 DBusFreeFunction old_free_function = NULL; 05205 05206 _dbus_return_if_fail (connection != NULL); 05207 05208 CONNECTION_LOCK (connection); 05209 _dbus_transport_set_unix_user_function (connection->transport, 05210 function, data, free_data_function, 05211 &old_data, &old_free_function); 05212 CONNECTION_UNLOCK (connection); 05213 05214 if (old_free_function != NULL) 05215 (* old_free_function) (old_data); 05216 } 05217 05249 dbus_bool_t 05250 dbus_connection_get_windows_user (DBusConnection *connection, 05251 char **windows_sid_p) 05252 { 05253 dbus_bool_t result; 05254 05255 _dbus_return_val_if_fail (connection != NULL, FALSE); 05256 _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE); 05257 05258 CONNECTION_LOCK (connection); 05259 05260 if (!_dbus_transport_get_is_authenticated (connection->transport)) 05261 result = FALSE; 05262 else 05263 result = _dbus_transport_get_windows_user (connection->transport, 05264 windows_sid_p); 05265 05266 #ifdef DBUS_UNIX 05267 _dbus_assert (!result); 05268 #endif 05269 05270 CONNECTION_UNLOCK (connection); 05271 05272 return result; 05273 } 05274 05296 void 05297 dbus_connection_set_windows_user_function (DBusConnection *connection, 05298 DBusAllowWindowsUserFunction function, 05299 void *data, 05300 DBusFreeFunction free_data_function) 05301 { 05302 void *old_data = NULL; 05303 DBusFreeFunction old_free_function = NULL; 05304 05305 _dbus_return_if_fail (connection != NULL); 05306 05307 CONNECTION_LOCK (connection); 05308 _dbus_transport_set_windows_user_function (connection->transport, 05309 function, data, free_data_function, 05310 &old_data, &old_free_function); 05311 CONNECTION_UNLOCK (connection); 05312 05313 if (old_free_function != NULL) 05314 (* old_free_function) (old_data); 05315 } 05316 05343 void 05344 dbus_connection_set_allow_anonymous (DBusConnection *connection, 05345 dbus_bool_t value) 05346 { 05347 _dbus_return_if_fail (connection != NULL); 05348 05349 CONNECTION_LOCK (connection); 05350 _dbus_transport_set_allow_anonymous (connection->transport, value); 05351 CONNECTION_UNLOCK (connection); 05352 } 05353 05371 void 05372 dbus_connection_set_route_peer_messages (DBusConnection *connection, 05373 dbus_bool_t value) 05374 { 05375 _dbus_return_if_fail (connection != NULL); 05376 05377 CONNECTION_LOCK (connection); 05378 connection->route_peer_messages = TRUE; 05379 CONNECTION_UNLOCK (connection); 05380 } 05381 05403 dbus_bool_t 05404 dbus_connection_add_filter (DBusConnection *connection, 05405 DBusHandleMessageFunction function, 05406 void *user_data, 05407 DBusFreeFunction free_data_function) 05408 { 05409 DBusMessageFilter *filter; 05410 05411 _dbus_return_val_if_fail (connection != NULL, FALSE); 05412 _dbus_return_val_if_fail (function != NULL, FALSE); 05413 05414 filter = dbus_new0 (DBusMessageFilter, 1); 05415 if (filter == NULL) 05416 return FALSE; 05417 05418 filter->refcount.value = 1; 05419 05420 CONNECTION_LOCK (connection); 05421 05422 if (!_dbus_list_append (&connection->filter_list, 05423 filter)) 05424 { 05425 _dbus_message_filter_unref (filter); 05426 CONNECTION_UNLOCK (connection); 05427 return FALSE; 05428 } 05429 05430 /* Fill in filter after all memory allocated, 05431 * so we don't run the free_user_data_function 05432 * if the add_filter() fails 05433 */ 05434 05435 filter->function = function; 05436 filter->user_data = user_data; 05437 filter->free_user_data_function = free_data_function; 05438 05439 CONNECTION_UNLOCK (connection); 05440 return TRUE; 05441 } 05442 05455 void 05456 dbus_connection_remove_filter (DBusConnection *connection, 05457 DBusHandleMessageFunction function, 05458 void *user_data) 05459 { 05460 DBusList *link; 05461 DBusMessageFilter *filter; 05462 05463 _dbus_return_if_fail (connection != NULL); 05464 _dbus_return_if_fail (function != NULL); 05465 05466 CONNECTION_LOCK (connection); 05467 05468 filter = NULL; 05469 05470 link = _dbus_list_get_last_link (&connection->filter_list); 05471 while (link != NULL) 05472 { 05473 filter = link->data; 05474 05475 if (filter->function == function && 05476 filter->user_data == user_data) 05477 { 05478 _dbus_list_remove_link (&connection->filter_list, link); 05479 filter->function = NULL; 05480 05481 break; 05482 } 05483 05484 link = _dbus_list_get_prev_link (&connection->filter_list, link); 05485 filter = NULL; 05486 } 05487 05488 CONNECTION_UNLOCK (connection); 05489 05490 #ifndef DBUS_DISABLE_CHECKS 05491 if (filter == NULL) 05492 { 05493 _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n", 05494 function, user_data); 05495 return; 05496 } 05497 #endif 05498 05499 /* Call application code */ 05500 if (filter->free_user_data_function) 05501 (* filter->free_user_data_function) (filter->user_data); 05502 05503 filter->free_user_data_function = NULL; 05504 filter->user_data = NULL; 05505 05506 _dbus_message_filter_unref (filter); 05507 } 05508 05521 dbus_bool_t 05522 dbus_connection_try_register_object_path (DBusConnection *connection, 05523 const char *path, 05524 const DBusObjectPathVTable *vtable, 05525 void *user_data, 05526 DBusError *error) 05527 { 05528 char **decomposed_path; 05529 dbus_bool_t retval; 05530 05531 _dbus_return_val_if_fail (connection != NULL, FALSE); 05532 _dbus_return_val_if_fail (path != NULL, FALSE); 05533 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05534 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05535 05536 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05537 return FALSE; 05538 05539 CONNECTION_LOCK (connection); 05540 05541 retval = _dbus_object_tree_register (connection->objects, 05542 FALSE, 05543 (const char **) decomposed_path, vtable, 05544 user_data, error); 05545 05546 CONNECTION_UNLOCK (connection); 05547 05548 dbus_free_string_array (decomposed_path); 05549 05550 return retval; 05551 } 05552 05567 dbus_bool_t 05568 dbus_connection_register_object_path (DBusConnection *connection, 05569 const char *path, 05570 const DBusObjectPathVTable *vtable, 05571 void *user_data) 05572 { 05573 char **decomposed_path; 05574 dbus_bool_t retval; 05575 DBusError error = DBUS_ERROR_INIT; 05576 05577 _dbus_return_val_if_fail (connection != NULL, FALSE); 05578 _dbus_return_val_if_fail (path != NULL, FALSE); 05579 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05580 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05581 05582 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05583 return FALSE; 05584 05585 CONNECTION_LOCK (connection); 05586 05587 retval = _dbus_object_tree_register (connection->objects, 05588 FALSE, 05589 (const char **) decomposed_path, vtable, 05590 user_data, &error); 05591 05592 CONNECTION_UNLOCK (connection); 05593 05594 dbus_free_string_array (decomposed_path); 05595 05596 if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE)) 05597 { 05598 _dbus_warn ("%s\n", error.message); 05599 dbus_error_free (&error); 05600 return FALSE; 05601 } 05602 05603 return retval; 05604 } 05605 05620 dbus_bool_t 05621 dbus_connection_try_register_fallback (DBusConnection *connection, 05622 const char *path, 05623 const DBusObjectPathVTable *vtable, 05624 void *user_data, 05625 DBusError *error) 05626 { 05627 char **decomposed_path; 05628 dbus_bool_t retval; 05629 05630 _dbus_return_val_if_fail (connection != NULL, FALSE); 05631 _dbus_return_val_if_fail (path != NULL, FALSE); 05632 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05633 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05634 05635 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05636 return FALSE; 05637 05638 CONNECTION_LOCK (connection); 05639 05640 retval = _dbus_object_tree_register (connection->objects, 05641 TRUE, 05642 (const char **) decomposed_path, vtable, 05643 user_data, error); 05644 05645 CONNECTION_UNLOCK (connection); 05646 05647 dbus_free_string_array (decomposed_path); 05648 05649 return retval; 05650 } 05651 05668 dbus_bool_t 05669 dbus_connection_register_fallback (DBusConnection *connection, 05670 const char *path, 05671 const DBusObjectPathVTable *vtable, 05672 void *user_data) 05673 { 05674 char **decomposed_path; 05675 dbus_bool_t retval; 05676 DBusError error = DBUS_ERROR_INIT; 05677 05678 _dbus_return_val_if_fail (connection != NULL, FALSE); 05679 _dbus_return_val_if_fail (path != NULL, FALSE); 05680 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05681 _dbus_return_val_if_fail (vtable != NULL, FALSE); 05682 05683 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05684 return FALSE; 05685 05686 CONNECTION_LOCK (connection); 05687 05688 retval = _dbus_object_tree_register (connection->objects, 05689 TRUE, 05690 (const char **) decomposed_path, vtable, 05691 user_data, &error); 05692 05693 CONNECTION_UNLOCK (connection); 05694 05695 dbus_free_string_array (decomposed_path); 05696 05697 if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE)) 05698 { 05699 _dbus_warn ("%s\n", error.message); 05700 dbus_error_free (&error); 05701 return FALSE; 05702 } 05703 05704 return retval; 05705 } 05706 05716 dbus_bool_t 05717 dbus_connection_unregister_object_path (DBusConnection *connection, 05718 const char *path) 05719 { 05720 char **decomposed_path; 05721 05722 _dbus_return_val_if_fail (connection != NULL, FALSE); 05723 _dbus_return_val_if_fail (path != NULL, FALSE); 05724 _dbus_return_val_if_fail (path[0] == '/', FALSE); 05725 05726 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05727 return FALSE; 05728 05729 CONNECTION_LOCK (connection); 05730 05731 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path); 05732 05733 dbus_free_string_array (decomposed_path); 05734 05735 return TRUE; 05736 } 05737 05748 dbus_bool_t 05749 dbus_connection_get_object_path_data (DBusConnection *connection, 05750 const char *path, 05751 void **data_p) 05752 { 05753 char **decomposed_path; 05754 05755 _dbus_return_val_if_fail (connection != NULL, FALSE); 05756 _dbus_return_val_if_fail (path != NULL, FALSE); 05757 _dbus_return_val_if_fail (data_p != NULL, FALSE); 05758 05759 *data_p = NULL; 05760 05761 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 05762 return FALSE; 05763 05764 CONNECTION_LOCK (connection); 05765 05766 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path); 05767 05768 CONNECTION_UNLOCK (connection); 05769 05770 dbus_free_string_array (decomposed_path); 05771 05772 return TRUE; 05773 } 05774 05785 dbus_bool_t 05786 dbus_connection_list_registered (DBusConnection *connection, 05787 const char *parent_path, 05788 char ***child_entries) 05789 { 05790 char **decomposed_path; 05791 dbus_bool_t retval; 05792 _dbus_return_val_if_fail (connection != NULL, FALSE); 05793 _dbus_return_val_if_fail (parent_path != NULL, FALSE); 05794 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE); 05795 _dbus_return_val_if_fail (child_entries != NULL, FALSE); 05796 05797 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL)) 05798 return FALSE; 05799 05800 CONNECTION_LOCK (connection); 05801 05802 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects, 05803 (const char **) decomposed_path, 05804 child_entries); 05805 dbus_free_string_array (decomposed_path); 05806 05807 return retval; 05808 } 05809 05810 static DBusDataSlotAllocator slot_allocator; 05811 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots); 05812 05827 dbus_bool_t 05828 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p) 05829 { 05830 return _dbus_data_slot_allocator_alloc (&slot_allocator, 05831 &_DBUS_LOCK_NAME (connection_slots), 05832 slot_p); 05833 } 05834 05846 void 05847 dbus_connection_free_data_slot (dbus_int32_t *slot_p) 05848 { 05849 _dbus_return_if_fail (*slot_p >= 0); 05850 05851 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 05852 } 05853 05876 dbus_bool_t 05877 dbus_connection_set_data (DBusConnection *connection, 05878 dbus_int32_t slot, 05879 void *data, 05880 DBusFreeFunction free_data_func) 05881 { 05882 DBusFreeFunction old_free_func; 05883 void *old_data; 05884 dbus_bool_t retval; 05885 05886 _dbus_return_val_if_fail (connection != NULL, FALSE); 05887 _dbus_return_val_if_fail (slot >= 0, FALSE); 05888 05889 SLOTS_LOCK (connection); 05890 05891 retval = _dbus_data_slot_list_set (&slot_allocator, 05892 &connection->slot_list, 05893 slot, data, free_data_func, 05894 &old_free_func, &old_data); 05895 05896 SLOTS_UNLOCK (connection); 05897 05898 if (retval) 05899 { 05900 /* Do the actual free outside the connection lock */ 05901 if (old_free_func) 05902 (* old_free_func) (old_data); 05903 } 05904 05905 return retval; 05906 } 05907 05925 void* 05926 dbus_connection_get_data (DBusConnection *connection, 05927 dbus_int32_t slot) 05928 { 05929 void *res; 05930 05931 _dbus_return_val_if_fail (connection != NULL, NULL); 05932 05933 SLOTS_LOCK (connection); 05934 05935 res = _dbus_data_slot_list_get (&slot_allocator, 05936 &connection->slot_list, 05937 slot); 05938 05939 SLOTS_UNLOCK (connection); 05940 05941 return res; 05942 } 05943 05950 void 05951 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe) 05952 { 05953 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE; 05954 } 05955 05964 void 05965 dbus_connection_set_max_message_size (DBusConnection *connection, 05966 long size) 05967 { 05968 _dbus_return_if_fail (connection != NULL); 05969 05970 CONNECTION_LOCK (connection); 05971 _dbus_transport_set_max_message_size (connection->transport, 05972 size); 05973 CONNECTION_UNLOCK (connection); 05974 } 05975 05982 long 05983 dbus_connection_get_max_message_size (DBusConnection *connection) 05984 { 05985 long res; 05986 05987 _dbus_return_val_if_fail (connection != NULL, 0); 05988 05989 CONNECTION_LOCK (connection); 05990 res = _dbus_transport_get_max_message_size (connection->transport); 05991 CONNECTION_UNLOCK (connection); 05992 return res; 05993 } 05994 06003 void 06004 dbus_connection_set_max_message_unix_fds (DBusConnection *connection, 06005 long n) 06006 { 06007 _dbus_return_if_fail (connection != NULL); 06008 06009 CONNECTION_LOCK (connection); 06010 _dbus_transport_set_max_message_unix_fds (connection->transport, 06011 n); 06012 CONNECTION_UNLOCK (connection); 06013 } 06014 06021 long 06022 dbus_connection_get_max_message_unix_fds (DBusConnection *connection) 06023 { 06024 long res; 06025 06026 _dbus_return_val_if_fail (connection != NULL, 0); 06027 06028 CONNECTION_LOCK (connection); 06029 res = _dbus_transport_get_max_message_unix_fds (connection->transport); 06030 CONNECTION_UNLOCK (connection); 06031 return res; 06032 } 06033 06059 void 06060 dbus_connection_set_max_received_size (DBusConnection *connection, 06061 long size) 06062 { 06063 _dbus_return_if_fail (connection != NULL); 06064 06065 CONNECTION_LOCK (connection); 06066 _dbus_transport_set_max_received_size (connection->transport, 06067 size); 06068 CONNECTION_UNLOCK (connection); 06069 } 06070 06077 long 06078 dbus_connection_get_max_received_size (DBusConnection *connection) 06079 { 06080 long res; 06081 06082 _dbus_return_val_if_fail (connection != NULL, 0); 06083 06084 CONNECTION_LOCK (connection); 06085 res = _dbus_transport_get_max_received_size (connection->transport); 06086 CONNECTION_UNLOCK (connection); 06087 return res; 06088 } 06089 06101 void 06102 dbus_connection_set_max_received_unix_fds (DBusConnection *connection, 06103 long n) 06104 { 06105 _dbus_return_if_fail (connection != NULL); 06106 06107 CONNECTION_LOCK (connection); 06108 _dbus_transport_set_max_received_unix_fds (connection->transport, 06109 n); 06110 CONNECTION_UNLOCK (connection); 06111 } 06112 06119 long 06120 dbus_connection_get_max_received_unix_fds (DBusConnection *connection) 06121 { 06122 long res; 06123 06124 _dbus_return_val_if_fail (connection != NULL, 0); 06125 06126 CONNECTION_LOCK (connection); 06127 res = _dbus_transport_get_max_received_unix_fds (connection->transport); 06128 CONNECTION_UNLOCK (connection); 06129 return res; 06130 } 06131 06142 long 06143 dbus_connection_get_outgoing_size (DBusConnection *connection) 06144 { 06145 long res; 06146 06147 _dbus_return_val_if_fail (connection != NULL, 0); 06148 06149 CONNECTION_LOCK (connection); 06150 res = _dbus_counter_get_size_value (connection->outgoing_counter); 06151 CONNECTION_UNLOCK (connection); 06152 return res; 06153 } 06154 06162 long 06163 dbus_connection_get_outgoing_unix_fds (DBusConnection *connection) 06164 { 06165 long res; 06166 06167 _dbus_return_val_if_fail (connection != NULL, 0); 06168 06169 CONNECTION_LOCK (connection); 06170 res = _dbus_counter_get_unix_fd_value (connection->outgoing_counter); 06171 CONNECTION_UNLOCK (connection); 06172 return res; 06173 } 06174
1.7.4