Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

dbus-connection.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */ 00002 /* dbus-connection.c DBusConnection object 00003 * 00004 * Copyright (C) 2002, 2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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-list.h" 00033 #include "dbus-hash.h" 00034 #include "dbus-message-internal.h" 00035 #include "dbus-threads.h" 00036 #include "dbus-protocol.h" 00037 #include "dbus-dataslot.h" 00038 #include "dbus-string.h" 00039 #include "dbus-pending-call.h" 00040 #include "dbus-object-tree.h" 00041 #include "dbus-marshal.h" 00042 00043 #if 0 00044 #define CONNECTION_LOCK(connection) do { \ 00045 _dbus_verbose (" LOCK: %s\n", _DBUS_FUNCTION_NAME); \ 00046 dbus_mutex_lock ((connection)->mutex); \ 00047 } while (0) 00048 #define CONNECTION_UNLOCK(connection) do { \ 00049 _dbus_verbose (" UNLOCK: %s\n", _DBUS_FUNCTION_NAME); \ 00050 dbus_mutex_unlock ((connection)->mutex); \ 00051 } while (0) 00052 #else 00053 #define CONNECTION_LOCK(connection) dbus_mutex_lock ((connection)->mutex) 00054 #define CONNECTION_UNLOCK(connection) dbus_mutex_unlock ((connection)->mutex) 00055 #endif 00056 00134 typedef struct DBusMessageFilter DBusMessageFilter; 00135 00139 struct DBusMessageFilter 00140 { 00141 DBusAtomic refcount; 00142 DBusHandleMessageFunction function; 00143 void *user_data; 00144 DBusFreeFunction free_user_data_function; 00145 }; 00146 00147 00151 struct DBusPreallocatedSend 00152 { 00153 DBusConnection *connection; 00154 DBusList *queue_link; 00155 DBusList *counter_link; 00156 }; 00157 00158 static dbus_bool_t _dbus_modify_sigpipe = TRUE; 00159 00163 struct DBusConnection 00164 { 00165 DBusAtomic refcount; 00167 DBusMutex *mutex; 00169 dbus_bool_t dispatch_acquired; 00170 DBusCondVar *dispatch_cond; 00172 dbus_bool_t io_path_acquired; 00173 DBusCondVar *io_path_cond; 00175 DBusList *outgoing_messages; 00176 DBusList *incoming_messages; 00178 DBusMessage *message_borrowed; 00179 DBusCondVar *message_returned_cond; 00181 int n_outgoing; 00182 int n_incoming; 00184 DBusCounter *outgoing_counter; 00186 DBusTransport *transport; 00187 DBusWatchList *watches; 00188 DBusTimeoutList *timeouts; 00190 DBusList *filter_list; 00192 DBusDataSlotList slot_list; 00194 DBusHashTable *pending_replies; 00196 dbus_uint32_t client_serial; 00197 DBusList *disconnect_message_link; 00199 DBusWakeupMainFunction wakeup_main_function; 00200 void *wakeup_main_data; 00201 DBusFreeFunction free_wakeup_main_data; 00203 DBusDispatchStatusFunction dispatch_status_function; 00204 void *dispatch_status_data; 00205 DBusFreeFunction free_dispatch_status_data; 00207 DBusDispatchStatus last_dispatch_status; 00209 DBusList *link_cache; 00212 DBusObjectTree *objects; 00214 unsigned int exit_on_disconnect : 1; 00215 }; 00216 00217 static void _dbus_connection_remove_timeout_locked (DBusConnection *connection, 00218 DBusTimeout *timeout); 00219 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection); 00220 static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection, 00221 DBusDispatchStatus new_status); 00222 static void _dbus_connection_last_unref (DBusConnection *connection); 00223 00224 static DBusMessageFilter * 00225 _dbus_message_filter_ref (DBusMessageFilter *filter) 00226 { 00227 _dbus_assert (filter->refcount.value > 0); 00228 _dbus_atomic_inc (&filter->refcount); 00229 00230 return filter; 00231 } 00232 00233 static void 00234 _dbus_message_filter_unref (DBusMessageFilter *filter) 00235 { 00236 _dbus_assert (filter->refcount.value > 0); 00237 00238 if (_dbus_atomic_dec (&filter->refcount) == 1) 00239 { 00240 if (filter->free_user_data_function) 00241 (* filter->free_user_data_function) (filter->user_data); 00242 00243 dbus_free (filter); 00244 } 00245 } 00246 00252 void 00253 _dbus_connection_lock (DBusConnection *connection) 00254 { 00255 CONNECTION_LOCK (connection); 00256 } 00257 00263 void 00264 _dbus_connection_unlock (DBusConnection *connection) 00265 { 00266 CONNECTION_UNLOCK (connection); 00267 } 00268 00276 static void 00277 _dbus_connection_wakeup_mainloop (DBusConnection *connection) 00278 { 00279 if (connection->wakeup_main_function) 00280 (*connection->wakeup_main_function) (connection->wakeup_main_data); 00281 } 00282 00283 #ifdef DBUS_BUILD_TESTS 00284 /* For now this function isn't used */ 00294 dbus_bool_t 00295 _dbus_connection_queue_received_message (DBusConnection *connection, 00296 DBusMessage *message) 00297 { 00298 DBusList *link; 00299 00300 link = _dbus_list_alloc_link (message); 00301 if (link == NULL) 00302 return FALSE; 00303 00304 dbus_message_ref (message); 00305 _dbus_connection_queue_received_message_link (connection, link); 00306 00307 return TRUE; 00308 } 00309 #endif 00310 00319 void 00320 _dbus_connection_queue_received_message_link (DBusConnection *connection, 00321 DBusList *link) 00322 { 00323 DBusPendingCall *pending; 00324 dbus_int32_t reply_serial; 00325 DBusMessage *message; 00326 00327 _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport)); 00328 00329 _dbus_list_append_link (&connection->incoming_messages, 00330 link); 00331 message = link->data; 00332 00333 /* If this is a reply we're waiting on, remove timeout for it */ 00334 reply_serial = dbus_message_get_reply_serial (message); 00335 if (reply_serial != -1) 00336 { 00337 pending = _dbus_hash_table_lookup_int (connection->pending_replies, 00338 reply_serial); 00339 if (pending != NULL) 00340 { 00341 if (pending->timeout_added) 00342 _dbus_connection_remove_timeout_locked (connection, 00343 pending->timeout); 00344 00345 pending->timeout_added = FALSE; 00346 } 00347 } 00348 00349 connection->n_incoming += 1; 00350 00351 _dbus_connection_wakeup_mainloop (connection); 00352 00353 _dbus_verbose ("Message %p (%d %s '%s') added to incoming queue %p, %d incoming\n", 00354 message, 00355 dbus_message_get_type (message), 00356 dbus_message_get_interface (message) ? 00357 dbus_message_get_interface (message) : 00358 "no interface", 00359 dbus_message_get_signature (message), 00360 connection, 00361 connection->n_incoming); 00362 } 00363 00374 static void 00375 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection, 00376 DBusList *link) 00377 { 00378 _dbus_list_append_link (&connection->incoming_messages, link); 00379 00380 connection->n_incoming += 1; 00381 00382 _dbus_connection_wakeup_mainloop (connection); 00383 00384 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n", 00385 link->data, connection, connection->n_incoming); 00386 } 00387 00388 00395 dbus_bool_t 00396 _dbus_connection_have_messages_to_send (DBusConnection *connection) 00397 { 00398 return connection->outgoing_messages != NULL; 00399 } 00400 00408 DBusMessage* 00409 _dbus_connection_get_message_to_send (DBusConnection *connection) 00410 { 00411 return _dbus_list_get_last (&connection->outgoing_messages); 00412 } 00413 00422 void 00423 _dbus_connection_message_sent (DBusConnection *connection, 00424 DBusMessage *message) 00425 { 00426 DBusList *link; 00427 00428 _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport)); 00429 00430 link = _dbus_list_get_last_link (&connection->outgoing_messages); 00431 _dbus_assert (link != NULL); 00432 _dbus_assert (link->data == message); 00433 00434 /* Save this link in the link cache */ 00435 _dbus_list_unlink (&connection->outgoing_messages, 00436 link); 00437 _dbus_list_prepend_link (&connection->link_cache, link); 00438 00439 connection->n_outgoing -= 1; 00440 00441 _dbus_verbose ("Message %p (%d %s '%s') removed from outgoing queue %p, %d left to send\n", 00442 message, 00443 dbus_message_get_type (message), 00444 dbus_message_get_interface (message) ? 00445 dbus_message_get_interface (message) : 00446 "no interface", 00447 dbus_message_get_signature (message), 00448 connection, connection->n_outgoing); 00449 00450 /* Save this link in the link cache also */ 00451 _dbus_message_remove_size_counter (message, connection->outgoing_counter, 00452 &link); 00453 _dbus_list_prepend_link (&connection->link_cache, link); 00454 00455 dbus_message_unref (message); 00456 00457 if (connection->n_outgoing == 0) 00458 _dbus_transport_messages_pending (connection->transport, 00459 connection->n_outgoing); 00460 } 00461 00472 dbus_bool_t 00473 _dbus_connection_add_watch (DBusConnection *connection, 00474 DBusWatch *watch) 00475 { 00476 if (connection->watches) /* null during finalize */ 00477 return _dbus_watch_list_add_watch (connection->watches, 00478 watch); 00479 else 00480 return FALSE; 00481 } 00482 00491 void 00492 _dbus_connection_remove_watch (DBusConnection *connection, 00493 DBusWatch *watch) 00494 { 00495 if (connection->watches) /* null during finalize */ 00496 _dbus_watch_list_remove_watch (connection->watches, 00497 watch); 00498 } 00499 00509 void 00510 _dbus_connection_toggle_watch (DBusConnection *connection, 00511 DBusWatch *watch, 00512 dbus_bool_t enabled) 00513 { 00514 if (connection->watches) /* null during finalize */ 00515 _dbus_watch_list_toggle_watch (connection->watches, 00516 watch, enabled); 00517 } 00518 00530 dbus_bool_t 00531 _dbus_connection_add_timeout (DBusConnection *connection, 00532 DBusTimeout *timeout) 00533 { 00534 if (connection->timeouts) /* null during finalize */ 00535 return _dbus_timeout_list_add_timeout (connection->timeouts, 00536 timeout); 00537 else 00538 return FALSE; 00539 } 00540 00549 void 00550 _dbus_connection_remove_timeout (DBusConnection *connection, 00551 DBusTimeout *timeout) 00552 { 00553 if (connection->timeouts) /* null during finalize */ 00554 _dbus_timeout_list_remove_timeout (connection->timeouts, 00555 timeout); 00556 } 00557 00558 static void 00559 _dbus_connection_remove_timeout_locked (DBusConnection *connection, 00560 DBusTimeout *timeout) 00561 { 00562 CONNECTION_LOCK (connection); 00563 _dbus_connection_remove_timeout (connection, timeout); 00564 CONNECTION_UNLOCK (connection); 00565 } 00566 00576 void 00577 _dbus_connection_toggle_timeout (DBusConnection *connection, 00578 DBusTimeout *timeout, 00579 dbus_bool_t enabled) 00580 { 00581 if (connection->timeouts) /* null during finalize */ 00582 _dbus_timeout_list_toggle_timeout (connection->timeouts, 00583 timeout, enabled); 00584 } 00585 00586 static dbus_bool_t 00587 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection, 00588 DBusPendingCall *pending) 00589 { 00590 _dbus_assert (pending->reply_serial != 0); 00591 00592 if (!_dbus_connection_add_timeout (connection, pending->timeout)) 00593 return FALSE; 00594 00595 if (!_dbus_hash_table_insert_int (connection->pending_replies, 00596 pending->reply_serial, 00597 pending)) 00598 { 00599 _dbus_connection_remove_timeout (connection, pending->timeout); 00600 return FALSE; 00601 } 00602 00603 pending->timeout_added = TRUE; 00604 pending->connection = connection; 00605 00606 dbus_pending_call_ref (pending); 00607 00608 return TRUE; 00609 } 00610 00611 static void 00612 free_pending_call_on_hash_removal (void *data) 00613 { 00614 DBusPendingCall *pending; 00615 00616 if (data == NULL) 00617 return; 00618 00619 pending = data; 00620 00621 if (pending->connection) 00622 { 00623 if (pending->timeout_added) 00624 { 00625 _dbus_connection_remove_timeout (pending->connection, 00626 pending->timeout); 00627 pending->timeout_added = FALSE; 00628 } 00629 00630 pending->connection = NULL; 00631 00632 dbus_pending_call_unref (pending); 00633 } 00634 } 00635 00636 static void 00637 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection, 00638 DBusPendingCall *pending) 00639 { 00640 /* The idea here is to avoid finalizing the pending call 00641 * with the lock held, since there's a destroy notifier 00642 * in pending call that goes out to application code. 00643 */ 00644 dbus_pending_call_ref (pending); 00645 _dbus_hash_table_remove_int (connection->pending_replies, 00646 pending->reply_serial); 00647 CONNECTION_UNLOCK (connection); 00648 dbus_pending_call_unref (pending); 00649 } 00650 00659 void 00660 _dbus_connection_remove_pending_call (DBusConnection *connection, 00661 DBusPendingCall *pending) 00662 { 00663 CONNECTION_LOCK (connection); 00664 _dbus_connection_detach_pending_call_and_unlock (connection, pending); 00665 } 00666 00675 void 00676 _dbus_pending_call_complete_and_unlock (DBusPendingCall *pending, 00677 DBusMessage *message) 00678 { 00679 if (message == NULL) 00680 { 00681 message = pending->timeout_link->data; 00682 _dbus_list_clear (&pending->timeout_link); 00683 } 00684 else 00685 dbus_message_ref (message); 00686 00687 _dbus_verbose (" handing message %p (%s) to pending call serial %u\n", 00688 message, 00689 dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN ? 00690 "method return" : 00691 dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ? 00692 "error" : "other type", 00693 pending->reply_serial); 00694 00695 _dbus_assert (pending->reply == NULL); 00696 _dbus_assert (pending->reply_serial == dbus_message_get_reply_serial (message)); 00697 pending->reply = message; 00698 00699 dbus_pending_call_ref (pending); /* in case there's no app with a ref held */ 00700 _dbus_connection_detach_pending_call_and_unlock (pending->connection, pending); 00701 00702 /* Must be called unlocked since it invokes app callback */ 00703 _dbus_pending_call_notify (pending); 00704 dbus_pending_call_unref (pending); 00705 } 00706 00716 static dbus_bool_t 00717 _dbus_connection_acquire_io_path (DBusConnection *connection, 00718 int timeout_milliseconds) 00719 { 00720 dbus_bool_t res = TRUE; 00721 00722 if (connection->io_path_acquired) 00723 { 00724 if (timeout_milliseconds != -1) 00725 res = dbus_condvar_wait_timeout (connection->io_path_cond, 00726 connection->mutex, 00727 timeout_milliseconds); 00728 else 00729 dbus_condvar_wait (connection->io_path_cond, connection->mutex); 00730 } 00731 00732 if (res) 00733 { 00734 _dbus_assert (!connection->io_path_acquired); 00735 00736 connection->io_path_acquired = TRUE; 00737 } 00738 00739 return res; 00740 } 00741 00749 static void 00750 _dbus_connection_release_io_path (DBusConnection *connection) 00751 { 00752 _dbus_assert (connection->io_path_acquired); 00753 00754 connection->io_path_acquired = FALSE; 00755 dbus_condvar_wake_one (connection->io_path_cond); 00756 } 00757 00758 00785 void 00786 _dbus_connection_do_iteration (DBusConnection *connection, 00787 unsigned int flags, 00788 int timeout_milliseconds) 00789 { 00790 if (connection->n_outgoing == 0) 00791 flags &= ~DBUS_ITERATION_DO_WRITING; 00792 00793 if (_dbus_connection_acquire_io_path (connection, 00794 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0)) 00795 { 00796 _dbus_transport_do_iteration (connection->transport, 00797 flags, timeout_milliseconds); 00798 _dbus_connection_release_io_path (connection); 00799 } 00800 } 00801 00811 DBusConnection* 00812 _dbus_connection_new_for_transport (DBusTransport *transport) 00813 { 00814 DBusConnection *connection; 00815 DBusWatchList *watch_list; 00816 DBusTimeoutList *timeout_list; 00817 DBusHashTable *pending_replies; 00818 DBusMutex *mutex; 00819 DBusCondVar *message_returned_cond; 00820 DBusCondVar *dispatch_cond; 00821 DBusCondVar *io_path_cond; 00822 DBusList *disconnect_link; 00823 DBusMessage *disconnect_message; 00824 DBusCounter *outgoing_counter; 00825 DBusObjectTree *objects; 00826 00827 watch_list = NULL; 00828 connection = NULL; 00829 pending_replies = NULL; 00830 timeout_list = NULL; 00831 mutex = NULL; 00832 message_returned_cond = NULL; 00833 dispatch_cond = NULL; 00834 io_path_cond = NULL; 00835 disconnect_link = NULL; 00836 disconnect_message = NULL; 00837 outgoing_counter = NULL; 00838 objects = NULL; 00839 00840 watch_list = _dbus_watch_list_new (); 00841 if (watch_list == NULL) 00842 goto error; 00843 00844 timeout_list = _dbus_timeout_list_new (); 00845 if (timeout_list == NULL) 00846 goto error; 00847 00848 pending_replies = 00849 _dbus_hash_table_new (DBUS_HASH_INT, 00850 NULL, 00851 (DBusFreeFunction)free_pending_call_on_hash_removal); 00852 if (pending_replies == NULL) 00853 goto error; 00854 00855 connection = dbus_new0 (DBusConnection, 1); 00856 if (connection == NULL) 00857 goto error; 00858 00859 mutex = dbus_mutex_new (); 00860 if (mutex == NULL) 00861 goto error; 00862 00863 message_returned_cond = dbus_condvar_new (); 00864 if (message_returned_cond == NULL) 00865 goto error; 00866 00867 dispatch_cond = dbus_condvar_new (); 00868 if (dispatch_cond == NULL) 00869 goto error; 00870 00871 io_path_cond = dbus_condvar_new (); 00872 if (io_path_cond == NULL) 00873 goto error; 00874 00875 disconnect_message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_LOCAL, 00876 DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, 00877 "Disconnected"); 00878 00879 if (disconnect_message == NULL) 00880 goto error; 00881 00882 disconnect_link = _dbus_list_alloc_link (disconnect_message); 00883 if (disconnect_link == NULL) 00884 goto error; 00885 00886 outgoing_counter = _dbus_counter_new (); 00887 if (outgoing_counter == NULL) 00888 goto error; 00889 00890 objects = _dbus_object_tree_new (connection); 00891 if (objects == NULL) 00892 goto error; 00893 00894 if (_dbus_modify_sigpipe) 00895 _dbus_disable_sigpipe (); 00896 00897 connection->refcount.value = 1; 00898 connection->mutex = mutex; 00899 connection->dispatch_cond = dispatch_cond; 00900 connection->io_path_cond = io_path_cond; 00901 connection->message_returned_cond = message_returned_cond; 00902 connection->transport = transport; 00903 connection->watches = watch_list; 00904 connection->timeouts = timeout_list; 00905 connection->pending_replies = pending_replies; 00906 connection->outgoing_counter = outgoing_counter; 00907 connection->filter_list = NULL; 00908 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */ 00909 connection->objects = objects; 00910 connection->exit_on_disconnect = FALSE; 00911 00912 _dbus_data_slot_list_init (&connection->slot_list); 00913 00914 connection->client_serial = 1; 00915 00916 connection->disconnect_message_link = disconnect_link; 00917 00918 if (!_dbus_transport_set_connection (transport, connection)) 00919 goto error; 00920 00921 _dbus_transport_ref (transport); 00922 00923 return connection; 00924 00925 error: 00926 if (disconnect_message != NULL) 00927 dbus_message_unref (disconnect_message); 00928 00929 if (disconnect_link != NULL) 00930 _dbus_list_free_link (disconnect_link); 00931 00932 if (io_path_cond != NULL) 00933 dbus_condvar_free (io_path_cond); 00934 00935 if (dispatch_cond != NULL) 00936 dbus_condvar_free (dispatch_cond); 00937 00938 if (message_returned_cond != NULL) 00939 dbus_condvar_free (message_returned_cond); 00940 00941 if (mutex != NULL) 00942 dbus_mutex_free (mutex); 00943 00944 if (connection != NULL) 00945 dbus_free (connection); 00946 00947 if (pending_replies) 00948 _dbus_hash_table_unref (pending_replies); 00949 00950 if (watch_list) 00951 _dbus_watch_list_free (watch_list); 00952 00953 if (timeout_list) 00954 _dbus_timeout_list_free (timeout_list); 00955 00956 if (outgoing_counter) 00957 _dbus_counter_unref (outgoing_counter); 00958 00959 if (objects) 00960 _dbus_object_tree_unref (objects); 00961 00962 return NULL; 00963 } 00964 00972 DBusConnection * 00973 _dbus_connection_ref_unlocked (DBusConnection *connection) 00974 { 00975 #ifdef DBUS_HAVE_ATOMIC_INT 00976 _dbus_atomic_inc (&connection->refcount); 00977 #else 00978 _dbus_assert (connection->refcount.value > 0); 00979 connection->refcount.value += 1; 00980 #endif 00981 00982 return connection; 00983 } 00984 00991 void 00992 _dbus_connection_unref_unlocked (DBusConnection *connection) 00993 { 00994 dbus_bool_t last_unref; 00995 00996 _dbus_return_if_fail (connection != NULL); 00997 00998 /* The connection lock is better than the global 00999 * lock in the atomic increment fallback 01000 */ 01001 01002 #ifdef DBUS_HAVE_ATOMIC_INT 01003 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1); 01004 #else 01005 _dbus_assert (connection->refcount.value > 0); 01006 01007 connection->refcount.value -= 1; 01008 last_unref = (connection->refcount.value == 0); 01009 #if 0 01010 printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value); 01011 #endif 01012 #endif 01013 01014 if (last_unref) 01015 _dbus_connection_last_unref (connection); 01016 } 01017 01018 static dbus_uint32_t 01019 _dbus_connection_get_next_client_serial (DBusConnection *connection) 01020 { 01021 int serial; 01022 01023 serial = connection->client_serial++; 01024 01025 if (connection->client_serial < 0) 01026 connection->client_serial = 1; 01027 01028 return serial; 01029 } 01030 01044 dbus_bool_t 01045 _dbus_connection_handle_watch (DBusWatch *watch, 01046 unsigned int condition, 01047 void *data) 01048 { 01049 DBusConnection *connection; 01050 dbus_bool_t retval; 01051 DBusDispatchStatus status; 01052 01053 connection = data; 01054 01055 CONNECTION_LOCK (connection); 01056 _dbus_connection_acquire_io_path (connection, -1); 01057 retval = _dbus_transport_handle_watch (connection->transport, 01058 watch, condition); 01059 _dbus_connection_release_io_path (connection); 01060 01061 status = _dbus_connection_get_dispatch_status_unlocked (connection); 01062 01063 /* this calls out to user code */ 01064 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 01065 01066 return retval; 01067 } 01068 01093 DBusConnection* 01094 dbus_connection_open (const char *address, 01095 DBusError *error) 01096 { 01097 DBusConnection *connection; 01098 DBusTransport *transport; 01099 01100 _dbus_return_val_if_fail (address != NULL, NULL); 01101 _dbus_return_val_if_error_is_set (error, NULL); 01102 01103 transport = _dbus_transport_open (address, error); 01104 if (transport == NULL) 01105 { 01106 _DBUS_ASSERT_ERROR_IS_SET (error); 01107 return NULL; 01108 } 01109 01110 connection = _dbus_connection_new_for_transport (transport); 01111 01112 _dbus_transport_unref (transport); 01113 01114 if (connection == NULL) 01115 { 01116 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 01117 return NULL; 01118 } 01119 01120 return connection; 01121 } 01122 01129 DBusConnection * 01130 dbus_connection_ref (DBusConnection *connection) 01131 { 01132 _dbus_return_val_if_fail (connection != NULL, NULL); 01133 01134 /* The connection lock is better than the global 01135 * lock in the atomic increment fallback 01136 */ 01137 01138 #ifdef DBUS_HAVE_ATOMIC_INT 01139 _dbus_atomic_inc (&connection->refcount); 01140 #else 01141 CONNECTION_LOCK (connection); 01142 _dbus_assert (connection->refcount.value > 0); 01143 01144 connection->refcount.value += 1; 01145 CONNECTION_UNLOCK (connection); 01146 #endif 01147 01148 return connection; 01149 } 01150 01151 static void 01152 free_outgoing_message (void *element, 01153 void *data) 01154 { 01155 DBusMessage *message = element; 01156 DBusConnection *connection = data; 01157 01158 _dbus_message_remove_size_counter (message, 01159 connection->outgoing_counter, 01160 NULL); 01161 dbus_message_unref (message); 01162 } 01163 01164 /* This is run without the mutex held, but after the last reference 01165 * to the connection has been dropped we should have no thread-related 01166 * problems 01167 */ 01168 static void 01169 _dbus_connection_last_unref (DBusConnection *connection) 01170 { 01171 DBusList *link; 01172 01173 _dbus_verbose ("Finalizing connection %p\n", connection); 01174 01175 _dbus_assert (connection->refcount.value == 0); 01176 01177 /* You have to disconnect the connection before unref:ing it. Otherwise 01178 * you won't get the disconnected message. 01179 */ 01180 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport)); 01181 01182 /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */ 01183 _dbus_object_tree_free_all_unlocked (connection->objects); 01184 01185 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL); 01186 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL); 01187 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL); 01188 01189 _dbus_watch_list_free (connection->watches); 01190 connection->watches = NULL; 01191 01192 _dbus_timeout_list_free (connection->timeouts); 01193 connection->timeouts = NULL; 01194 01195 _dbus_data_slot_list_free (&connection->slot_list); 01196 01197 link = _dbus_list_get_first_link (&connection->filter_list); 01198 while (link != NULL) 01199 { 01200 DBusMessageFilter *filter = link->data; 01201 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link); 01202 01203 filter->function = NULL; 01204 _dbus_message_filter_unref (filter); /* calls app callback */ 01205 link->data = NULL; 01206 01207 link = next; 01208 } 01209 _dbus_list_clear (&connection->filter_list); 01210 01211 /* ---- Done with stuff that invokes application callbacks */ 01212 01213 _dbus_object_tree_unref (connection->objects); 01214 01215 _dbus_hash_table_unref (connection->pending_replies); 01216 connection->pending_replies = NULL; 01217 01218 _dbus_list_clear (&connection->filter_list); 01219 01220 _dbus_list_foreach (&connection->outgoing_messages, 01221 free_outgoing_message, 01222 connection); 01223 _dbus_list_clear (&connection->outgoing_messages); 01224 01225 _dbus_list_foreach (&connection->incoming_messages, 01226 (DBusForeachFunction) dbus_message_unref, 01227 NULL); 01228 _dbus_list_clear (&connection->incoming_messages); 01229 01230 _dbus_counter_unref (connection->outgoing_counter); 01231 01232 _dbus_transport_unref (connection->transport); 01233 01234 if (connection->disconnect_message_link) 01235 { 01236 DBusMessage *message = connection->disconnect_message_link->data; 01237 dbus_message_unref (message); 01238 _dbus_list_free_link (connection->disconnect_message_link); 01239 } 01240 01241 _dbus_list_clear (&connection->link_cache); 01242 01243 dbus_condvar_free (connection->dispatch_cond); 01244 dbus_condvar_free (connection->io_path_cond); 01245 dbus_condvar_free (connection->message_returned_cond); 01246 01247 dbus_mutex_free (connection->mutex); 01248 01249 dbus_free (connection); 01250 } 01251 01263 void 01264 dbus_connection_unref (DBusConnection *connection) 01265 { 01266 dbus_bool_t last_unref; 01267 01268 _dbus_return_if_fail (connection != NULL); 01269 01270 /* The connection lock is better than the global 01271 * lock in the atomic increment fallback 01272 */ 01273 01274 #ifdef DBUS_HAVE_ATOMIC_INT 01275 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1); 01276 #else 01277 CONNECTION_LOCK (connection); 01278 01279 _dbus_assert (connection->refcount.value > 0); 01280 01281 connection->refcount.value -= 1; 01282 last_unref = (connection->refcount.value == 0); 01283 01284 #if 0 01285 printf ("unref() connection %p count = %d\n", connection, connection->refcount.value); 01286 #endif 01287 01288 CONNECTION_UNLOCK (connection); 01289 #endif 01290 01291 if (last_unref) 01292 _dbus_connection_last_unref (connection); 01293 } 01294 01308 void 01309 dbus_connection_disconnect (DBusConnection *connection) 01310 { 01311 DBusDispatchStatus status; 01312 01313 _dbus_return_if_fail (connection != NULL); 01314 01315 CONNECTION_LOCK (connection); 01316 _dbus_transport_disconnect (connection->transport); 01317 01318 status = _dbus_connection_get_dispatch_status_unlocked (connection); 01319 01320 /* this calls out to user code */ 01321 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 01322 } 01323 01324 static dbus_bool_t 01325 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection) 01326 { 01327 return _dbus_transport_get_is_connected (connection->transport); 01328 } 01329 01340 dbus_bool_t 01341 dbus_connection_get_is_connected (DBusConnection *connection) 01342 { 01343 dbus_bool_t res; 01344 01345 _dbus_return_val_if_fail (connection != NULL, FALSE); 01346 01347 CONNECTION_LOCK (connection); 01348 res = _dbus_connection_get_is_connected_unlocked (connection); 01349 CONNECTION_UNLOCK (connection); 01350 01351 return res; 01352 } 01353 01362 dbus_bool_t 01363 dbus_connection_get_is_authenticated (DBusConnection *connection) 01364 { 01365 dbus_bool_t res; 01366 01367 _dbus_return_val_if_fail (connection != NULL, FALSE); 01368 01369 CONNECTION_LOCK (connection); 01370 res = _dbus_transport_get_is_authenticated (connection->transport); 01371 CONNECTION_UNLOCK (connection); 01372 01373 return res; 01374 } 01375 01389 void 01390 dbus_connection_set_exit_on_disconnect (DBusConnection *connection, 01391 dbus_bool_t exit_on_disconnect) 01392 { 01393 _dbus_return_if_fail (connection != NULL); 01394 01395 CONNECTION_LOCK (connection); 01396 connection->exit_on_disconnect = exit_on_disconnect != FALSE; 01397 CONNECTION_UNLOCK (connection); 01398 } 01399 01400 static DBusPreallocatedSend* 01401 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection) 01402 { 01403 DBusPreallocatedSend *preallocated; 01404 01405 _dbus_return_val_if_fail (connection != NULL, NULL); 01406 01407 preallocated = dbus_new (DBusPreallocatedSend, 1); 01408 if (preallocated == NULL) 01409 return NULL; 01410 01411 if (connection->link_cache != NULL) 01412 { 01413 preallocated->queue_link = 01414 _dbus_list_pop_first_link (&connection->link_cache); 01415 preallocated->queue_link->data = NULL; 01416 } 01417 else 01418 { 01419 preallocated->queue_link = _dbus_list_alloc_link (NULL); 01420 if (preallocated->queue_link == NULL) 01421 goto failed_0; 01422 } 01423 01424 if (connection->link_cache != NULL) 01425 { 01426 preallocated->counter_link = 01427 _dbus_list_pop_first_link (&connection->link_cache); 01428 preallocated->counter_link->data = connection->outgoing_counter; 01429 } 01430 else 01431 { 01432 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter); 01433 if (preallocated->counter_link == NULL) 01434 goto failed_1; 01435 } 01436 01437 _dbus_counter_ref (preallocated->counter_link->data); 01438 01439 preallocated->connection = connection; 01440 01441 return preallocated; 01442 01443 failed_1: 01444 _dbus_list_free_link (preallocated->queue_link); 01445 failed_0: 01446 dbus_free (preallocated); 01447 01448 return NULL; 01449 } 01450 01460 DBusPreallocatedSend* 01461 dbus_connection_preallocate_send (DBusConnection *connection) 01462 { 01463 DBusPreallocatedSend *preallocated; 01464 01465 _dbus_return_val_if_fail (connection != NULL, NULL); 01466 01467 CONNECTION_LOCK (connection); 01468 01469 preallocated = 01470 _dbus_connection_preallocate_send_unlocked (connection); 01471 01472 CONNECTION_UNLOCK (connection); 01473 01474 return preallocated; 01475 } 01476 01486 void 01487 dbus_connection_free_preallocated_send (DBusConnection *connection, 01488 DBusPreallocatedSend *preallocated) 01489 { 01490 _dbus_return_if_fail (connection != NULL); 01491 _dbus_return_if_fail (preallocated != NULL); 01492 _dbus_return_if_fail (connection == preallocated->connection); 01493 01494 _dbus_list_free_link (preallocated->queue_link); 01495 _dbus_counter_unref (preallocated->counter_link->data); 01496 _dbus_list_free_link (preallocated->counter_link); 01497 dbus_free (preallocated); 01498 } 01499 01500 static void 01501 _dbus_connection_send_preallocated_unlocked (DBusConnection *connection, 01502 DBusPreallocatedSend *preallocated, 01503 DBusMessage *message, 01504 dbus_uint32_t *client_serial) 01505 { 01506 dbus_uint32_t serial; 01507 01508 preallocated->queue_link->data = message; 01509 _dbus_list_prepend_link (&connection->outgoing_messages, 01510 preallocated->queue_link); 01511 01512 _dbus_message_add_size_counter_link (message, 01513 preallocated->counter_link); 01514 01515 dbus_free (preallocated); 01516 preallocated = NULL; 01517 01518 dbus_message_ref (message); 01519 01520 connection->n_outgoing += 1; 01521 01522 _dbus_verbose ("Message %p (%d %s '%s') added to outgoing queue %p, %d pending to send\n", 01523 message, 01524 dbus_message_get_type (message), 01525 dbus_message_get_interface (message) ? 01526 dbus_message_get_interface (message) : 01527 "no interface", 01528 dbus_message_get_signature (message), 01529 connection, 01530 connection->n_outgoing); 01531 01532 if (dbus_message_get_serial (message) == 0) 01533 { 01534 serial = _dbus_connection_get_next_client_serial (connection); 01535 _dbus_message_set_serial (message, serial); 01536 if (client_serial) 01537 *client_serial = serial; 01538 } 01539 else 01540 { 01541 if (client_serial) 01542 *client_serial = dbus_message_get_serial (message); 01543 } 01544 01545 _dbus_message_lock (message); 01546 01547 if (connection->n_outgoing == 1) 01548 _dbus_transport_messages_pending (connection->transport, 01549 connection->n_outgoing); 01550 01551 _dbus_connection_wakeup_mainloop (connection); 01552 } 01553 01566 void 01567 dbus_connection_send_preallocated (DBusConnection *connection, 01568 DBusPreallocatedSend *preallocated, 01569 DBusMessage *message, 01570 dbus_uint32_t *client_serial) 01571 { 01572 _dbus_return_if_fail (connection != NULL); 01573 _dbus_return_if_fail (preallocated != NULL); 01574 _dbus_return_if_fail (message != NULL); 01575 _dbus_return_if_fail (preallocated->connection == connection); 01576 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL || 01577 (dbus_message_get_interface (message) != NULL && 01578 dbus_message_get_member (message) != NULL)); 01579 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL || 01580 (dbus_message_get_interface (message) != NULL && 01581 dbus_message_get_member (message) != NULL)); 01582 01583 CONNECTION_LOCK (connection); 01584 _dbus_connection_send_preallocated_unlocked (connection, 01585 preallocated, 01586 message, client_serial); 01587 CONNECTION_UNLOCK (connection); 01588 } 01589 01590 static dbus_bool_t 01591 _dbus_connection_send_unlocked (DBusConnection *connection, 01592 DBusMessage *message, 01593 dbus_uint32_t *client_serial) 01594 { 01595 DBusPreallocatedSend *preallocated; 01596 01597 _dbus_assert (connection != NULL); 01598 _dbus_assert (message != NULL); 01599 01600 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 01601 if (preallocated == NULL) 01602 return FALSE; 01603 01604 01605 _dbus_connection_send_preallocated_unlocked (connection, 01606 preallocated, 01607 message, 01608 client_serial); 01609 return TRUE; 01610 } 01611 01630 dbus_bool_t 01631 dbus_connection_send (DBusConnection *connection, 01632 DBusMessage *message, 01633 dbus_uint32_t *client_serial) 01634 { 01635 _dbus_return_val_if_fail (connection != NULL, FALSE); 01636 _dbus_return_val_if_fail (message != NULL, FALSE); 01637 01638 CONNECTION_LOCK (connection); 01639 01640 if (!_dbus_connection_send_unlocked (connection, message, client_serial)) 01641 { 01642 CONNECTION_UNLOCK (connection); 01643 return FALSE; 01644 } 01645 01646 CONNECTION_UNLOCK (connection); 01647 return TRUE; 01648 } 01649 01650 static dbus_bool_t 01651 reply_handler_timeout (void *data) 01652 { 01653 DBusConnection *connection; 01654 DBusDispatchStatus status; 01655 DBusPendingCall *pending = data; 01656 01657 connection = pending->connection; 01658 01659 CONNECTION_LOCK (connection); 01660 if (pending->timeout_link) 01661 { 01662 _dbus_connection_queue_synthesized_message_link (connection, 01663 pending->timeout_link); 01664 pending->timeout_link = NULL; 01665 } 01666 01667 _dbus_connection_remove_timeout (connection, 01668 pending->timeout); 01669 pending->timeout_added = FALSE; 01670 01671 status = _dbus_connection_get_dispatch_status_unlocked (connection); 01672 01673 /* Unlocks, and calls out to user code */ 01674 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 01675 01676 return TRUE; 01677 } 01678 01716 dbus_bool_t 01717 dbus_connection_send_with_reply (DBusConnection *connection, 01718 DBusMessage *message, 01719 DBusPendingCall **pending_return, 01720 int timeout_milliseconds) 01721 { 01722 DBusPendingCall *pending; 01723 DBusMessage *reply; 01724 DBusList *reply_link; 01725 dbus_int32_t serial = -1; 01726 01727 _dbus_return_val_if_fail (connection != NULL, FALSE); 01728 _dbus_return_val_if_fail (message != NULL, FALSE); 01729 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 01730 01731 if (pending_return) 01732 *pending_return = NULL; 01733 01734 pending = _dbus_pending_call_new (connection, 01735 timeout_milliseconds, 01736 reply_handler_timeout); 01737 01738 if (pending == NULL) 01739 return FALSE; 01740 01741 CONNECTION_LOCK (connection); 01742 01743 /* Assign a serial to the message */ 01744 if (dbus_message_get_serial (message) == 0) 01745 { 01746 serial = _dbus_connection_get_next_client_serial (connection); 01747 _dbus_message_set_serial (message, serial); 01748 } 01749 01750 pending->reply_serial = serial; 01751 01752 reply = dbus_message_new_error (message, DBUS_ERROR_NO_REPLY, 01753 "No reply within specified time"); 01754 if (reply == NULL) 01755 goto error; 01756 01757 reply_link = _dbus_list_alloc_link (reply); 01758 if (reply_link == NULL) 01759 { 01760 CONNECTION_UNLOCK (connection); 01761 dbus_message_unref (reply); 01762 goto error_unlocked; 01763 } 01764 01765 pending->timeout_link = reply_link; 01766 01767 /* Insert the serial in the pending replies hash; 01768 * hash takes a refcount on DBusPendingCall. 01769 * Also, add the timeout. 01770 */ 01771 if (!_dbus_connection_attach_pending_call_unlocked (connection, 01772 pending)) 01773 goto error; 01774 01775 if (!_dbus_connection_send_unlocked (connection, message, NULL)) 01776 { 01777 _dbus_connection_detach_pending_call_and_unlock (connection, 01778 pending); 01779 goto error_unlocked; 01780 } 01781 01782 if (pending_return) 01783 *pending_return = pending; 01784 else 01785 dbus_pending_call_unref (pending); 01786 01787 CONNECTION_UNLOCK (connection); 01788 01789 return TRUE; 01790 01791 error: 01792 CONNECTION_UNLOCK (connection); 01793 error_unlocked: 01794 dbus_pending_call_unref (pending); 01795 return FALSE; 01796 } 01797 01798 static DBusMessage* 01799 check_for_reply_unlocked (DBusConnection *connection, 01800 dbus_uint32_t client_serial) 01801 { 01802 DBusList *link; 01803 01804 link = _dbus_list_get_first_link (&connection->incoming_messages); 01805 01806 while (link != NULL) 01807 { 01808 DBusMessage *reply = link->data; 01809 01810 if (dbus_message_get_reply_serial (reply) == client_serial) 01811 { 01812 _dbus_list_remove_link (&connection->incoming_messages, link); 01813 connection->n_incoming -= 1; 01814 return reply; 01815 } 01816 link = _dbus_list_get_next_link (&connection->incoming_messages, link); 01817 } 01818 01819 return NULL; 01820 } 01821 01839 DBusMessage* 01840 _dbus_connection_block_for_reply (DBusConnection *connection, 01841 dbus_uint32_t client_serial, 01842 int timeout_milliseconds) 01843 { 01844 long start_tv_sec, start_tv_usec; 01845 long end_tv_sec, end_tv_usec; 01846 long tv_sec, tv_usec; 01847 DBusDispatchStatus status; 01848 01849 _dbus_return_val_if_fail (connection != NULL, NULL); 01850 _dbus_return_val_if_fail (client_serial != 0, NULL); 01851 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 01852 01853 if (timeout_milliseconds == -1) 01854 timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE; 01855 01856 /* it would probably seem logical to pass in _DBUS_INT_MAX 01857 * for infinite timeout, but then math below would get 01858 * all overflow-prone, so smack that down. 01859 */ 01860 if (timeout_milliseconds > _DBUS_ONE_HOUR_IN_MILLISECONDS * 6) 01861 timeout_milliseconds = _DBUS_ONE_HOUR_IN_MILLISECONDS * 6; 01862 01863 /* Flush message queue */ 01864 dbus_connection_flush (connection); 01865 01866 CONNECTION_LOCK (connection); 01867 01868 _dbus_get_current_time (&start_tv_sec, &start_tv_usec); 01869 end_tv_sec = start_tv_sec + timeout_milliseconds / 1000; 01870 end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000; 01871 end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND; 01872 end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND; 01873 01874 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec to %ld sec %ld usec\n", 01875 timeout_milliseconds, 01876 client_serial, 01877 start_tv_sec, start_tv_usec, 01878 end_tv_sec, end_tv_usec); 01879 01880 /* Now we wait... */ 01881 /* THREAD TODO: This is busted. What if a dispatch() or pop_message 01882 * gets the message before we do? 01883 */ 01884 /* always block at least once as we know we don't have the reply yet */ 01885 _dbus_connection_do_iteration (connection, 01886 DBUS_ITERATION_DO_READING | 01887 DBUS_ITERATION_BLOCK, 01888 timeout_milliseconds); 01889 01890 recheck_status: 01891 01892 /* queue messages and get status */ 01893 status = _dbus_connection_get_dispatch_status_unlocked (connection); 01894 01895 if (status == DBUS_DISPATCH_DATA_REMAINS) 01896 { 01897 DBusMessage *reply; 01898 01899 reply = check_for_reply_unlocked (connection, client_serial); 01900 if (reply != NULL) 01901 { 01902 status = _dbus_connection_get_dispatch_status_unlocked (connection); 01903 01904 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n"); 01905 01906 /* Unlocks, and calls out to user code */ 01907 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 01908 01909 return reply; 01910 } 01911 } 01912 01913 _dbus_get_current_time (&tv_sec, &tv_usec); 01914 01915 if (!_dbus_connection_get_is_connected_unlocked (connection)) 01916 return NULL; 01917 else if (tv_sec < start_tv_sec) 01918 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n"); 01919 else if (connection->disconnect_message_link == NULL) 01920 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n"); 01921 else if (tv_sec < end_tv_sec || 01922 (tv_sec == end_tv_sec && tv_usec < end_tv_usec)) 01923 { 01924 timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 + 01925 (end_tv_usec - tv_usec) / 1000; 01926 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds); 01927 _dbus_assert (timeout_milliseconds >= 0); 01928 01929 if (status == DBUS_DISPATCH_NEED_MEMORY) 01930 { 01931 /* Try sleeping a bit, as we aren't sure we need to block for reading, 01932 * we may already have a reply in the buffer and just can't process 01933 * it. 01934 */ 01935 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n"); 01936 01937 if (timeout_milliseconds < 100) 01938 ; /* just busy loop */ 01939 else if (timeout_milliseconds <= 1000) 01940 _dbus_sleep_milliseconds (timeout_milliseconds / 3); 01941 else 01942 _dbus_sleep_milliseconds (1000); 01943 } 01944 else 01945 { 01946 /* block again, we don't have the reply buffered yet. */ 01947 _dbus_connection_do_iteration (connection, 01948 DBUS_ITERATION_DO_READING | 01949 DBUS_ITERATION_BLOCK, 01950 timeout_milliseconds); 01951 } 01952 01953 goto recheck_status; 01954 } 01955 01956 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n", 01957 (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000); 01958 01959 /* unlocks and calls out to user code */ 01960 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 01961 01962 return NULL; 01963 } 01964 01987 DBusMessage * 01988 dbus_connection_send_with_reply_and_block (DBusConnection *connection, 01989 DBusMessage *message, 01990 int timeout_milliseconds, 01991 DBusError *error) 01992 { 01993 dbus_uint32_t client_serial; 01994 DBusMessage *reply; 01995 01996 _dbus_return_val_if_fail (connection != NULL, NULL); 01997 _dbus_return_val_if_fail (message != NULL, NULL); 01998 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE); 01999 _dbus_return_val_if_error_is_set (error, NULL); 02000 02001 if (!dbus_connection_send (connection, message, &client_serial)) 02002 { 02003 _DBUS_SET_OOM (error); 02004 return NULL; 02005 } 02006 02007 reply = _dbus_connection_block_for_reply (connection, 02008 client_serial, 02009 timeout_milliseconds); 02010 02011 if (reply == NULL) 02012 { 02013 if (dbus_connection_get_is_connected (connection)) 02014 dbus_set_error (error, DBUS_ERROR_NO_REPLY, "Message did not receive a reply"); 02015 else 02016 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Disconnected prior to receiving a reply"); 02017 02018 return NULL; 02019 } 02020 else if (dbus_set_error_from_message (error, reply)) 02021 { 02022 dbus_message_unref (reply); 02023 return NULL; 02024 } 02025 else 02026 return reply; 02027 } 02028 02034 void 02035 dbus_connection_flush (DBusConnection *connection) 02036 { 02037 /* We have to specify DBUS_ITERATION_DO_READING here because 02038 * otherwise we could have two apps deadlock if they are both doing 02039 * a flush(), and the kernel buffers fill up. This could change the 02040 * dispatch status. 02041 */ 02042 DBusDispatchStatus status; 02043 02044 _dbus_return_if_fail (connection != NULL); 02045 02046 CONNECTION_LOCK (connection); 02047 while (connection->n_outgoing > 0 && 02048 _dbus_connection_get_is_connected_unlocked (connection)) 02049 _dbus_connection_do_iteration (connection, 02050 DBUS_ITERATION_DO_READING | 02051 DBUS_ITERATION_DO_WRITING | 02052 DBUS_ITERATION_BLOCK, 02053 -1); 02054 02055 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02056 02057 /* Unlocks and calls out to user code */ 02058 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02059 } 02060 02061 /* Call with mutex held. Will drop it while waiting and re-acquire 02062 * before returning 02063 */ 02064 static void 02065 _dbus_connection_wait_for_borrowed (DBusConnection *connection) 02066 { 02067 _dbus_assert (connection->message_borrowed != NULL); 02068 02069 while (connection->message_borrowed != NULL) 02070 dbus_condvar_wait (connection->message_returned_cond, connection->mutex); 02071 } 02072 02087 DBusMessage* 02088 dbus_connection_borrow_message (DBusConnection *connection) 02089 { 02090 DBusMessage *message; 02091 DBusDispatchStatus status; 02092 02093 _dbus_return_val_if_fail (connection != NULL, NULL); 02094 /* can't borrow during dispatch */ 02095 _dbus_return_val_if_fail (!connection->dispatch_acquired, NULL); 02096 02097 /* this is called for the side effect that it queues 02098 * up any messages from the transport 02099 */ 02100 status = dbus_connection_get_dispatch_status (connection); 02101 if (status != DBUS_DISPATCH_DATA_REMAINS) 02102 return NULL; 02103 02104 CONNECTION_LOCK (connection); 02105 02106 if (connection->message_borrowed != NULL) 02107 _dbus_connection_wait_for_borrowed (connection); 02108 02109 message = _dbus_list_get_first (&connection->incoming_messages); 02110 02111 if (message) 02112 connection->message_borrowed = message; 02113 02114 CONNECTION_UNLOCK (connection); 02115 return message; 02116 } 02117 02125 void 02126 dbus_connection_return_message (DBusConnection *connection, 02127 DBusMessage *message) 02128 { 02129 _dbus_return_if_fail (connection != NULL); 02130 _dbus_return_if_fail (message != NULL); 02131 /* can't borrow during dispatch */ 02132 _dbus_return_if_fail (!connection->dispatch_acquired); 02133 02134 CONNECTION_LOCK (connection); 02135 02136 _dbus_assert (message == connection->message_borrowed); 02137 02138 connection->message_borrowed = NULL; 02139 dbus_condvar_wake_all (connection->message_returned_cond); 02140 02141 CONNECTION_UNLOCK (connection); 02142 } 02143 02153 void 02154 dbus_connection_steal_borrowed_message (DBusConnection *connection, 02155 DBusMessage *message) 02156 { 02157 DBusMessage *pop_message; 02158 02159 _dbus_return_if_fail (connection != NULL); 02160 _dbus_return_if_fail (message != NULL); 02161 /* can't borrow during dispatch */ 02162 _dbus_return_if_fail (!connection->dispatch_acquired); 02163 02164 CONNECTION_LOCK (connection); 02165 02166 _dbus_assert (message == connection->message_borrowed); 02167 02168 pop_message = _dbus_list_pop_first (&connection->incoming_messages); 02169 _dbus_assert (message == pop_message); 02170 02171 connection->n_incoming -= 1; 02172 02173 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n", 02174 message, connection->n_incoming); 02175 02176 connection->message_borrowed = NULL; 02177 dbus_condvar_wake_all (connection->message_returned_cond); 02178 02179 CONNECTION_UNLOCK (connection); 02180 } 02181 02182 /* See dbus_connection_pop_message, but requires the caller to own 02183 * the lock before calling. May drop the lock while running. 02184 */ 02185 static DBusList* 02186 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection) 02187 { 02188 if (connection->message_borrowed != NULL) 02189 _dbus_connection_wait_for_borrowed (connection); 02190 02191 if (connection->n_incoming > 0) 02192 { 02193 DBusList *link; 02194 02195 link = _dbus_list_pop_first_link (&connection->incoming_messages); 02196 connection->n_incoming -= 1; 02197 02198 _dbus_verbose ("Message %p (%d %s '%s') removed from incoming queue %p, %d incoming\n", 02199 link->data, 02200 dbus_message_get_type (link->data), 02201 dbus_message_get_interface (link->data) ? 02202 dbus_message_get_interface (link->data) : 02203 "no interface", 02204 dbus_message_get_signature (link->data), 02205 connection, connection->n_incoming); 02206 02207 return link; 02208 } 02209 else 02210 return NULL; 02211 } 02212 02213 /* See dbus_connection_pop_message, but requires the caller to own 02214 * the lock before calling. May drop the lock while running. 02215 */ 02216 static DBusMessage* 02217 _dbus_connection_pop_message_unlocked (DBusConnection *connection) 02218 { 02219 DBusList *link; 02220 02221 link = _dbus_connection_pop_message_link_unlocked (connection); 02222 02223 if (link != NULL) 02224 { 02225 DBusMessage *message; 02226 02227 message = link->data; 02228 02229 _dbus_list_free_link (link); 02230 02231 return message; 02232 } 02233 else 02234 return NULL; 02235 } 02236 02237 static void 02238 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection, 02239 DBusList *message_link) 02240 { 02241 _dbus_assert (message_link != NULL); 02242 /* You can't borrow a message while a link is outstanding */ 02243 _dbus_assert (connection->message_borrowed == NULL); 02244 02245 _dbus_list_prepend_link (&connection->incoming_messages, 02246 message_link); 02247 connection->n_incoming += 1; 02248 02249 _dbus_verbose ("Message %p (%d %s '%s') put back into queue %p, %d incoming\n", 02250 message_link->data, 02251 dbus_message_get_type (message_link->data), 02252 dbus_message_get_interface (message_link->data) ? 02253 dbus_message_get_interface (message_link->data) : 02254 "no interface", 02255 dbus_message_get_signature (message_link->data), 02256 connection, connection->n_incoming); 02257 } 02258 02273 DBusMessage* 02274 dbus_connection_pop_message (DBusConnection *connection) 02275 { 02276 DBusMessage *message; 02277 DBusDispatchStatus status; 02278 02279 /* this is called for the side effect that it queues 02280 * up any messages from the transport 02281 */ 02282 status = dbus_connection_get_dispatch_status (connection); 02283 if (status != DBUS_DISPATCH_DATA_REMAINS) 02284 return NULL; 02285 02286 CONNECTION_LOCK (connection); 02287 02288 message = _dbus_connection_pop_message_unlocked (connection); 02289 02290 _dbus_verbose ("Returning popped message %p\n", message); 02291 02292 CONNECTION_UNLOCK (connection); 02293 02294 return message; 02295 } 02296 02305 static void 02306 _dbus_connection_acquire_dispatch (DBusConnection *connection) 02307 { 02308 if (connection->dispatch_acquired) 02309 dbus_condvar_wait (connection->dispatch_cond, connection->mutex); 02310 _dbus_assert (!connection->dispatch_acquired); 02311 02312 connection->dispatch_acquired = TRUE; 02313 } 02314 02322 static void 02323 _dbus_connection_release_dispatch (DBusConnection *connection) 02324 { 02325 _dbus_assert (connection->dispatch_acquired); 02326 02327 connection->dispatch_acquired = FALSE; 02328 dbus_condvar_wake_one (connection->dispatch_cond); 02329 } 02330 02331 static void 02332 _dbus_connection_failed_pop (DBusConnection *connection, 02333 DBusList *message_link) 02334 { 02335 _dbus_list_prepend_link (&connection->incoming_messages, 02336 message_link); 02337 connection->n_incoming += 1; 02338 } 02339 02340 static DBusDispatchStatus 02341 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection) 02342 { 02343 if (connection->n_incoming > 0) 02344 return DBUS_DISPATCH_DATA_REMAINS; 02345 else if (!_dbus_transport_queue_messages (connection->transport)) 02346 return DBUS_DISPATCH_NEED_MEMORY; 02347 else 02348 { 02349 DBusDispatchStatus status; 02350 02351 status = _dbus_transport_get_dispatch_status (connection->transport); 02352 02353 if (status == DBUS_DISPATCH_COMPLETE && 02354 connection->disconnect_message_link && 02355 !_dbus_transport_get_is_connected (connection->transport)) 02356 { 02357 /* We haven't sent the disconnect message already, 02358 * and all real messages have been queued up. 02359 */ 02360 _dbus_connection_queue_synthesized_message_link (connection, 02361 connection->disconnect_message_link); 02362 connection->disconnect_message_link = NULL; 02363 } 02364 02365 if (status != DBUS_DISPATCH_COMPLETE) 02366 return status; 02367 else if (connection->n_incoming > 0) 02368 return DBUS_DISPATCH_DATA_REMAINS; 02369 else 02370 return DBUS_DISPATCH_COMPLETE; 02371 } 02372 } 02373 02374 static void 02375 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection, 02376 DBusDispatchStatus new_status) 02377 { 02378 dbus_bool_t changed; 02379 DBusDispatchStatusFunction function; 02380 void *data; 02381 02382 /* We have the lock */ 02383 02384 _dbus_connection_ref_unlocked (connection); 02385 02386 changed = new_status != connection->last_dispatch_status; 02387 02388 connection->last_dispatch_status = new_status; 02389 02390 function = connection->dispatch_status_function; 02391 data = connection->dispatch_status_data; 02392 02393 /* We drop the lock */ 02394 CONNECTION_UNLOCK (connection); 02395 02396 if (changed && function) 02397 { 02398 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n", 02399 connection, new_status, 02400 new_status == DBUS_DISPATCH_COMPLETE ? "complete" : 02401 new_status == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : 02402 new_status == DBUS_DISPATCH_NEED_MEMORY ? "need memory" : 02403 "???"); 02404 (* function) (connection, new_status, data); 02405 } 02406 02407 dbus_connection_unref (connection); 02408 } 02409 02418 DBusDispatchStatus 02419 dbus_connection_get_dispatch_status (DBusConnection *connection) 02420 { 02421 DBusDispatchStatus status; 02422 02423 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE); 02424 02425 CONNECTION_LOCK (connection); 02426 02427 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02428 02429 CONNECTION_UNLOCK (connection); 02430 02431 return status; 02432 } 02433 02461 DBusDispatchStatus 02462 dbus_connection_dispatch (DBusConnection *connection) 02463 { 02464 DBusMessage *message; 02465 DBusList *link, *filter_list_copy, *message_link; 02466 DBusHandlerResult result; 02467 DBusPendingCall *pending; 02468 dbus_int32_t reply_serial; 02469 DBusDispatchStatus status; 02470 02471 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE); 02472 02473 CONNECTION_LOCK (connection); 02474 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02475 if (status != DBUS_DISPATCH_DATA_REMAINS) 02476 { 02477 /* unlocks and calls out to user code */ 02478 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02479 return status; 02480 } 02481 02482 /* We need to ref the connection since the callback could potentially 02483 * drop the last ref to it 02484 */ 02485 _dbus_connection_ref_unlocked (connection); 02486 02487 _dbus_connection_acquire_dispatch (connection); 02488 02489 /* This call may drop the lock during the execution (if waiting for 02490 * borrowed messages to be returned) but the order of message 02491 * dispatch if several threads call dispatch() is still 02492 * protected by the lock, since only one will get the lock, and that 02493 * one will finish the message dispatching 02494 */ 02495 message_link = _dbus_connection_pop_message_link_unlocked (connection); 02496 if (message_link == NULL) 02497 { 02498 /* another thread dispatched our stuff */ 02499 02500 _dbus_connection_release_dispatch (connection); 02501 02502 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02503 02504 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02505 02506 dbus_connection_unref (connection); 02507 02508 return status; 02509 } 02510 02511 message = message_link->data; 02512 02513 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 02514 02515 reply_serial = dbus_message_get_reply_serial (message); 02516 pending = _dbus_hash_table_lookup_int (connection->pending_replies, 02517 reply_serial); 02518 02519 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy)) 02520 { 02521 _dbus_connection_release_dispatch (connection); 02522 02523 _dbus_connection_failed_pop (connection, message_link); 02524 02525 /* unlocks and calls user code */ 02526 _dbus_connection_update_dispatch_status_and_unlock (connection, 02527 DBUS_DISPATCH_NEED_MEMORY); 02528 02529 dbus_connection_unref (connection); 02530 02531 return DBUS_DISPATCH_NEED_MEMORY; 02532 } 02533 02534 _dbus_list_foreach (&filter_list_copy, 02535 (DBusForeachFunction)_dbus_message_filter_ref, 02536 NULL); 02537 02538 /* We're still protected from dispatch() reentrancy here 02539 * since we acquired the dispatcher 02540 */ 02541 CONNECTION_UNLOCK (connection); 02542 02543 link = _dbus_list_get_first_link (&filter_list_copy); 02544 while (link != NULL) 02545 { 02546 DBusMessageFilter *filter = link->data; 02547 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link); 02548 02549 _dbus_verbose (" running filter on message %p\n", message); 02550 result = (* filter->function) (connection, message, filter->user_data); 02551 02552 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 02553 break; 02554 02555 link = next; 02556 } 02557 02558 _dbus_list_foreach (&filter_list_copy, 02559 (DBusForeachFunction)_dbus_message_filter_unref, 02560 NULL); 02561 _dbus_list_clear (&filter_list_copy); 02562 02563 CONNECTION_LOCK (connection); 02564 02565 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) 02566 goto out; 02567 02568 /* Did a reply we were waiting on get filtered? */ 02569 if (pending && result == DBUS_HANDLER_RESULT_HANDLED) 02570 { 02571 /* Queue the timeout immediately! */ 02572 if (pending->timeout_link) 02573 { 02574 _dbus_connection_queue_synthesized_message_link (connection, 02575 pending->timeout_link); 02576 pending->timeout_link = NULL; 02577 } 02578 else 02579 { 02580 /* We already queued the timeout? Then it was filtered! */ 02581 _dbus_warn ("The timeout error with reply serial %d was filtered, so the DBusPendingCall will never stop pending.\n", reply_serial); 02582 } 02583 } 02584 02585 if (result == DBUS_HANDLER_RESULT_HANDLED) 02586 goto out; 02587 02588 if (pending) 02589 { 02590 _dbus_pending_call_complete_and_unlock (pending, message); 02591 02592 pending = NULL; 02593 02594 CONNECTION_LOCK (connection); 02595 goto out; 02596 } 02597 02598 /* We're still protected from dispatch() reentrancy here 02599 * since we acquired the dispatcher 02600 */ 02601 _dbus_verbose (" running object path dispatch on message %p (%d %s '%s')\n", 02602 message, 02603 dbus_message_get_type (message), 02604 dbus_message_get_interface (message) ? 02605 dbus_message_get_interface (message) : 02606 "no interface", 02607 dbus_message_get_signature (message)); 02608 02609 result = _dbus_object_tree_dispatch_and_unlock (connection->objects, 02610 message); 02611 02612 CONNECTION_LOCK (connection); 02613 02614 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 02615 goto out; 02616 02617 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL) 02618 { 02619 DBusMessage *reply; 02620 DBusString str; 02621 DBusPreallocatedSend *preallocated; 02622 02623 _dbus_verbose (" sending error %s\n", 02624 DBUS_ERROR_UNKNOWN_METHOD); 02625 02626 if (!_dbus_string_init (&str)) 02627 { 02628 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 02629 goto out; 02630 } 02631 02632 if (!_dbus_string_append_printf (&str, 02633 "Method \"%s\" on interface \"%s\" doesn't exist\n", 02634 dbus_message_get_member (message), 02635 dbus_message_get_interface (message))) 02636 { 02637 _dbus_string_free (&str); 02638 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 02639 goto out; 02640 } 02641 02642 reply = dbus_message_new_error (message, 02643 DBUS_ERROR_UNKNOWN_METHOD, 02644 _dbus_string_get_const_data (&str)); 02645 _dbus_string_free (&str); 02646 02647 if (reply == NULL) 02648 { 02649 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 02650 goto out; 02651 } 02652 02653 preallocated = _dbus_connection_preallocate_send_unlocked (connection); 02654 02655 if (preallocated == NULL) 02656 { 02657 dbus_message_unref (reply); 02658 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 02659 goto out; 02660 } 02661 02662 _dbus_connection_send_preallocated_unlocked (connection, preallocated, 02663 reply, NULL); 02664 02665 dbus_message_unref (reply); 02666 02667 result = DBUS_HANDLER_RESULT_HANDLED; 02668 } 02669 02670 _dbus_verbose (" done dispatching %p (%d %s '%s') on connection %p\n", message, 02671 dbus_message_get_type (message), 02672 dbus_message_get_interface (message) ? 02673 dbus_message_get_interface (message) : 02674 "no interface", 02675 dbus_message_get_signature (message), 02676 connection); 02677 02678 out: 02679 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) 02680 { 02681 _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME); 02682 02683 /* Put message back, and we'll start over. 02684 * Yes this means handlers must be idempotent if they 02685 * don't return HANDLED; c'est la vie. 02686 */ 02687 _dbus_connection_putback_message_link_unlocked (connection, 02688 message_link); 02689 } 02690 else 02691 { 02692 _dbus_verbose ("Done with message in %s\n", _DBUS_FUNCTION_NAME); 02693 02694 if (connection->exit_on_disconnect && 02695 dbus_message_is_signal (message, 02696 DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL, 02697 "Disconnected")) 02698 { 02699 _dbus_verbose ("Exiting on Disconnected signal\n"); 02700 CONNECTION_UNLOCK (connection); 02701 _dbus_exit (1); 02702 _dbus_assert_not_reached ("Call to exit() returned"); 02703 } 02704 02705 _dbus_list_free_link (message_link); 02706 dbus_message_unref (message); /* don't want the message to count in max message limits 02707 * in computing dispatch status below 02708 */ 02709 } 02710 02711 _dbus_connection_release_dispatch (connection); 02712 02713 status = _dbus_connection_get_dispatch_status_unlocked (connection); 02714 02715 /* unlocks and calls user code */ 02716 _dbus_connection_update_dispatch_status_and_unlock (connection, status); 02717 02718 dbus_connection_unref (connection); 02719 02720 return status; 02721 } 02722 02781 dbus_bool_t 02782 dbus_connection_set_watch_functions (DBusConnection *connection, 02783 DBusAddWatchFunction add_function, 02784 DBusRemoveWatchFunction remove_function, 02785 DBusWatchToggledFunction toggled_function, 02786 void *data, 02787 DBusFreeFunction free_data_function) 02788 { 02789 dbus_bool_t retval; 02790 02791 _dbus_return_val_if_fail (connection != NULL, FALSE); 02792 02793 CONNECTION_LOCK (connection); 02794 /* ref connection for slightly better reentrancy */ 02795 _dbus_connection_ref_unlocked (connection); 02796 02797 /* FIXME this can call back into user code, and we need to drop the 02798 * connection lock when it does. 02799 */ 02800 retval = _dbus_watch_list_set_functions (connection->watches, 02801 add_function, remove_function, 02802 toggled_function, 02803 data, free_data_function); 02804 02805 CONNECTION_UNLOCK (connection); 02806 /* drop our paranoid refcount */ 02807 dbus_connection_unref (connection); 02808 02809 return retval; 02810 } 02811 02845 dbus_bool_t 02846 dbus_connection_set_timeout_functions (DBusConnection *connection, 02847 DBusAddTimeoutFunction add_function, 02848 DBusRemoveTimeoutFunction remove_function, 02849 DBusTimeoutToggledFunction toggled_function, 02850 void *data, 02851 DBusFreeFunction free_data_function) 02852 { 02853 dbus_bool_t retval; 02854 02855 _dbus_return_val_if_fail (connection != NULL, FALSE); 02856 02857 CONNECTION_LOCK (connection); 02858 /* ref connection for slightly better reentrancy */ 02859 _dbus_connection_ref_unlocked (connection); 02860 02861 retval = _dbus_timeout_list_set_functions (connection->timeouts, 02862 add_function, remove_function, 02863 toggled_function, 02864 data, free_data_function); 02865 02866 CONNECTION_UNLOCK (connection); 02867 /* drop our paranoid refcount */ 02868 dbus_connection_unref (connection); 02869 02870 return retval; 02871 } 02872 02887 void 02888 dbus_connection_set_wakeup_main_function (DBusConnection *connection, 02889 DBusWakeupMainFunction wakeup_main_function, 02890 void *data, 02891 DBusFreeFunction free_data_function) 02892 { 02893 void *old_data; 02894 DBusFreeFunction old_free_data; 02895 02896 _dbus_return_if_fail (connection != NULL); 02897 02898 CONNECTION_LOCK (connection); 02899 old_data = connection->wakeup_main_data; 02900 old_free_data = connection->free_wakeup_main_data; 02901 02902 connection->wakeup_main_function = wakeup_main_function; 02903 connection->wakeup_main_data = data; 02904 connection->free_wakeup_main_data = free_data_function; 02905 02906 CONNECTION_UNLOCK (connection); 02907 02908 /* Callback outside the lock */ 02909 if (old_free_data) 02910 (*old_free_data) (old_data); 02911 } 02912 02929 void 02930 dbus_connection_set_dispatch_status_function (DBusConnection *connection, 02931 DBusDispatchStatusFunction function, 02932 void *data, 02933 DBusFreeFunction free_data_function) 02934 { 02935 void *old_data; 02936 DBusFreeFunction old_free_data; 02937 02938 _dbus_return_if_fail (connection != NULL); 02939 02940 CONNECTION_LOCK (connection); 02941 old_data = connection->dispatch_status_data; 02942 old_free_data = connection->free_dispatch_status_data; 02943 02944 connection->dispatch_status_function = function; 02945 connection->dispatch_status_data = data; 02946 connection->free_dispatch_status_data = free_data_function; 02947 02948 CONNECTION_UNLOCK (connection); 02949 02950 /* Callback outside the lock */ 02951 if (old_free_data) 02952 (*old_free_data) (old_data); 02953 } 02954 02967 dbus_bool_t 02968 dbus_connection_get_unix_fd (DBusConnection *connection, 02969 int *fd) 02970 { 02971 dbus_bool_t retval; 02972 02973 _dbus_return_val_if_fail (connection != NULL, FALSE); 02974 _dbus_return_val_if_fail (connection->transport != NULL, FALSE); 02975 02976 CONNECTION_LOCK (connection); 02977 02978 retval = _dbus_transport_get_unix_fd (connection->transport, 02979 fd); 02980 02981 CONNECTION_UNLOCK (connection); 02982 02983 return retval; 02984 } 02985 02997 dbus_bool_t 02998 dbus_connection_get_unix_user (DBusConnection *connection, 02999 unsigned long *uid) 03000 { 03001 dbus_bool_t result; 03002 03003 _dbus_return_val_if_fail (connection != NULL, FALSE); 03004 _dbus_return_val_if_fail (uid != NULL, FALSE); 03005 03006 CONNECTION_LOCK (connection); 03007 03008 if (!_dbus_transport_get_is_authenticated (connection->transport)) 03009 result = FALSE; 03010 else 03011 result = _dbus_transport_get_unix_user (connection->transport, 03012 uid); 03013 CONNECTION_UNLOCK (connection); 03014 03015 return result; 03016 } 03017 03028 dbus_bool_t 03029 dbus_connection_get_unix_process_id (DBusConnection *connection, 03030 unsigned long *pid) 03031 { 03032 dbus_bool_t result; 03033 03034 _dbus_return_val_if_fail (connection != NULL, FALSE); 03035 _dbus_return_val_if_fail (pid != NULL, FALSE); 03036 03037 CONNECTION_LOCK (connection); 03038 03039 if (!_dbus_transport_get_is_authenticated (connection->transport)) 03040 result = FALSE; 03041 else 03042 result = _dbus_transport_get_unix_process_id (connection->transport, 03043 pid); 03044 CONNECTION_UNLOCK (connection); 03045 03046 return result; 03047 } 03048 03065 void 03066 dbus_connection_set_unix_user_function (DBusConnection *connection, 03067 DBusAllowUnixUserFunction function, 03068 void *data, 03069 DBusFreeFunction free_data_function) 03070 { 03071 void *old_data = NULL; 03072 DBusFreeFunction old_free_function = NULL; 03073 03074 _dbus_return_if_fail (connection != NULL); 03075 03076 CONNECTION_LOCK (connection); 03077 _dbus_transport_set_unix_user_function (connection->transport, 03078 function, data, free_data_function, 03079 &old_data, &old_free_function); 03080 CONNECTION_UNLOCK (connection); 03081 03082 if (old_free_function != NULL) 03083 (* old_free_function) (old_data); 03084 } 03085 03107 dbus_bool_t 03108 dbus_connection_add_filter (DBusConnection *connection, 03109 DBusHandleMessageFunction function, 03110 void *user_data, 03111 DBusFreeFunction free_data_function) 03112 { 03113 DBusMessageFilter *filter; 03114 03115 _dbus_return_val_if_fail (connection != NULL, FALSE); 03116 _dbus_return_val_if_fail (function != NULL, FALSE); 03117 03118 filter = dbus_new0 (DBusMessageFilter, 1); 03119 if (filter == NULL) 03120 return FALSE; 03121 03122 filter->refcount.value = 1; 03123 03124 CONNECTION_LOCK (connection); 03125 03126 if (!_dbus_list_append (&connection->filter_list, 03127 filter)) 03128 { 03129 _dbus_message_filter_unref (filter); 03130 CONNECTION_UNLOCK (connection); 03131 return FALSE; 03132 } 03133 03134 /* Fill in filter after all memory allocated, 03135 * so we don't run the free_user_data_function 03136 * if the add_filter() fails 03137 */ 03138 03139 filter->function = function; 03140 filter->user_data = user_data; 03141 filter->free_user_data_function = free_data_function; 03142 03143 CONNECTION_UNLOCK (connection); 03144 return TRUE; 03145 } 03146 03159 void 03160 dbus_connection_remove_filter (DBusConnection *connection, 03161 DBusHandleMessageFunction function, 03162 void *user_data) 03163 { 03164 DBusList *link; 03165 DBusMessageFilter *filter; 03166 03167 _dbus_return_if_fail (connection != NULL); 03168 _dbus_return_if_fail (function != NULL); 03169 03170 CONNECTION_LOCK (connection); 03171 03172 filter = NULL; 03173 03174 link = _dbus_list_get_last_link (&connection->filter_list); 03175 while (link != NULL) 03176 { 03177 filter = link->data; 03178 03179 if (filter->function == function && 03180 filter->user_data == user_data) 03181 { 03182 _dbus_list_remove_link (&connection->filter_list, link); 03183 filter->function = NULL; 03184 03185 break; 03186 } 03187 03188 link = _dbus_list_get_prev_link (&connection->filter_list, link); 03189 } 03190 03191 CONNECTION_UNLOCK (connection); 03192 03193 #ifndef DBUS_DISABLE_CHECKS 03194 if (filter == NULL) 03195 { 03196 _dbus_warn ("Attempt to remove filter function %p user data %p, but no such filter has been added\n", 03197 function, user_data); 03198 return; 03199 } 03200 #endif 03201 03202 /* Call application code */ 03203 if (filter->free_user_data_function) 03204 (* filter->free_user_data_function) (filter->user_data); 03205 03206 filter->free_user_data_function = NULL; 03207 filter->user_data = NULL; 03208 03209 _dbus_message_filter_unref (filter); 03210 } 03211 03223 dbus_bool_t 03224 dbus_connection_register_object_path (DBusConnection *connection, 03225 const char *path, 03226 const DBusObjectPathVTable *vtable, 03227 void *user_data) 03228 { 03229 char **decomposed_path; 03230 dbus_bool_t retval; 03231 03232 _dbus_return_val_if_fail (connection != NULL, FALSE); 03233 _dbus_return_val_if_fail (path != NULL, FALSE); 03234 _dbus_return_val_if_fail (path[0] == '/', FALSE); 03235 _dbus_return_val_if_fail (vtable != NULL, FALSE); 03236 03237 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 03238 return FALSE; 03239 03240 CONNECTION_LOCK (connection); 03241 03242 retval = _dbus_object_tree_register (connection->objects, 03243 FALSE, 03244 (const char **) decomposed_path, vtable, 03245 user_data); 03246 03247 CONNECTION_UNLOCK (connection); 03248 03249 dbus_free_string_array (decomposed_path); 03250 03251 return retval; 03252 } 03253 03266 dbus_bool_t 03267 dbus_connection_register_fallback (DBusConnection *connection, 03268 const char *path, 03269 const DBusObjectPathVTable *vtable, 03270 void *user_data) 03271 { 03272 char **decomposed_path; 03273 dbus_bool_t retval; 03274 03275 _dbus_return_val_if_fail (connection != NULL, FALSE); 03276 _dbus_return_val_if_fail (path != NULL, FALSE); 03277 _dbus_return_val_if_fail (path[0] == '/', FALSE); 03278 _dbus_return_val_if_fail (vtable != NULL, FALSE); 03279 03280 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 03281 return FALSE; 03282 03283 CONNECTION_LOCK (connection); 03284 03285 retval = _dbus_object_tree_register (connection->objects, 03286 TRUE, 03287 (const char **) decomposed_path, vtable, 03288 user_data); 03289 03290 CONNECTION_UNLOCK (connection); 03291 03292 dbus_free_string_array (decomposed_path); 03293 03294 return retval; 03295 } 03296 03306 dbus_bool_t 03307 dbus_connection_unregister_object_path (DBusConnection *connection, 03308 const char *path) 03309 { 03310 char **decomposed_path; 03311 03312 _dbus_return_val_if_fail (connection != NULL, FALSE); 03313 _dbus_return_val_if_fail (path != NULL, FALSE); 03314 _dbus_return_val_if_fail (path[0] == '/', FALSE); 03315 03316 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL)) 03317 return FALSE; 03318 03319 CONNECTION_LOCK (connection); 03320 03321 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path); 03322 03323 dbus_free_string_array (decomposed_path); 03324 03325 return TRUE; 03326 } 03327 03338 dbus_bool_t 03339 dbus_connection_list_registered (DBusConnection *connection, 03340 const char *parent_path, 03341 char ***child_entries) 03342 { 03343 char **decomposed_path; 03344 dbus_bool_t retval; 03345 _dbus_return_val_if_fail (connection != NULL, FALSE); 03346 _dbus_return_val_if_fail (parent_path != NULL, FALSE); 03347 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE); 03348 _dbus_return_val_if_fail (child_entries != NULL, FALSE); 03349 03350 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL)) 03351 return FALSE; 03352 03353 CONNECTION_LOCK (connection); 03354 03355 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects, 03356 (const char **) decomposed_path, 03357 child_entries); 03358 dbus_free_string_array (decomposed_path); 03359 03360 return retval; 03361 } 03362 03363 static DBusDataSlotAllocator slot_allocator; 03364 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots); 03365 03380 dbus_bool_t 03381 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p) 03382 { 03383 return _dbus_data_slot_allocator_alloc (&slot_allocator, 03384 _DBUS_LOCK_NAME (connection_slots), 03385 slot_p); 03386 } 03387 03399 void 03400 dbus_connection_free_data_slot (dbus_int32_t *slot_p) 03401 { 03402 _dbus_return_if_fail (*slot_p >= 0); 03403 03404 _dbus_data_slot_allocator_free (&slot_allocator, slot_p); 03405 } 03406 03420 dbus_bool_t 03421 dbus_connection_set_data (DBusConnection *connection, 03422 dbus_int32_t slot, 03423 void *data, 03424 DBusFreeFunction free_data_func) 03425 { 03426 DBusFreeFunction old_free_func; 03427 void *old_data; 03428 dbus_bool_t retval; 03429 03430 _dbus_return_val_if_fail (connection != NULL, FALSE); 03431 _dbus_return_val_if_fail (slot >= 0, FALSE); 03432 03433 CONNECTION_LOCK (connection); 03434 03435 retval = _dbus_data_slot_list_set (&slot_allocator, 03436 &connection->slot_list, 03437 slot, data, free_data_func, 03438 &old_free_func, &old_data); 03439 03440 CONNECTION_UNLOCK (connection); 03441 03442 if (retval) 03443 { 03444 /* Do the actual free outside the connection lock */ 03445 if (old_free_func) 03446 (* old_free_func) (old_data); 03447 } 03448 03449 return retval; 03450 } 03451 03460 void* 03461 dbus_connection_get_data (DBusConnection *connection, 03462 dbus_int32_t slot) 03463 { 03464 void *res; 03465 03466 _dbus_return_val_if_fail (connection != NULL, NULL); 03467 03468 CONNECTION_LOCK (connection); 03469 03470 res = _dbus_data_slot_list_get (&slot_allocator, 03471 &connection->slot_list, 03472 slot); 03473 03474 CONNECTION_UNLOCK (connection); 03475 03476 return res; 03477 } 03478 03485 void 03486 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe) 03487 { 03488 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE; 03489 } 03490 03499 void 03500 dbus_connection_set_max_message_size (DBusConnection *connection, 03501 long size) 03502 { 03503 _dbus_return_if_fail (connection != NULL); 03504 03505 CONNECTION_LOCK (connection); 03506 _dbus_transport_set_max_message_size (connection->transport, 03507 size); 03508 CONNECTION_UNLOCK (connection); 03509 } 03510 03517 long 03518 dbus_connection_get_max_message_size (DBusConnection *connection) 03519 { 03520 long res; 03521 03522 _dbus_return_val_if_fail (connection != NULL, 0); 03523 03524 CONNECTION_LOCK (connection); 03525 res = _dbus_transport_get_max_message_size (connection->transport); 03526 CONNECTION_UNLOCK (connection); 03527 return res; 03528 } 03529 03555 void 03556 dbus_connection_set_max_received_size (DBusConnection *connection, 03557 long size) 03558 { 03559 _dbus_return_if_fail (connection != NULL); 03560 03561 CONNECTION_LOCK (connection); 03562 _dbus_transport_set_max_received_size (connection->transport, 03563 size); 03564 CONNECTION_UNLOCK (connection); 03565 } 03566 03573 long 03574 dbus_connection_get_max_received_size (DBusConnection *connection) 03575 { 03576 long res; 03577 03578 _dbus_return_val_if_fail (connection != NULL, 0); 03579 03580 CONNECTION_LOCK (connection); 03581 res = _dbus_transport_get_max_received_size (connection->transport); 03582 CONNECTION_UNLOCK (connection); 03583 return res; 03584 } 03585 03596 long 03597 dbus_connection_get_outgoing_size (DBusConnection *connection) 03598 { 03599 long res; 03600 03601 _dbus_return_val_if_fail (connection != NULL, 0); 03602 03603 CONNECTION_LOCK (connection); 03604 res = _dbus_counter_get_value (connection->outgoing_counter); 03605 CONNECTION_UNLOCK (connection); 03606 return res; 03607 } 03608

Generated on Tue Oct 12 02:07:52 2004 for D-BUS by doxygen 1.3.7