00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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-threads.h"
00037 #include "dbus-protocol.h"
00038 #include "dbus-dataslot.h"
00039 #include "dbus-string.h"
00040 #include "dbus-pending-call.h"
00041 #include "dbus-object-tree.h"
00042 #include "dbus-threads-internal.h"
00043 #include "dbus-bus.h"
00044
00045 #ifdef DBUS_DISABLE_CHECKS
00046 #define TOOK_LOCK_CHECK(connection)
00047 #define RELEASING_LOCK_CHECK(connection)
00048 #define HAVE_LOCK_CHECK(connection)
00049 #else
00050 #define TOOK_LOCK_CHECK(connection) do { \
00051 _dbus_assert (!(connection)->have_connection_lock); \
00052 (connection)->have_connection_lock = TRUE; \
00053 } while (0)
00054 #define RELEASING_LOCK_CHECK(connection) do { \
00055 _dbus_assert ((connection)->have_connection_lock); \
00056 (connection)->have_connection_lock = FALSE; \
00057 } while (0)
00058 #define HAVE_LOCK_CHECK(connection) _dbus_assert ((connection)->have_connection_lock)
00059
00060 #endif
00061
00062 #define TRACE_LOCKS 1
00063
00064 #define CONNECTION_LOCK(connection) do { \
00065 if (TRACE_LOCKS) { _dbus_verbose (" LOCK: %s\n", _DBUS_FUNCTION_NAME); } \
00066 _dbus_mutex_lock ((connection)->mutex); \
00067 TOOK_LOCK_CHECK (connection); \
00068 } while (0)
00069
00070 #define CONNECTION_UNLOCK(connection) do { \
00071 if (TRACE_LOCKS) { _dbus_verbose (" UNLOCK: %s\n", _DBUS_FUNCTION_NAME); } \
00072 RELEASING_LOCK_CHECK (connection); \
00073 _dbus_mutex_unlock ((connection)->mutex); \
00074 } while (0)
00075
00076 #define DISPATCH_STATUS_NAME(s) \
00077 ((s) == DBUS_DISPATCH_COMPLETE ? "complete" : \
00078 (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
00079 (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" : \
00080 "???")
00081
00159 typedef struct DBusMessageFilter DBusMessageFilter;
00160
00164 struct DBusMessageFilter
00165 {
00166 DBusAtomic refcount;
00167 DBusHandleMessageFunction function;
00168 void *user_data;
00169 DBusFreeFunction free_user_data_function;
00170 };
00171
00172
00176 struct DBusPreallocatedSend
00177 {
00178 DBusConnection *connection;
00179 DBusList *queue_link;
00180 DBusList *counter_link;
00181 };
00182
00183 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00184
00188 struct DBusConnection
00189 {
00190 DBusAtomic refcount;
00192 DBusMutex *mutex;
00194 DBusMutex *dispatch_mutex;
00195 DBusCondVar *dispatch_cond;
00196 DBusMutex *io_path_mutex;
00197 DBusCondVar *io_path_cond;
00199 DBusList *outgoing_messages;
00200 DBusList *incoming_messages;
00202 DBusMessage *message_borrowed;
00206 int n_outgoing;
00207 int n_incoming;
00209 DBusCounter *outgoing_counter;
00211 DBusTransport *transport;
00212 DBusWatchList *watches;
00213 DBusTimeoutList *timeouts;
00215 DBusList *filter_list;
00217 DBusDataSlotList slot_list;
00219 DBusHashTable *pending_replies;
00221 dbus_uint32_t client_serial;
00222 DBusList *disconnect_message_link;
00224 DBusWakeupMainFunction wakeup_main_function;
00225 void *wakeup_main_data;
00226 DBusFreeFunction free_wakeup_main_data;
00228 DBusDispatchStatusFunction dispatch_status_function;
00229 void *dispatch_status_data;
00230 DBusFreeFunction free_dispatch_status_data;
00232 DBusDispatchStatus last_dispatch_status;
00234 DBusList *link_cache;
00237 DBusObjectTree *objects;
00239 char *server_guid;
00241 unsigned int shareable : 1;
00243 unsigned int shared : 1;
00245 unsigned int dispatch_acquired : 1;
00246 unsigned int io_path_acquired : 1;
00248 unsigned int exit_on_disconnect : 1;
00250 #ifndef DBUS_DISABLE_CHECKS
00251 unsigned int have_connection_lock : 1;
00252 #endif
00253
00254 #ifndef DBUS_DISABLE_CHECKS
00255 int generation;
00256 #endif
00257 };
00258
00259 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection);
00260 static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
00261 DBusDispatchStatus new_status);
00262 static void _dbus_connection_last_unref (DBusConnection *connection);
00263 static void _dbus_connection_acquire_dispatch (DBusConnection *connection);
00264 static void _dbus_connection_release_dispatch (DBusConnection *connection);
00265 static DBusDispatchStatus _dbus_connection_flush_unlocked (DBusConnection *connection);
00266
00267 static DBusMessageFilter *
00268 _dbus_message_filter_ref (DBusMessageFilter *filter)
00269 {
00270 _dbus_assert (filter->refcount.value > 0);
00271 _dbus_atomic_inc (&filter->refcount);
00272
00273 return filter;
00274 }
00275
00276 static void
00277 _dbus_message_filter_unref (DBusMessageFilter *filter)
00278 {
00279 _dbus_assert (filter->refcount.value > 0);
00280
00281 if (_dbus_atomic_dec (&filter->refcount) == 1)
00282 {
00283 if (filter->free_user_data_function)
00284 (* filter->free_user_data_function) (filter->user_data);
00285
00286 dbus_free (filter);
00287 }
00288 }
00289
00295 void
00296 _dbus_connection_lock (DBusConnection *connection)
00297 {
00298 CONNECTION_LOCK (connection);
00299 }
00300
00306 void
00307 _dbus_connection_unlock (DBusConnection *connection)
00308 {
00309 CONNECTION_UNLOCK (connection);
00310 }
00311
00319 static void
00320 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00321 {
00322 if (connection->wakeup_main_function)
00323 (*connection->wakeup_main_function) (connection->wakeup_main_data);
00324 }
00325
00326 #ifdef DBUS_BUILD_TESTS
00327
00337 dbus_bool_t
00338 _dbus_connection_queue_received_message (DBusConnection *connection,
00339 DBusMessage *message)
00340 {
00341 DBusList *link;
00342
00343 link = _dbus_list_alloc_link (message);
00344 if (link == NULL)
00345 return FALSE;
00346
00347 dbus_message_ref (message);
00348 _dbus_connection_queue_received_message_link (connection, link);
00349
00350 return TRUE;
00351 }
00352
00365 void
00366 _dbus_connection_test_get_locks (DBusConnection *conn,
00367 DBusMutex **mutex_loc,
00368 DBusMutex **dispatch_mutex_loc,
00369 DBusMutex **io_path_mutex_loc,
00370 DBusCondVar **dispatch_cond_loc,
00371 DBusCondVar **io_path_cond_loc)
00372 {
00373 *mutex_loc = conn->mutex;
00374 *dispatch_mutex_loc = conn->dispatch_mutex;
00375 *io_path_mutex_loc = conn->io_path_mutex;
00376 *dispatch_cond_loc = conn->dispatch_cond;
00377 *io_path_cond_loc = conn->io_path_cond;
00378 }
00379 #endif
00380
00389 void
00390 _dbus_connection_queue_received_message_link (DBusConnection *connection,
00391 DBusList *link)
00392 {
00393 DBusPendingCall *pending;
00394 dbus_int32_t reply_serial;
00395 DBusMessage *message;
00396
00397 _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00398
00399 _dbus_list_append_link (&connection->incoming_messages,
00400 link);
00401 message = link->data;
00402
00403
00404 reply_serial = dbus_message_get_reply_serial (message);
00405 if (reply_serial != -1)
00406 {
00407 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00408 reply_serial);
00409 if (pending != NULL)
00410 {
00411 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00412 _dbus_connection_remove_timeout_unlocked (connection,
00413 _dbus_pending_call_get_timeout_unlocked (pending));
00414
00415 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00416 }
00417 }
00418
00419
00420
00421 connection->n_incoming += 1;
00422
00423 _dbus_connection_wakeup_mainloop (connection);
00424
00425 _dbus_verbose ("Message %p (%d %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00426 message,
00427 dbus_message_get_type (message),
00428 dbus_message_get_path (message) ?
00429 dbus_message_get_path (message) :
00430 "no path",
00431 dbus_message_get_interface (message) ?
00432 dbus_message_get_interface (message) :
00433 "no interface",
00434 dbus_message_get_member (message) ?
00435 dbus_message_get_member (message) :
00436 "no member",
00437 dbus_message_get_signature (message),
00438 dbus_message_get_reply_serial (message),
00439 connection,
00440 connection->n_incoming);}
00441
00450 void
00451 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00452 DBusList *link)
00453 {
00454 HAVE_LOCK_CHECK (connection);
00455
00456 _dbus_list_append_link (&connection->incoming_messages, link);
00457
00458 connection->n_incoming += 1;
00459
00460 _dbus_connection_wakeup_mainloop (connection);
00461
00462 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00463 link->data, connection, connection->n_incoming);
00464 }
00465
00466
00474 dbus_bool_t
00475 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00476 {
00477 HAVE_LOCK_CHECK (connection);
00478 return connection->outgoing_messages != NULL;
00479 }
00480
00487 dbus_bool_t
00488 dbus_connection_has_messages_to_send (DBusConnection *connection)
00489 {
00490 dbus_bool_t v;
00491
00492 _dbus_return_val_if_fail (connection != NULL, FALSE);
00493
00494 CONNECTION_LOCK (connection);
00495 v = _dbus_connection_has_messages_to_send_unlocked (connection);
00496 CONNECTION_UNLOCK (connection);
00497
00498 return v;
00499 }
00500
00508 DBusMessage*
00509 _dbus_connection_get_message_to_send (DBusConnection *connection)
00510 {
00511 HAVE_LOCK_CHECK (connection);
00512
00513 return _dbus_list_get_last (&connection->outgoing_messages);
00514 }
00515
00524 void
00525 _dbus_connection_message_sent (DBusConnection *connection,
00526 DBusMessage *message)
00527 {
00528 DBusList *link;
00529
00530 HAVE_LOCK_CHECK (connection);
00531
00532
00533
00534
00535
00536
00537 link = _dbus_list_get_last_link (&connection->outgoing_messages);
00538 _dbus_assert (link != NULL);
00539 _dbus_assert (link->data == message);
00540
00541
00542 _dbus_list_unlink (&connection->outgoing_messages,
00543 link);
00544 _dbus_list_prepend_link (&connection->link_cache, link);
00545
00546 connection->n_outgoing -= 1;
00547
00548 _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00549 message,
00550 dbus_message_get_type (message),
00551 dbus_message_get_path (message) ?
00552 dbus_message_get_path (message) :
00553 "no path",
00554 dbus_message_get_interface (message) ?
00555 dbus_message_get_interface (message) :
00556 "no interface",
00557 dbus_message_get_member (message) ?
00558 dbus_message_get_member (message) :
00559 "no member",
00560 dbus_message_get_signature (message),
00561 connection, connection->n_outgoing);
00562
00563
00564 _dbus_message_remove_size_counter (message, connection->outgoing_counter,
00565 &link);
00566 _dbus_list_prepend_link (&connection->link_cache, link);
00567
00568 dbus_message_unref (message);
00569 }
00570
00571 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list,
00572 DBusWatch *watch);
00573 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list,
00574 DBusWatch *watch);
00575 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list,
00576 DBusWatch *watch,
00577 dbus_bool_t enabled);
00578
00579 static dbus_bool_t
00580 protected_change_watch (DBusConnection *connection,
00581 DBusWatch *watch,
00582 DBusWatchAddFunction add_function,
00583 DBusWatchRemoveFunction remove_function,
00584 DBusWatchToggleFunction toggle_function,
00585 dbus_bool_t enabled)
00586 {
00587 DBusWatchList *watches;
00588 dbus_bool_t retval;
00589
00590 HAVE_LOCK_CHECK (connection);
00591
00592
00593
00594
00595
00596 watches = connection->watches;
00597 if (watches)
00598 {
00599 connection->watches = NULL;
00600 _dbus_connection_ref_unlocked (connection);
00601 CONNECTION_UNLOCK (connection);
00602
00603 if (add_function)
00604 retval = (* add_function) (watches, watch);
00605 else if (remove_function)
00606 {
00607 retval = TRUE;
00608 (* remove_function) (watches, watch);
00609 }
00610 else
00611 {
00612 retval = TRUE;
00613 (* toggle_function) (watches, watch, enabled);
00614 }
00615
00616 CONNECTION_LOCK (connection);
00617 connection->watches = watches;
00618 _dbus_connection_unref_unlocked (connection);
00619
00620 return retval;
00621 }
00622 else
00623 return FALSE;
00624 }
00625
00626
00638 dbus_bool_t
00639 _dbus_connection_add_watch_unlocked (DBusConnection *connection,
00640 DBusWatch *watch)
00641 {
00642 return protected_change_watch (connection, watch,
00643 _dbus_watch_list_add_watch,
00644 NULL, NULL, FALSE);
00645 }
00646
00656 void
00657 _dbus_connection_remove_watch_unlocked (DBusConnection *connection,
00658 DBusWatch *watch)
00659 {
00660 protected_change_watch (connection, watch,
00661 NULL,
00662 _dbus_watch_list_remove_watch,
00663 NULL, FALSE);
00664 }
00665
00676 void
00677 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
00678 DBusWatch *watch,
00679 dbus_bool_t enabled)
00680 {
00681 _dbus_assert (watch != NULL);
00682
00683 protected_change_watch (connection, watch,
00684 NULL, NULL,
00685 _dbus_watch_list_toggle_watch,
00686 enabled);
00687 }
00688
00689 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list,
00690 DBusTimeout *timeout);
00691 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00692 DBusTimeout *timeout);
00693 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00694 DBusTimeout *timeout,
00695 dbus_bool_t enabled);
00696
00697 static dbus_bool_t
00698 protected_change_timeout (DBusConnection *connection,
00699 DBusTimeout *timeout,
00700 DBusTimeoutAddFunction add_function,
00701 DBusTimeoutRemoveFunction remove_function,
00702 DBusTimeoutToggleFunction toggle_function,
00703 dbus_bool_t enabled)
00704 {
00705 DBusTimeoutList *timeouts;
00706 dbus_bool_t retval;
00707
00708 HAVE_LOCK_CHECK (connection);
00709
00710
00711
00712
00713
00714 timeouts = connection->timeouts;
00715 if (timeouts)
00716 {
00717 connection->timeouts = NULL;
00718 _dbus_connection_ref_unlocked (connection);
00719 CONNECTION_UNLOCK (connection);
00720
00721 if (add_function)
00722 retval = (* add_function) (timeouts, timeout);
00723 else if (remove_function)
00724 {
00725 retval = TRUE;
00726 (* remove_function) (timeouts, timeout);
00727 }
00728 else
00729 {
00730 retval = TRUE;
00731 (* toggle_function) (timeouts, timeout, enabled);
00732 }
00733
00734 CONNECTION_LOCK (connection);
00735 connection->timeouts = timeouts;
00736 _dbus_connection_unref_unlocked (connection);
00737
00738 return retval;
00739 }
00740 else
00741 return FALSE;
00742 }
00743
00756 dbus_bool_t
00757 _dbus_connection_add_timeout_unlocked (DBusConnection *connection,
00758 DBusTimeout *timeout)
00759 {
00760 return protected_change_timeout (connection, timeout,
00761 _dbus_timeout_list_add_timeout,
00762 NULL, NULL, FALSE);
00763 }
00764
00774 void
00775 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
00776 DBusTimeout *timeout)
00777 {
00778 protected_change_timeout (connection, timeout,
00779 NULL,
00780 _dbus_timeout_list_remove_timeout,
00781 NULL, FALSE);
00782 }
00783
00794 void
00795 _dbus_connection_toggle_timeout_unlocked (DBusConnection *connection,
00796 DBusTimeout *timeout,
00797 dbus_bool_t enabled)
00798 {
00799 protected_change_timeout (connection, timeout,
00800 NULL, NULL,
00801 _dbus_timeout_list_toggle_timeout,
00802 enabled);
00803 }
00804
00805 static dbus_bool_t
00806 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection,
00807 DBusPendingCall *pending)
00808 {
00809 dbus_uint32_t reply_serial;
00810 DBusTimeout *timeout;
00811
00812 HAVE_LOCK_CHECK (connection);
00813
00814 reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
00815
00816 _dbus_assert (reply_serial != 0);
00817
00818 timeout = _dbus_pending_call_get_timeout_unlocked (pending);
00819
00820 if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
00821 return FALSE;
00822
00823 if (!_dbus_hash_table_insert_int (connection->pending_replies,
00824 reply_serial,
00825 pending))
00826 {
00827 _dbus_connection_remove_timeout_unlocked (connection, timeout);
00828
00829 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00830 HAVE_LOCK_CHECK (connection);
00831 return FALSE;
00832 }
00833
00834 _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE);
00835
00836 _dbus_pending_call_ref_unlocked (pending);
00837
00838 HAVE_LOCK_CHECK (connection);
00839
00840 return TRUE;
00841 }
00842
00843 static void
00844 free_pending_call_on_hash_removal (void *data)
00845 {
00846 DBusPendingCall *pending;
00847 DBusConnection *connection;
00848
00849 if (data == NULL)
00850 return;
00851
00852 pending = data;
00853
00854 connection = _dbus_pending_call_get_connection_unlocked (pending);
00855
00856 HAVE_LOCK_CHECK (connection);
00857
00858 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00859 {
00860 _dbus_connection_remove_timeout_unlocked (connection,
00861 _dbus_pending_call_get_timeout_unlocked (pending));
00862
00863 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00864 }
00865
00866
00867
00868
00869
00870
00871 _dbus_connection_ref_unlocked (connection);
00872 _dbus_pending_call_unref_and_unlock (pending);
00873 CONNECTION_LOCK (connection);
00874 _dbus_connection_unref_unlocked (connection);
00875 }
00876
00877 static void
00878 _dbus_connection_detach_pending_call_unlocked (DBusConnection *connection,
00879 DBusPendingCall *pending)
00880 {
00881
00882
00883
00884 _dbus_hash_table_remove_int (connection->pending_replies,
00885 _dbus_pending_call_get_reply_serial_unlocked (pending));
00886 }
00887
00888 static void
00889 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection,
00890 DBusPendingCall *pending)
00891 {
00892
00893
00894
00895
00896
00897
00898
00899 _dbus_pending_call_ref_unlocked (pending);
00900 _dbus_hash_table_remove_int (connection->pending_replies,
00901 _dbus_pending_call_get_reply_serial_unlocked (pending));
00902 _dbus_pending_call_unref_and_unlock (pending);
00903 }
00904
00913 void
00914 _dbus_connection_remove_pending_call (DBusConnection *connection,
00915 DBusPendingCall *pending)
00916 {
00917 CONNECTION_LOCK (connection);
00918 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
00919 }
00920
00930 static dbus_bool_t
00931 _dbus_connection_acquire_io_path (DBusConnection *connection,
00932 int timeout_milliseconds)
00933 {
00934 dbus_bool_t we_acquired;
00935
00936 HAVE_LOCK_CHECK (connection);
00937
00938
00939 _dbus_connection_ref_unlocked (connection);
00940
00941
00942 CONNECTION_UNLOCK (connection);
00943
00944 _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00945 _dbus_mutex_lock (connection->io_path_mutex);
00946
00947 _dbus_verbose ("%s start connection->io_path_acquired = %d timeout = %d\n",
00948 _DBUS_FUNCTION_NAME, connection->io_path_acquired, timeout_milliseconds);
00949
00950 we_acquired = FALSE;
00951
00952 if (connection->io_path_acquired)
00953 {
00954 if (timeout_milliseconds != -1)
00955 {
00956 _dbus_verbose ("%s waiting %d for IO path to be acquirable\n",
00957 _DBUS_FUNCTION_NAME, timeout_milliseconds);
00958 _dbus_condvar_wait_timeout (connection->io_path_cond,
00959 connection->io_path_mutex,
00960 timeout_milliseconds);
00961 }
00962 else
00963 {
00964 while (connection->io_path_acquired)
00965 {
00966 _dbus_verbose ("%s waiting for IO path to be acquirable\n", _DBUS_FUNCTION_NAME);
00967 _dbus_condvar_wait (connection->io_path_cond,
00968 connection->io_path_mutex);
00969 }
00970 }
00971 }
00972
00973 if (!connection->io_path_acquired)
00974 {
00975 we_acquired = TRUE;
00976 connection->io_path_acquired = TRUE;
00977 }
00978
00979 _dbus_verbose ("%s end connection->io_path_acquired = %d we_acquired = %d\n",
00980 _DBUS_FUNCTION_NAME, connection->io_path_acquired, we_acquired);
00981
00982 _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
00983 _dbus_mutex_unlock (connection->io_path_mutex);
00984
00985 CONNECTION_LOCK (connection);
00986
00987 HAVE_LOCK_CHECK (connection);
00988
00989 _dbus_connection_unref_unlocked (connection);
00990
00991 return we_acquired;
00992 }
00993
01001 static void
01002 _dbus_connection_release_io_path (DBusConnection *connection)
01003 {
01004 HAVE_LOCK_CHECK (connection);
01005
01006 _dbus_verbose ("%s locking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01007 _dbus_mutex_lock (connection->io_path_mutex);
01008
01009 _dbus_assert (connection->io_path_acquired);
01010
01011 _dbus_verbose ("%s start connection->io_path_acquired = %d\n",
01012 _DBUS_FUNCTION_NAME, connection->io_path_acquired);
01013
01014 connection->io_path_acquired = FALSE;
01015 _dbus_condvar_wake_one (connection->io_path_cond);
01016
01017 _dbus_verbose ("%s unlocking io_path_mutex\n", _DBUS_FUNCTION_NAME);
01018 _dbus_mutex_unlock (connection->io_path_mutex);
01019 }
01020
01049 void
01050 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01051 unsigned int flags,
01052 int timeout_milliseconds)
01053 {
01054 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01055
01056 HAVE_LOCK_CHECK (connection);
01057
01058 if (connection->n_outgoing == 0)
01059 flags &= ~DBUS_ITERATION_DO_WRITING;
01060
01061 if (_dbus_connection_acquire_io_path (connection,
01062 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01063 {
01064 HAVE_LOCK_CHECK (connection);
01065
01066 _dbus_transport_do_iteration (connection->transport,
01067 flags, timeout_milliseconds);
01068 _dbus_connection_release_io_path (connection);
01069 }
01070
01071 HAVE_LOCK_CHECK (connection);
01072
01073 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01074 }
01075
01085 DBusConnection*
01086 _dbus_connection_new_for_transport (DBusTransport *transport)
01087 {
01088 DBusConnection *connection;
01089 DBusWatchList *watch_list;
01090 DBusTimeoutList *timeout_list;
01091 DBusHashTable *pending_replies;
01092 DBusList *disconnect_link;
01093 DBusMessage *disconnect_message;
01094 DBusCounter *outgoing_counter;
01095 DBusObjectTree *objects;
01096
01097 watch_list = NULL;
01098 connection = NULL;
01099 pending_replies = NULL;
01100 timeout_list = NULL;
01101 disconnect_link = NULL;
01102 disconnect_message = NULL;
01103 outgoing_counter = NULL;
01104 objects = NULL;
01105
01106 watch_list = _dbus_watch_list_new ();
01107 if (watch_list == NULL)
01108 goto error;
01109
01110 timeout_list = _dbus_timeout_list_new ();
01111 if (timeout_list == NULL)
01112 goto error;
01113
01114 pending_replies =
01115 _dbus_hash_table_new (DBUS_HASH_INT,
01116 NULL,
01117 (DBusFreeFunction)free_pending_call_on_hash_removal);
01118 if (pending_replies == NULL)
01119 goto error;
01120
01121 connection = dbus_new0 (DBusConnection, 1);
01122 if (connection == NULL)
01123 goto error;
01124
01125 _dbus_mutex_new_at_location (&connection->mutex);
01126 if (connection->mutex == NULL)
01127 goto error;
01128
01129 _dbus_mutex_new_at_location (&connection->io_path_mutex);
01130 if (connection->io_path_mutex == NULL)
01131 goto error;
01132
01133 _dbus_mutex_new_at_location (&connection->dispatch_mutex);
01134 if (connection->dispatch_mutex == NULL)
01135 goto error;
01136
01137 _dbus_condvar_new_at_location (&connection->dispatch_cond);
01138 if (connection->dispatch_cond == NULL)
01139 goto error;
01140
01141 _dbus_condvar_new_at_location (&connection->io_path_cond);
01142 if (connection->io_path_cond == NULL)
01143 goto error;
01144
01145 disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01146 DBUS_INTERFACE_LOCAL,
01147 "Disconnected");
01148
01149 if (disconnect_message == NULL)
01150 goto error;
01151
01152 disconnect_link = _dbus_list_alloc_link (disconnect_message);
01153 if (disconnect_link == NULL)
01154 goto error;
01155
01156 outgoing_counter = _dbus_counter_new ();
01157 if (outgoing_counter == NULL)
01158 goto error;
01159
01160 objects = _dbus_object_tree_new (connection);
01161 if (objects == NULL)
01162 goto error;
01163
01164 if (_dbus_modify_sigpipe)
01165 _dbus_disable_sigpipe ();
01166
01167 connection->refcount.value = 1;
01168 connection->transport = transport;
01169 connection->watches = watch_list;
01170 connection->timeouts = timeout_list;
01171 connection->pending_replies = pending_replies;
01172 connection->outgoing_counter = outgoing_counter;
01173 connection->filter_list = NULL;
01174 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE;
01175 connection->objects = objects;
01176 connection->exit_on_disconnect = FALSE;
01177 connection->shareable = FALSE;
01178 #ifndef DBUS_DISABLE_CHECKS
01179 connection->generation = _dbus_current_generation;
01180 #endif
01181
01182 _dbus_data_slot_list_init (&connection->slot_list);
01183
01184 connection->client_serial = 1;
01185
01186 connection->disconnect_message_link = disconnect_link;
01187
01188 CONNECTION_LOCK (connection);
01189
01190 if (!_dbus_transport_set_connection (transport, connection))
01191 {
01192 CONNECTION_UNLOCK (connection);
01193
01194 goto error;
01195 }
01196
01197 _dbus_transport_ref (transport);
01198
01199 CONNECTION_UNLOCK (connection);
01200
01201 return connection;
01202
01203 error:
01204 if (disconnect_message != NULL)
01205 dbus_message_unref (disconnect_message);
01206
01207 if (disconnect_link != NULL)
01208 _dbus_list_free_link (disconnect_link);
01209
01210 if (connection != NULL)
01211 {
01212 _dbus_condvar_free_at_location (&connection->io_path_cond);
01213 _dbus_condvar_free_at_location (&connection->dispatch_cond);
01214 _dbus_mutex_free_at_location (&connection->mutex);
01215 _dbus_mutex_free_at_location (&connection->io_path_mutex);
01216 _dbus_mutex_free_at_location (&connection->dispatch_mutex);
01217 dbus_free (connection);
01218 }
01219 if (pending_replies)
01220 _dbus_hash_table_unref (pending_replies);
01221
01222 if (watch_list)
01223 _dbus_watch_list_free (watch_list);
01224
01225 if (timeout_list)
01226 _dbus_timeout_list_free (timeout_list);
01227
01228 if (outgoing_counter)
01229 _dbus_counter_unref (outgoing_counter);
01230
01231 if (objects)
01232 _dbus_object_tree_unref (objects);
01233
01234 return NULL;
01235 }
01236
01244 DBusConnection *
01245 _dbus_connection_ref_unlocked (DBusConnection *connection)
01246 {
01247 _dbus_assert (connection != NULL);
01248 _dbus_assert (connection->generation == _dbus_current_generation);
01249
01250 HAVE_LOCK_CHECK (connection);
01251
01252 #ifdef DBUS_HAVE_ATOMIC_INT
01253 _dbus_atomic_inc (&connection->refcount);
01254 #else
01255 _dbus_assert (connection->refcount.value > 0);
01256 connection->refcount.value += 1;
01257 #endif
01258
01259 return connection;
01260 }
01261
01268 void
01269 _dbus_connection_unref_unlocked (DBusConnection *connection)
01270 {
01271 dbus_bool_t last_unref;
01272
01273 HAVE_LOCK_CHECK (connection);
01274
01275 _dbus_assert (connection != NULL);
01276
01277
01278
01279
01280
01281 #ifdef DBUS_HAVE_ATOMIC_INT
01282 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01283 #else
01284 _dbus_assert (connection->refcount.value > 0);
01285
01286 connection->refcount.value -= 1;
01287 last_unref = (connection->refcount.value == 0);
01288 #if 0
01289 printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01290 #endif
01291 #endif
01292
01293 if (last_unref)
01294 _dbus_connection_last_unref (connection);
01295 }
01296
01297 static dbus_uint32_t
01298 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01299 {
01300 int serial;
01301
01302 serial = connection->client_serial++;
01303
01304 if (connection->client_serial < 0)
01305 connection->client_serial = 1;
01306
01307 return serial;
01308 }
01309
01323 dbus_bool_t
01324 _dbus_connection_handle_watch (DBusWatch *watch,
01325 unsigned int condition,
01326 void *data)
01327 {
01328 DBusConnection *connection;
01329 dbus_bool_t retval;
01330 DBusDispatchStatus status;
01331
01332 connection = data;
01333
01334 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
01335
01336 CONNECTION_LOCK (connection);
01337 _dbus_connection_acquire_io_path (connection, -1);
01338 HAVE_LOCK_CHECK (connection);
01339 retval = _dbus_transport_handle_watch (connection->transport,
01340 watch, condition);
01341
01342 _dbus_connection_release_io_path (connection);
01343
01344 HAVE_LOCK_CHECK (connection);
01345
01346 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01347
01348 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01349
01350
01351 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01352
01353 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
01354
01355 return retval;
01356 }
01357
01358 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01359 static DBusHashTable *shared_connections = NULL;
01360
01361 static void
01362 shared_connections_shutdown (void *data)
01363 {
01364 _DBUS_LOCK (shared_connections);
01365
01366 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01367
01368 _dbus_hash_table_unref (shared_connections);
01369 shared_connections = NULL;
01370
01371 _DBUS_UNLOCK (shared_connections);
01372 }
01373
01374 static dbus_bool_t
01375 connection_lookup_shared (DBusAddressEntry *entry,
01376 DBusConnection **result)
01377 {
01378 _dbus_verbose ("checking for existing connection\n");
01379
01380 *result = NULL;
01381
01382 _DBUS_LOCK (shared_connections);
01383
01384 if (shared_connections == NULL)
01385 {
01386 _dbus_verbose ("creating shared_connections hash table\n");
01387
01388 shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01389 dbus_free,
01390 NULL);
01391 if (shared_connections == NULL)
01392 {
01393 _DBUS_UNLOCK (shared_connections);
01394 return FALSE;
01395 }
01396
01397 if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01398 {
01399 _dbus_hash_table_unref (shared_connections);
01400 shared_connections = NULL;
01401 _DBUS_UNLOCK (shared_connections);
01402 return FALSE;
01403 }
01404
01405 _dbus_verbose (" successfully created shared_connections\n");
01406
01407 _DBUS_UNLOCK (shared_connections);
01408 return TRUE;
01409 }
01410 else
01411 {
01412 const char *guid;
01413
01414 guid = dbus_address_entry_get_value (entry, "guid");
01415
01416 if (guid != NULL)
01417 {
01418 *result = _dbus_hash_table_lookup_string (shared_connections,
01419 guid);
01420
01421 if (*result)
01422 {
01423
01424
01425
01426
01427
01428
01429
01430
01431 dbus_connection_ref (*result);
01432
01433 _dbus_verbose ("looked up existing connection to server guid %s\n",
01434 guid);
01435 }
01436 }
01437
01438 _DBUS_UNLOCK (shared_connections);
01439 return TRUE;
01440 }
01441 }
01442
01443 static dbus_bool_t
01444 connection_record_shared_unlocked (DBusConnection *connection,
01445 const char *guid)
01446 {
01447 char *guid_key;
01448 char *guid_in_connection;
01449
01450
01451
01452
01453
01454
01455 _dbus_assert (connection->server_guid == NULL);
01456 _dbus_assert (connection->shareable);
01457
01458 guid_key = _dbus_strdup (guid);
01459 if (guid_key == NULL)
01460 return FALSE;
01461
01462 guid_in_connection = _dbus_strdup (guid);
01463 if (guid_in_connection == NULL)
01464 {
01465 dbus_free (guid_key);
01466 return FALSE;
01467 }
01468
01469 _DBUS_LOCK (shared_connections);
01470 _dbus_assert (shared_connections != NULL);
01471
01472 if (!_dbus_hash_table_insert_string (shared_connections,
01473 guid_key, connection))
01474 {
01475 dbus_free (guid_key);
01476 dbus_free (guid_in_connection);
01477 _DBUS_UNLOCK (shared_connections);
01478 return FALSE;
01479 }
01480
01481 connection->server_guid = guid_in_connection;
01482 connection->shared = TRUE;
01483
01484
01485 dbus_connection_ref (connection);
01486
01487 _dbus_verbose ("stored connection to %s to be shared\n",
01488 connection->server_guid);
01489
01490 _DBUS_UNLOCK (shared_connections);
01491
01492 _dbus_assert (connection->server_guid != NULL);
01493
01494 return TRUE;
01495 }
01496
01497 static void
01498 connection_forget_shared_unlocked (DBusConnection *connection)
01499 {
01500 HAVE_LOCK_CHECK (connection);
01501
01502 if (connection->server_guid == NULL)
01503 return;
01504
01505 _dbus_verbose ("dropping connection to %s out of the shared table\n",
01506 connection->server_guid);
01507
01508 _DBUS_LOCK (shared_connections);
01509
01510 if (!_dbus_hash_table_remove_string (shared_connections,
01511 connection->server_guid))
01512 _dbus_assert_not_reached ("connection was not in the shared table");
01513
01514 dbus_free (connection->server_guid);
01515 connection->server_guid = NULL;
01516
01517
01518 _dbus_connection_unref_unlocked (connection);
01519 _DBUS_UNLOCK (shared_connections);
01520 }
01521
01522 static DBusConnection*
01523 connection_try_from_address_entry (DBusAddressEntry *entry,
01524 DBusError *error)
01525 {
01526 DBusTransport *transport;
01527 DBusConnection *connection;
01528
01529 transport = _dbus_transport_open (entry, error);
01530
01531 if (transport == NULL)
01532 {
01533 _DBUS_ASSERT_ERROR_IS_SET (error);
01534 return NULL;
01535 }
01536
01537 connection = _dbus_connection_new_for_transport (transport);
01538
01539 _dbus_transport_unref (transport);
01540
01541 if (connection == NULL)
01542 {
01543 _DBUS_SET_OOM (error);
01544 return NULL;
01545 }
01546
01547 #ifndef DBUS_DISABLE_CHECKS
01548 _dbus_assert (!connection->have_connection_lock);
01549 #endif
01550 return connection;
01551 }
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565 static DBusConnection*
01566 _dbus_connection_open_internal (const char *address,
01567 dbus_bool_t shared,
01568 DBusError *error)
01569 {
01570 DBusConnection *connection;
01571 DBusAddressEntry **entries;
01572 DBusError tmp_error;
01573 DBusError first_error;
01574 int len, i;
01575
01576 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01577
01578 _dbus_verbose ("opening %s connection to: %s\n",
01579 shared ? "shared" : "private", address);
01580
01581 if (!dbus_parse_address (address, &entries, &len, error))
01582 return NULL;
01583
01584 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01585
01586 connection = NULL;
01587
01588 dbus_error_init (&tmp_error);
01589 dbus_error_init (&first_error);
01590 for (i = 0; i < len; i++)
01591 {
01592 if (shared)
01593 {
01594 if (!connection_lookup_shared (entries[i], &connection))
01595 _DBUS_SET_OOM (&tmp_error);
01596 }
01597
01598 if (connection == NULL)
01599 {
01600 connection = connection_try_from_address_entry (entries[i],
01601 &tmp_error);
01602
01603 if (connection != NULL && shared)
01604 {
01605 const char *guid;
01606
01607 connection->shareable = TRUE;
01608
01609 guid = dbus_address_entry_get_value (entries[i], "guid");
01610
01611
01612
01613
01614
01615 if (guid &&
01616 !connection_record_shared_unlocked (connection, guid))
01617 {
01618 _DBUS_SET_OOM (&tmp_error);
01619 _dbus_connection_close_internal (connection);
01620 dbus_connection_unref (connection);
01621 connection = NULL;
01622 }
01623
01624
01625
01626
01627 }
01628 }
01629
01630 if (connection)
01631 break;
01632
01633 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01634
01635 if (i == 0)
01636 dbus_move_error (&tmp_error, &first_error);
01637 else
01638 dbus_error_free (&tmp_error);
01639 }
01640
01641
01642
01643 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01644 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01645
01646 if (connection == NULL)
01647 {
01648 _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01649 dbus_move_error (&first_error, error);
01650 }
01651 else
01652 {
01653 dbus_error_free (&first_error);
01654 }
01655
01656 dbus_address_entries_free (entries);
01657 return connection;
01658 }
01659
01687 DBusConnection*
01688 dbus_connection_open (const char *address,
01689 DBusError *error)
01690 {
01691 DBusConnection *connection;
01692
01693 _dbus_return_val_if_fail (address != NULL, NULL);
01694 _dbus_return_val_if_error_is_set (error, NULL);
01695
01696 connection = _dbus_connection_open_internal (address,
01697 TRUE,
01698 error);
01699
01700 return connection;
01701 }
01702
01717 DBusConnection*
01718 dbus_connection_open_private (const char *address,
01719 DBusError *error)
01720 {
01721 DBusConnection *connection;
01722
01723 _dbus_return_val_if_fail (address != NULL, NULL);
01724 _dbus_return_val_if_error_is_set (error, NULL);
01725
01726 connection = _dbus_connection_open_internal (address,
01727 FALSE,
01728 error);
01729
01730 return connection;
01731 }
01732
01739 DBusConnection *
01740 dbus_connection_ref (DBusConnection *connection)
01741 {
01742 _dbus_return_val_if_fail (connection != NULL, NULL);
01743 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
01744
01745
01746
01747
01748
01749 #ifdef DBUS_HAVE_ATOMIC_INT
01750 _dbus_atomic_inc (&connection->refcount);
01751 #else
01752 CONNECTION_LOCK (connection);
01753 _dbus_assert (connection->refcount.value > 0);
01754
01755 connection->refcount.value += 1;
01756 CONNECTION_UNLOCK (connection);
01757 #endif
01758
01759 return connection;
01760 }
01761
01762 static void
01763 free_outgoing_message (void *element,
01764 void *data)
01765 {
01766 DBusMessage *message = element;
01767 DBusConnection *connection = data;
01768
01769 _dbus_message_remove_size_counter (message,
01770 connection->outgoing_counter,
01771 NULL);
01772 dbus_message_unref (message);
01773 }
01774
01775
01776
01777
01778
01779 static void
01780 _dbus_connection_last_unref (DBusConnection *connection)
01781 {
01782 DBusList *link;
01783
01784 _dbus_verbose ("Finalizing connection %p\n", connection);
01785
01786 _dbus_assert (connection->refcount.value == 0);
01787
01788
01789
01790
01791 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
01792 _dbus_assert (connection->server_guid == NULL);
01793
01794
01795 _dbus_object_tree_free_all_unlocked (connection->objects);
01796
01797 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
01798 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
01799 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
01800
01801 _dbus_watch_list_free (connection->watches);
01802 connection->watches = NULL;
01803
01804 _dbus_timeout_list_free (connection->timeouts);
01805 connection->timeouts = NULL;
01806
01807 _dbus_data_slot_list_free (&connection->slot_list);
01808
01809 link = _dbus_list_get_first_link (&connection->filter_list);
01810 while (link != NULL)
01811 {
01812 DBusMessageFilter *filter = link->data;
01813 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
01814
01815 filter->function = NULL;
01816 _dbus_message_filter_unref (filter);
01817 link->data = NULL;
01818
01819 link = next;
01820 }
01821 _dbus_list_clear (&connection->filter_list);
01822
01823
01824
01825 _dbus_object_tree_unref (connection->objects);
01826
01827 _dbus_hash_table_unref (connection->pending_replies);
01828 connection->pending_replies = NULL;
01829
01830 _dbus_list_clear (&connection->filter_list);
01831
01832 _dbus_list_foreach (&connection->outgoing_messages,
01833 free_outgoing_message,
01834 connection);
01835 _dbus_list_clear (&connection->outgoing_messages);
01836
01837 _dbus_list_foreach (&connection->incoming_messages,
01838 (DBusForeachFunction) dbus_message_unref,
01839 NULL);
01840 _dbus_list_clear (&connection->incoming_messages);
01841
01842 _dbus_counter_unref (connection->outgoing_counter);
01843
01844 _dbus_transport_unref (connection->transport);
01845
01846 if (connection->disconnect_message_link)
01847 {
01848 DBusMessage *message = connection->disconnect_message_link->data;
01849 dbus_message_unref (message);
01850 _dbus_list_free_link (connection->disconnect_message_link);
01851 }
01852
01853 _dbus_list_clear (&connection->link_cache);
01854
01855 _dbus_condvar_free_at_location (&connection->dispatch_cond);
01856 _dbus_condvar_free_at_location (&connection->io_path_cond);
01857
01858 _dbus_mutex_free_at_location (&connection->io_path_mutex);
01859 _dbus_mutex_free_at_location (&connection->dispatch_mutex);
01860
01861 _dbus_mutex_free_at_location (&connection->mutex);
01862
01863 dbus_free (connection);
01864 }
01865
01877 void
01878 dbus_connection_unref (DBusConnection *connection)
01879 {
01880 dbus_bool_t last_unref;
01881
01882 _dbus_return_if_fail (connection != NULL);
01883 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
01884
01885
01886
01887
01888
01889 #ifdef DBUS_HAVE_ATOMIC_INT
01890 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01891 #else
01892 CONNECTION_LOCK (connection);
01893
01894 _dbus_assert (connection->refcount.value > 0);
01895
01896 connection->refcount.value -= 1;
01897 last_unref = (connection->refcount.value == 0);
01898
01899 #if 0
01900 printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
01901 #endif
01902
01903 CONNECTION_UNLOCK (connection);
01904 #endif
01905
01906 if (last_unref)
01907 _dbus_connection_last_unref (connection);
01908 }
01909
01910 static void
01911 _dbus_connection_close_internal_and_unlock (DBusConnection *connection)
01912 {
01913 DBusDispatchStatus status;
01914
01915 _dbus_verbose ("Disconnecting %p\n", connection);
01916
01917 _dbus_transport_disconnect (connection->transport);
01918
01919 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
01920 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01921
01922
01923 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01924 }
01925
01926 void
01927 _dbus_connection_close_internal (DBusConnection *connection)
01928 {
01929 _dbus_assert (connection != NULL);
01930 _dbus_assert (connection->generation == _dbus_current_generation);
01931
01932 CONNECTION_LOCK (connection);
01933 _dbus_connection_close_internal_and_unlock (connection);
01934 }
01935
01953 void
01954 dbus_connection_close (DBusConnection *connection)
01955 {
01956 _dbus_return_if_fail (connection != NULL);
01957 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
01958
01959 CONNECTION_LOCK (connection);
01960
01961 if (connection->shared)
01962 {
01963 CONNECTION_UNLOCK (connection);
01964
01965 _dbus_warn ("Applications can not close shared connections. Please fix this in your app. Ignoring close request and continuing.");
01966 return;
01967 }
01968
01969 _dbus_connection_close_internal_and_unlock (connection);
01970 }
01971
01972 static dbus_bool_t
01973 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
01974 {
01975 HAVE_LOCK_CHECK (connection);
01976 return _dbus_transport_get_is_connected (connection->transport);
01977 }
01978
01989 dbus_bool_t
01990 dbus_connection_get_is_connected (DBusConnection *connection)
01991 {
01992 dbus_bool_t res;
01993
01994 _dbus_return_val_if_fail (connection != NULL, FALSE);
01995
01996 CONNECTION_LOCK (connection);
01997 res = _dbus_connection_get_is_connected_unlocked (connection);
01998 CONNECTION_UNLOCK (connection);
01999
02000 return res;
02001 }
02002
02011 dbus_bool_t
02012 dbus_connection_get_is_authenticated (DBusConnection *connection)
02013 {
02014 dbus_bool_t res;
02015
02016 _dbus_return_val_if_fail (connection != NULL, FALSE);
02017
02018 CONNECTION_LOCK (connection);
02019 res = _dbus_transport_get_is_authenticated (connection->transport);
02020 CONNECTION_UNLOCK (connection);
02021
02022 return res;
02023 }
02024
02038 void
02039 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
02040 dbus_bool_t exit_on_disconnect)
02041 {
02042 _dbus_return_if_fail (connection != NULL);
02043
02044 CONNECTION_LOCK (connection);
02045 connection->exit_on_disconnect = exit_on_disconnect != FALSE;
02046 CONNECTION_UNLOCK (connection);
02047 }
02048
02049 static DBusPreallocatedSend*
02050 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
02051 {
02052 DBusPreallocatedSend *preallocated;
02053
02054 HAVE_LOCK_CHECK (connection);
02055
02056 _dbus_assert (connection != NULL);
02057
02058 preallocated = dbus_new (DBusPreallocatedSend, 1);
02059 if (preallocated == NULL)
02060 return NULL;
02061
02062 if (connection->link_cache != NULL)
02063 {
02064 preallocated->queue_link =
02065 _dbus_list_pop_first_link (&connection->link_cache);
02066 preallocated->queue_link->data = NULL;
02067 }
02068 else
02069 {
02070 preallocated->queue_link = _dbus_list_alloc_link (NULL);
02071 if (preallocated->queue_link == NULL)
02072 goto failed_0;
02073 }
02074
02075 if (connection->link_cache != NULL)
02076 {
02077 preallocated->counter_link =
02078 _dbus_list_pop_first_link (&connection->link_cache);
02079 preallocated->counter_link->data = connection->outgoing_counter;
02080 }
02081 else
02082 {
02083 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
02084 if (preallocated->counter_link == NULL)
02085 goto failed_1;
02086 }
02087
02088 _dbus_counter_ref (preallocated->counter_link->data);
02089
02090 preallocated->connection = connection;
02091
02092 return preallocated;
02093
02094 failed_1:
02095 _dbus_list_free_link (preallocated->queue_link);
02096 failed_0:
02097 dbus_free (preallocated);
02098
02099 return NULL;
02100 }
02101
02111 DBusPreallocatedSend*
02112 dbus_connection_preallocate_send (DBusConnection *connection)
02113 {
02114 DBusPreallocatedSend *preallocated;
02115
02116 _dbus_return_val_if_fail (connection != NULL, NULL);
02117
02118 CONNECTION_LOCK (connection);
02119
02120 preallocated =
02121 _dbus_connection_preallocate_send_unlocked (connection);
02122
02123 CONNECTION_UNLOCK (connection);
02124
02125 return preallocated;
02126 }
02127
02137 void
02138 dbus_connection_free_preallocated_send (DBusConnection *connection,
02139 DBusPreallocatedSend *preallocated)
02140 {
02141 _dbus_return_if_fail (connection != NULL);
02142 _dbus_return_if_fail (preallocated != NULL);
02143 _dbus_return_if_fail (connection == preallocated->connection);
02144
02145 _dbus_list_free_link (preallocated->queue_link);
02146 _dbus_counter_unref (preallocated->counter_link->data);
02147 _dbus_list_free_link (preallocated->counter_link);
02148 dbus_free (preallocated);
02149 }
02150
02151
02152 static void
02153 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection,
02154 DBusPreallocatedSend *preallocated,
02155 DBusMessage *message,
02156 dbus_uint32_t *client_serial)
02157 {
02158 dbus_uint32_t serial;
02159 const char *sig;
02160
02161 preallocated->queue_link->data = message;
02162 _dbus_list_prepend_link (&connection->outgoing_messages,
02163 preallocated->queue_link);
02164
02165 _dbus_message_add_size_counter_link (message,
02166 preallocated->counter_link);
02167
02168 dbus_free (preallocated);
02169 preallocated = NULL;
02170
02171 dbus_message_ref (message);
02172
02173 connection->n_outgoing += 1;
02174
02175 sig = dbus_message_get_signature (message);
02176
02177 _dbus_verbose ("Message %p (%d %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
02178 message,
02179 dbus_message_get_type (message),
02180 dbus_message_get_path (message) ?
02181 dbus_message_get_path (message) :
02182 "no path",
02183 dbus_message_get_interface (message) ?
02184 dbus_message_get_interface (message) :
02185 "no interface",
02186 dbus_message_get_member (message) ?
02187 dbus_message_get_member (message) :
02188 "no member",
02189 sig,
02190 dbus_message_get_destination (message) ?
02191 dbus_message_get_destination (message) :
02192 "null",
02193 connection,
02194 connection->n_outgoing);
02195
02196 if (dbus_message_get_serial (message) == 0)
02197 {
02198 serial = _dbus_connection_get_next_client_serial (connection);
02199 _dbus_message_set_serial (message, serial);
02200 if (client_serial)
02201 *client_serial = serial;
02202 }
02203 else
02204 {
02205 if (client_serial)
02206 *client_serial = dbus_message_get_serial (message);
02207 }
02208
02209 _dbus_verbose ("Message %p serial is %u\n",
02210 message, dbus_message_get_serial (message));
02211
02212 _dbus_message_lock (message);
02213
02214
02215
02216
02217 _dbus_connection_do_iteration_unlocked (connection,
02218 DBUS_ITERATION_DO_WRITING,
02219 -1);
02220
02221
02222 if (connection->n_outgoing > 0)
02223 _dbus_connection_wakeup_mainloop (connection);
02224 }
02225
02226 static void
02227 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection,
02228 DBusPreallocatedSend *preallocated,
02229 DBusMessage *message,
02230 dbus_uint32_t *client_serial)
02231 {
02232 DBusDispatchStatus status;
02233
02234 HAVE_LOCK_CHECK (connection);
02235
02236 _dbus_connection_send_preallocated_unlocked_no_update (connection,
02237 preallocated,
02238 message, client_serial);
02239
02240 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02241 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02242
02243
02244 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02245 }
02246
02259 void
02260 dbus_connection_send_preallocated (DBusConnection *connection,
02261 DBusPreallocatedSend *preallocated,
02262 DBusMessage *message,
02263 dbus_uint32_t *client_serial)
02264 {
02265 _dbus_return_if_fail (connection != NULL);
02266 _dbus_return_if_fail (preallocated != NULL);
02267 _dbus_return_if_fail (message != NULL);
02268 _dbus_return_if_fail (preallocated->connection == connection);
02269 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
02270 dbus_message_get_member (message) != NULL);
02271 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
02272 (dbus_message_get_interface (message) != NULL &&
02273 dbus_message_get_member (message) != NULL));
02274
02275 CONNECTION_LOCK (connection);
02276 _dbus_connection_send_preallocated_and_unlock (connection,
02277 preallocated,
02278 message, client_serial);
02279 }
02280
02281 static dbus_bool_t
02282 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
02283 DBusMessage *message,
02284 dbus_uint32_t *client_serial)
02285 {
02286 DBusPreallocatedSend *preallocated;
02287
02288 _dbus_assert (connection != NULL);
02289 _dbus_assert (message != NULL);
02290
02291 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02292 if (preallocated == NULL)
02293 return FALSE;
02294
02295 _dbus_connection_send_preallocated_unlocked_no_update (connection,
02296 preallocated,
02297 message,
02298 client_serial);
02299 return TRUE;
02300 }
02301
02302 dbus_bool_t
02303 _dbus_connection_send_and_unlock (DBusConnection *connection,
02304 DBusMessage *message,
02305 dbus_uint32_t *client_serial)
02306 {
02307 DBusPreallocatedSend *preallocated;
02308
02309 _dbus_assert (connection != NULL);
02310 _dbus_assert (message != NULL);
02311
02312 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02313 if (preallocated == NULL)
02314 {
02315 CONNECTION_UNLOCK (connection);
02316 return FALSE;
02317 }
02318
02319 _dbus_connection_send_preallocated_and_unlock (connection,
02320 preallocated,
02321 message,
02322 client_serial);
02323 return TRUE;
02324 }
02325
02344 dbus_bool_t
02345 dbus_connection_send (DBusConnection *connection,
02346 DBusMessage *message,
02347 dbus_uint32_t *client_serial)
02348 {
02349 _dbus_return_val_if_fail (connection != NULL, FALSE);
02350 _dbus_return_val_if_fail (message != NULL, FALSE);
02351
02352 CONNECTION_LOCK (connection);
02353
02354 return _dbus_connection_send_and_unlock (connection,
02355 message,
02356 client_serial);
02357 }
02358
02359 static dbus_bool_t
02360 reply_handler_timeout (void *data)
02361 {
02362 DBusConnection *connection;
02363 DBusDispatchStatus status;
02364 DBusPendingCall *pending = data;
02365
02366 connection = _dbus_pending_call_get_connection_and_lock (pending);
02367
02368 _dbus_pending_call_queue_timeout_error_unlocked (pending,
02369 connection);
02370 _dbus_connection_remove_timeout_unlocked (connection,
02371 _dbus_pending_call_get_timeout_unlocked (pending));
02372 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
02373
02374 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02375 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02376
02377
02378 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02379
02380 return TRUE;
02381 }
02382
02420 dbus_bool_t
02421 dbus_connection_send_with_reply (DBusConnection *connection,
02422 DBusMessage *message,
02423 DBusPendingCall **pending_return,
02424 int timeout_milliseconds)
02425 {
02426 DBusPendingCall *pending;
02427 dbus_int32_t serial = -1;
02428 DBusDispatchStatus status;
02429
02430 _dbus_return_val_if_fail (connection != NULL, FALSE);
02431 _dbus_return_val_if_fail (message != NULL, FALSE);
02432 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
02433
02434 if (pending_return)
02435 *pending_return = NULL;
02436
02437 CONNECTION_LOCK (connection);
02438
02439 if (!_dbus_connection_get_is_connected_unlocked (connection))
02440 {
02441 CONNECTION_UNLOCK (connection);
02442
02443 *pending_return = NULL;
02444
02445 return TRUE;
02446 }
02447
02448 pending = _dbus_pending_call_new_unlocked (connection,
02449 timeout_milliseconds,
02450 reply_handler_timeout);
02451
02452 if (pending == NULL)
02453 {
02454 CONNECTION_UNLOCK (connection);
02455 return FALSE;
02456 }
02457
02458
02459 serial = dbus_message_get_serial (message);
02460 if (serial == 0)
02461 {
02462 serial = _dbus_connection_get_next_client_serial (connection);
02463 _dbus_message_set_serial (message, serial);
02464 }
02465
02466 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
02467 goto error;
02468
02469
02470
02471
02472
02473 if (!_dbus_connection_attach_pending_call_unlocked (connection,
02474 pending))
02475 goto error;
02476
02477 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
02478 {
02479 _dbus_connection_detach_pending_call_and_unlock (connection,
02480 pending);
02481 goto error_unlocked;
02482 }
02483
02484 if (pending_return)
02485 *pending_return = pending;
02486 else
02487 {
02488 _dbus_connection_detach_pending_call_unlocked (connection, pending);
02489
02490
02491
02492 }
02493
02494 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02495
02496
02497 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02498
02499 if (pending_return == NULL)
02500 dbus_pending_call_unref (pending);
02501
02502 return TRUE;
02503
02504 error:
02505 CONNECTION_UNLOCK (connection);
02506 error_unlocked:
02507 dbus_pending_call_unref (pending);
02508 return FALSE;
02509 }
02510
02511
02512
02513
02514 static DBusMessage*
02515 check_for_reply_unlocked (DBusConnection *connection,
02516 dbus_uint32_t client_serial)
02517 {
02518 DBusList *link;
02519
02520 HAVE_LOCK_CHECK (connection);
02521
02522 link = _dbus_list_get_first_link (&connection->incoming_messages);
02523
02524 while (link != NULL)
02525 {
02526 DBusMessage *reply = link->data;
02527
02528 if (dbus_message_get_reply_serial (reply) == client_serial)
02529 {
02530 _dbus_list_remove_link (&connection->incoming_messages, link);
02531 connection->n_incoming -= 1;
02532 return reply;
02533 }
02534 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02535 }
02536
02537 return NULL;
02538 }
02539
02540 static void
02541 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
02542 {
02543
02544
02545
02546
02547
02548 while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
02549 {
02550 DBusPendingCall *pending;
02551 DBusHashIter iter;
02552
02553 _dbus_hash_iter_init (connection->pending_replies, &iter);
02554 _dbus_hash_iter_next (&iter);
02555
02556 pending = (DBusPendingCall *) _dbus_hash_iter_get_value (&iter);
02557 _dbus_pending_call_ref_unlocked (pending);
02558
02559 _dbus_pending_call_queue_timeout_error_unlocked (pending,
02560 connection);
02561 _dbus_connection_remove_timeout_unlocked (connection,
02562 _dbus_pending_call_get_timeout_unlocked (pending));
02563 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
02564 _dbus_hash_iter_remove_entry (&iter);
02565
02566 _dbus_pending_call_unref_and_unlock (pending);
02567 CONNECTION_LOCK (connection);
02568 }
02569 HAVE_LOCK_CHECK (connection);
02570 }
02571
02572 static void
02573 complete_pending_call_and_unlock (DBusConnection *connection,
02574 DBusPendingCall *pending,
02575 DBusMessage *message)
02576 {
02577 _dbus_pending_call_set_reply_unlocked (pending, message);
02578 _dbus_pending_call_ref_unlocked (pending);
02579 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
02580
02581
02582 _dbus_pending_call_complete (pending);
02583 dbus_pending_call_unref (pending);
02584 }
02585
02586 static dbus_bool_t
02587 check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection,
02588 DBusPendingCall *pending)
02589 {
02590 DBusMessage *reply;
02591 DBusDispatchStatus status;
02592
02593 reply = check_for_reply_unlocked (connection,
02594 _dbus_pending_call_get_reply_serial_unlocked (pending));
02595 if (reply != NULL)
02596 {
02597 _dbus_verbose ("%s checked for reply\n", _DBUS_FUNCTION_NAME);
02598
02599 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02600
02601 complete_pending_call_and_unlock (connection, pending, reply);
02602 dbus_message_unref (reply);
02603
02604 CONNECTION_LOCK (connection);
02605 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02606 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02607 dbus_pending_call_unref (pending);
02608
02609 return TRUE;
02610 }
02611
02612 return FALSE;
02613 }
02614
02624 static void
02625 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02626 {
02627 if (timeout_milliseconds == -1)
02628 _dbus_sleep_milliseconds (1000);
02629 else if (timeout_milliseconds < 100)
02630 ;
02631 else if (timeout_milliseconds <= 1000)
02632 _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02633 else
02634 _dbus_sleep_milliseconds (1000);
02635 }
02636
02637 static DBusMessage *
02638 generate_local_error_message (dbus_uint32_t serial,
02639 char *error_name,
02640 char *error_msg)
02641 {
02642 DBusMessage *message;
02643 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
02644 if (!message)
02645 goto out;
02646
02647 if (!dbus_message_set_error_name (message, error_name))
02648 {
02649 dbus_message_unref (message);
02650 message = NULL;
02651 goto out;
02652 }
02653
02654 dbus_message_set_no_reply (message, TRUE);
02655
02656 if (!dbus_message_set_reply_serial (message,
02657 serial))
02658 {
02659 dbus_message_unref (message);
02660 message = NULL;
02661 goto out;
02662 }
02663
02664 if (error_msg != NULL)
02665 {
02666 DBusMessageIter iter;
02667
02668 dbus_message_iter_init_append (message, &iter);
02669 if (!dbus_message_iter_append_basic (&iter,
02670 DBUS_TYPE_STRING,
02671 &error_msg))
02672 {
02673 dbus_message_unref (message);
02674 message = NULL;
02675 goto out;
02676 }
02677 }
02678
02679 out:
02680 return message;
02681 }
02682
02697 void
02698 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02699 {
02700 long start_tv_sec, start_tv_usec;
02701 long end_tv_sec, end_tv_usec;
02702 long tv_sec, tv_usec;
02703 DBusDispatchStatus status;
02704 DBusConnection *connection;
02705 dbus_uint32_t client_serial;
02706 int timeout_milliseconds;
02707
02708 _dbus_assert (pending != NULL);
02709
02710 if (dbus_pending_call_get_completed (pending))
02711 return;
02712
02713 dbus_pending_call_ref (pending);
02714
02715 connection = _dbus_pending_call_get_connection_and_lock (pending);
02716
02717
02718 _dbus_connection_flush_unlocked (connection);
02719
02720 client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
02721
02722
02723
02724
02725
02726 timeout_milliseconds = dbus_timeout_get_interval (_dbus_pending_call_get_timeout_unlocked (pending));
02727
02728 _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02729 end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
02730 end_tv_usec = start_tv_usec + (timeout_milliseconds % 1000) * 1000;
02731 end_tv_sec += end_tv_usec / _DBUS_USEC_PER_SECOND;
02732 end_tv_usec = end_tv_usec % _DBUS_USEC_PER_SECOND;
02733
02734 _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",
02735 timeout_milliseconds,
02736 client_serial,
02737 start_tv_sec, start_tv_usec,
02738 end_tv_sec, end_tv_usec);
02739
02740
02741
02742 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02743 return;
02744
02745
02746
02747 _dbus_connection_do_iteration_unlocked (connection,
02748 DBUS_ITERATION_DO_READING |
02749 DBUS_ITERATION_BLOCK,
02750 timeout_milliseconds);
02751
02752 recheck_status:
02753
02754 _dbus_verbose ("%s top of recheck\n", _DBUS_FUNCTION_NAME);
02755
02756 HAVE_LOCK_CHECK (connection);
02757
02758
02759
02760 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02761
02762
02763
02764
02765 if (_dbus_pending_call_get_completed_unlocked (pending))
02766 {
02767 _dbus_verbose ("Pending call completed by dispatch in %s\n", _DBUS_FUNCTION_NAME);
02768 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02769 dbus_pending_call_unref (pending);
02770 return;
02771 }
02772
02773 if (status == DBUS_DISPATCH_DATA_REMAINS) {
02774 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02775 return;
02776 }
02777
02778 _dbus_get_current_time (&tv_sec, &tv_usec);
02779
02780 if (!_dbus_connection_get_is_connected_unlocked (connection))
02781 {
02782 DBusMessage *error_msg;
02783
02784 error_msg = generate_local_error_message (client_serial,
02785 DBUS_ERROR_DISCONNECTED,
02786 "Connection was dissconnected before a reply was recived");
02787
02788
02789 complete_pending_call_and_unlock (connection, pending, error_msg);
02790 dbus_pending_call_unref (pending);
02791 return;
02792 }
02793 else if (tv_sec < start_tv_sec)
02794 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02795 else if (connection->disconnect_message_link == NULL)
02796 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02797 else if (tv_sec < end_tv_sec ||
02798 (tv_sec == end_tv_sec && tv_usec < end_tv_usec))
02799 {
02800 timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +
02801 (end_tv_usec - tv_usec) / 1000;
02802 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds);
02803 _dbus_assert (timeout_milliseconds >= 0);
02804
02805 if (status == DBUS_DISPATCH_NEED_MEMORY)
02806 {
02807
02808
02809
02810
02811 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02812
02813 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
02814 }
02815 else
02816 {
02817
02818 _dbus_connection_do_iteration_unlocked (connection,
02819 DBUS_ITERATION_DO_READING |
02820 DBUS_ITERATION_BLOCK,
02821 timeout_milliseconds);
02822 }
02823
02824 goto recheck_status;
02825 }
02826
02827 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n",
02828 (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000);
02829
02830 _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
02831
02832
02833 complete_pending_call_and_unlock (connection, pending, NULL);
02834
02835
02836 CONNECTION_LOCK (connection);
02837 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02838 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02839 dbus_pending_call_unref (pending);
02840 }
02841
02864 DBusMessage*
02865 dbus_connection_send_with_reply_and_block (DBusConnection *connection,
02866 DBusMessage *message,
02867 int timeout_milliseconds,
02868 DBusError *error)
02869 {
02870 DBusMessage *reply;
02871 DBusPendingCall *pending;
02872
02873 _dbus_return_val_if_fail (connection != NULL, NULL);
02874 _dbus_return_val_if_fail (message != NULL, NULL);
02875 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
02876 _dbus_return_val_if_error_is_set (error, NULL);
02877
02878 if (!dbus_connection_send_with_reply (connection, message,
02879 &pending, timeout_milliseconds))
02880 {
02881 _DBUS_SET_OOM (error);
02882 return NULL;
02883 }
02884
02885 _dbus_assert (pending != NULL);
02886
02887 dbus_pending_call_block (pending);
02888
02889 reply = dbus_pending_call_steal_reply (pending);
02890 dbus_pending_call_unref (pending);
02891
02892
02893
02894
02895 _dbus_assert (reply != NULL);
02896
02897 if (dbus_set_error_from_message (error, reply))
02898 {
02899 dbus_message_unref (reply);
02900 return NULL;
02901 }
02902 else
02903 return reply;
02904 }
02905
02914 DBusDispatchStatus
02915 _dbus_connection_flush_unlocked (DBusConnection *connection)
02916 {
02917
02918
02919
02920
02921
02922 DBusDispatchStatus status;
02923
02924 HAVE_LOCK_CHECK (connection);
02925
02926 while (connection->n_outgoing > 0 &&
02927 _dbus_connection_get_is_connected_unlocked (connection))
02928 {
02929 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
02930 HAVE_LOCK_CHECK (connection);
02931 _dbus_connection_do_iteration_unlocked (connection,
02932 DBUS_ITERATION_DO_READING |
02933 DBUS_ITERATION_DO_WRITING |
02934 DBUS_ITERATION_BLOCK,
02935 -1);
02936 }
02937
02938 HAVE_LOCK_CHECK (connection);
02939 _dbus_verbose ("%s middle\n", _DBUS_FUNCTION_NAME);
02940 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02941
02942 HAVE_LOCK_CHECK (connection);
02943 return status;
02944 }
02945
02951 void
02952 dbus_connection_flush (DBusConnection *connection)
02953 {
02954
02955
02956
02957
02958
02959 DBusDispatchStatus status;
02960
02961 _dbus_return_if_fail (connection != NULL);
02962
02963 CONNECTION_LOCK (connection);
02964
02965 status = _dbus_connection_flush_unlocked (connection);
02966
02967 HAVE_LOCK_CHECK (connection);
02968
02969 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02970
02971 _dbus_verbose ("%s end\n", _DBUS_FUNCTION_NAME);
02972 }
02973
03006 static dbus_bool_t
03007 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03008 int timeout_milliseconds,
03009 dbus_bool_t dispatch)
03010 {
03011 DBusDispatchStatus dstatus;
03012 dbus_bool_t dispatched_disconnected;
03013
03014 dstatus = dbus_connection_get_dispatch_status (connection);
03015
03016 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03017 {
03018 _dbus_verbose ("doing dispatch in %s\n", _DBUS_FUNCTION_NAME);
03019 dbus_connection_dispatch (connection);
03020 CONNECTION_LOCK (connection);
03021 }
03022 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03023 {
03024 _dbus_verbose ("pausing for memory in %s\n", _DBUS_FUNCTION_NAME);
03025 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03026 CONNECTION_LOCK (connection);
03027 }
03028 else
03029 {
03030 CONNECTION_LOCK (connection);
03031 if (_dbus_connection_get_is_connected_unlocked (connection))
03032 {
03033 _dbus_verbose ("doing iteration in %s\n", _DBUS_FUNCTION_NAME);
03034 _dbus_connection_do_iteration_unlocked (connection,
03035 DBUS_ITERATION_DO_READING |
03036 DBUS_ITERATION_DO_WRITING |
03037 DBUS_ITERATION_BLOCK,
03038 timeout_milliseconds);
03039 }
03040 }
03041
03042 HAVE_LOCK_CHECK (connection);
03043 dispatched_disconnected = connection->n_incoming == 0 &&
03044 connection->disconnect_message_link == NULL;
03045 CONNECTION_UNLOCK (connection);
03046 return !dispatched_disconnected;
03047 }
03048
03049
03081 dbus_bool_t
03082 dbus_connection_read_write_dispatch (DBusConnection *connection,
03083 int timeout_milliseconds)
03084 {
03085 _dbus_return_val_if_fail (connection != NULL, FALSE);
03086 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03087 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03088 }
03089
03106 dbus_bool_t
03107 dbus_connection_read_write (DBusConnection *connection,
03108 int timeout_milliseconds)
03109 {
03110 _dbus_return_val_if_fail (connection != NULL, FALSE);
03111 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03112 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03113 }
03114
03134 DBusMessage*
03135 dbus_connection_borrow_message (DBusConnection *connection)
03136 {
03137 DBusDispatchStatus status;
03138 DBusMessage *message;
03139
03140 _dbus_return_val_if_fail (connection != NULL, NULL);
03141
03142 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03143
03144
03145
03146
03147 status = dbus_connection_get_dispatch_status (connection);
03148 if (status != DBUS_DISPATCH_DATA_REMAINS)
03149 return NULL;
03150
03151 CONNECTION_LOCK (connection);
03152
03153 _dbus_connection_acquire_dispatch (connection);
03154
03155
03156 _dbus_assert (connection->message_borrowed == NULL);
03157
03158 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03159
03160 message = connection->message_borrowed;
03161
03162
03163 if (message == NULL)
03164 _dbus_connection_release_dispatch (connection);
03165
03166 CONNECTION_UNLOCK (connection);
03167
03168 return message;
03169 }
03170
03179 void
03180 dbus_connection_return_message (DBusConnection *connection,
03181 DBusMessage *message)
03182 {
03183 _dbus_return_if_fail (connection != NULL);
03184 _dbus_return_if_fail (message != NULL);
03185 _dbus_return_if_fail (message == connection->message_borrowed);
03186 _dbus_return_if_fail (connection->dispatch_acquired);
03187
03188 CONNECTION_LOCK (connection);
03189
03190 _dbus_assert (message == connection->message_borrowed);
03191
03192 connection->message_borrowed = NULL;
03193
03194 _dbus_connection_release_dispatch (connection);
03195
03196 CONNECTION_UNLOCK (connection);
03197 }
03198
03208 void
03209 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03210 DBusMessage *message)
03211 {
03212 DBusMessage *pop_message;
03213
03214 _dbus_return_if_fail (connection != NULL);
03215 _dbus_return_if_fail (message != NULL);
03216 _dbus_return_if_fail (message == connection->message_borrowed);
03217 _dbus_return_if_fail (connection->dispatch_acquired);
03218
03219 CONNECTION_LOCK (connection);
03220
03221 _dbus_assert (message == connection->message_borrowed);
03222
03223 pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03224 _dbus_assert (message == pop_message);
03225
03226 connection->n_incoming -= 1;
03227
03228 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03229 message, connection->n_incoming);
03230
03231 connection->message_borrowed = NULL;
03232
03233 _dbus_connection_release_dispatch (connection);
03234
03235 CONNECTION_UNLOCK (connection);
03236 }
03237
03238
03239
03240
03241 static DBusList*
03242 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03243 {
03244 HAVE_LOCK_CHECK (connection);
03245
03246 _dbus_assert (connection->message_borrowed == NULL);
03247
03248 if (connection->n_incoming > 0)
03249 {
03250 DBusList *link;
03251
03252 link = _dbus_list_pop_first_link (&connection->incoming_messages);
03253 connection->n_incoming -= 1;
03254
03255 _dbus_verbose ("Message %p (%d %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03256 link->data,
03257 dbus_message_get_type (link->data),
03258 dbus_message_get_path (link->data) ?
03259 dbus_message_get_path (link->data) :
03260 "no path",
03261 dbus_message_get_interface (link->data) ?
03262 dbus_message_get_interface (link->data) :
03263 "no interface",
03264 dbus_message_get_member (link->data) ?
03265 dbus_message_get_member (link->data) :
03266 "no member",
03267 dbus_message_get_signature (link->data),
03268 connection, connection->n_incoming);
03269
03270 return link;
03271 }
03272 else
03273 return NULL;
03274 }
03275
03276
03277
03278
03279 static DBusMessage*
03280 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03281 {
03282 DBusList *link;
03283
03284 HAVE_LOCK_CHECK (connection);
03285
03286 link = _dbus_connection_pop_message_link_unlocked (connection);
03287
03288 if (link != NULL)
03289 {
03290 DBusMessage *message;
03291
03292 message = link->data;
03293
03294 _dbus_list_free_link (link);
03295
03296 return message;
03297 }
03298 else
03299 return NULL;
03300 }
03301
03302 static void
03303 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
03304 DBusList *message_link)
03305 {
03306 HAVE_LOCK_CHECK (connection);
03307
03308 _dbus_assert (message_link != NULL);
03309
03310 _dbus_assert (connection->message_borrowed == NULL);
03311
03312 _dbus_assert (connection->dispatch_acquired);
03313
03314 _dbus_list_prepend_link (&connection->incoming_messages,
03315 message_link);
03316 connection->n_incoming += 1;
03317
03318 _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n",
03319 message_link->data,
03320 dbus_message_get_type (message_link->data),
03321 dbus_message_get_interface (message_link->data) ?
03322 dbus_message_get_interface (message_link->data) :
03323 "no interface",
03324 dbus_message_get_member (message_link->data) ?
03325 dbus_message_get_member (message_link->data) :
03326 "no member",
03327 dbus_message_get_signature (message_link->data),
03328 connection, connection->n_incoming);
03329 }
03330
03350 DBusMessage*
03351 dbus_connection_pop_message (DBusConnection *connection)
03352 {
03353 DBusMessage *message;
03354 DBusDispatchStatus status;
03355
03356 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03357
03358
03359
03360
03361 status = dbus_connection_get_dispatch_status (connection);
03362 if (status != DBUS_DISPATCH_DATA_REMAINS)
03363 return NULL;
03364
03365 CONNECTION_LOCK (connection);
03366 _dbus_connection_acquire_dispatch (connection);
03367 HAVE_LOCK_CHECK (connection);
03368
03369 message = _dbus_connection_pop_message_unlocked (connection);
03370
03371 _dbus_verbose ("Returning popped message %p\n", message);
03372
03373 _dbus_connection_release_dispatch (connection);
03374 CONNECTION_UNLOCK (connection);
03375
03376 return message;
03377 }
03378
03386 static void
03387 _dbus_connection_acquire_dispatch (DBusConnection *connection)
03388 {
03389 HAVE_LOCK_CHECK (connection);
03390
03391 _dbus_connection_ref_unlocked (connection);
03392 CONNECTION_UNLOCK (connection);
03393
03394 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03395 _dbus_mutex_lock (connection->dispatch_mutex);
03396
03397 while (connection->dispatch_acquired)
03398 {
03399 _dbus_verbose ("%s waiting for dispatch to be acquirable\n", _DBUS_FUNCTION_NAME);
03400 _dbus_condvar_wait (connection->dispatch_cond,
03401 connection->dispatch_mutex);
03402 }
03403
03404 _dbus_assert (!connection->dispatch_acquired);
03405
03406 connection->dispatch_acquired = TRUE;
03407
03408 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03409 _dbus_mutex_unlock (connection->dispatch_mutex);
03410
03411 CONNECTION_LOCK (connection);
03412 _dbus_connection_unref_unlocked (connection);
03413 }
03414
03422 static void
03423 _dbus_connection_release_dispatch (DBusConnection *connection)
03424 {
03425 HAVE_LOCK_CHECK (connection);
03426
03427 _dbus_verbose ("%s locking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03428 _dbus_mutex_lock (connection->dispatch_mutex);
03429
03430 _dbus_assert (connection->dispatch_acquired);
03431
03432 connection->dispatch_acquired = FALSE;
03433 _dbus_condvar_wake_one (connection->dispatch_cond);
03434
03435 _dbus_verbose ("%s unlocking dispatch_mutex\n", _DBUS_FUNCTION_NAME);
03436 _dbus_mutex_unlock (connection->dispatch_mutex);
03437 }
03438
03439 static void
03440 _dbus_connection_failed_pop (DBusConnection *connection,
03441 DBusList *message_link)
03442 {
03443 _dbus_list_prepend_link (&connection->incoming_messages,
03444 message_link);
03445 connection->n_incoming += 1;
03446 }
03447
03448 static DBusDispatchStatus
03449 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
03450 {
03451 HAVE_LOCK_CHECK (connection);
03452
03453 if (connection->n_incoming > 0)
03454 return DBUS_DISPATCH_DATA_REMAINS;
03455 else if (!_dbus_transport_queue_messages (connection->transport))
03456 return DBUS_DISPATCH_NEED_MEMORY;
03457 else
03458 {
03459 DBusDispatchStatus status;
03460 dbus_bool_t is_connected;
03461
03462 status = _dbus_transport_get_dispatch_status (connection->transport);
03463 is_connected = _dbus_transport_get_is_connected (connection->transport);
03464
03465 _dbus_verbose ("dispatch status = %s is_connected = %d\n",
03466 DISPATCH_STATUS_NAME (status), is_connected);
03467
03468 if (!is_connected)
03469 {
03470 if (status == DBUS_DISPATCH_COMPLETE &&
03471 connection->disconnect_message_link)
03472 {
03473 _dbus_verbose ("Sending disconnect message from %s\n",
03474 _DBUS_FUNCTION_NAME);
03475
03476 connection_forget_shared_unlocked (connection);
03477
03478
03479 connection_timeout_and_complete_all_pending_calls_unlocked (connection);
03480
03481
03482
03483
03484 _dbus_connection_queue_synthesized_message_link (connection,
03485 connection->disconnect_message_link);
03486 connection->disconnect_message_link = NULL;
03487
03488 status = DBUS_DISPATCH_DATA_REMAINS;
03489 }
03490
03491
03492
03493
03494
03495 if (connection->n_outgoing > 0)
03496 {
03497 DBusList *link;
03498
03499 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
03500 connection->n_outgoing);
03501
03502 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
03503 {
03504 _dbus_connection_message_sent (connection, link->data);
03505 }
03506 }
03507 }
03508
03509 if (status != DBUS_DISPATCH_COMPLETE)
03510 return status;
03511 else if (connection->n_incoming > 0)
03512 return DBUS_DISPATCH_DATA_REMAINS;
03513 else
03514 return DBUS_DISPATCH_COMPLETE;
03515 }
03516 }
03517
03518 static void
03519 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
03520 DBusDispatchStatus new_status)
03521 {
03522 dbus_bool_t changed;
03523 DBusDispatchStatusFunction function;
03524 void *data;
03525
03526 HAVE_LOCK_CHECK (connection);
03527
03528 _dbus_connection_ref_unlocked (connection);
03529
03530 changed = new_status != connection->last_dispatch_status;
03531
03532 connection->last_dispatch_status = new_status;
03533
03534 function = connection->dispatch_status_function;
03535 data = connection->dispatch_status_data;
03536
03537
03538 CONNECTION_UNLOCK (connection);
03539
03540 if (changed && function)
03541 {
03542 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
03543 connection, new_status,
03544 DISPATCH_STATUS_NAME (new_status));
03545 (* function) (connection, new_status, data);
03546 }
03547
03548 dbus_connection_unref (connection);
03549 }
03550
03559 DBusDispatchStatus
03560 dbus_connection_get_dispatch_status (DBusConnection *connection)
03561 {
03562 DBusDispatchStatus status;
03563
03564 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
03565
03566 _dbus_verbose ("%s start\n", _DBUS_FUNCTION_NAME);
03567
03568 CONNECTION_LOCK (connection);
03569
03570 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03571
03572 CONNECTION_UNLOCK (connection);
03573
03574 return status;
03575 }
03576
03580 static DBusHandlerResult
03581 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
03582 DBusMessage *message)
03583 {
03584 if (dbus_message_is_method_call (message,
03585 DBUS_INTERFACE_PEER,
03586 "Ping"))
03587 {
03588 DBusMessage *ret;
03589 dbus_bool_t sent;
03590
03591 ret = dbus_message_new_method_return (message);
03592 if (ret == NULL)
03593 return DBUS_HANDLER_RESULT_NEED_MEMORY;
03594
03595 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
03596
03597 dbus_message_unref (ret);
03598
03599 if (!sent)
03600 return DBUS_HANDLER_RESULT_NEED_MEMORY;
03601
03602 return DBUS_HANDLER_RESULT_HANDLED;
03603 }
03604
03605
03606 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03607 }
03608
03615 static DBusHandlerResult
03616 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
03617 DBusMessage *message)
03618 {
03619
03620
03621
03622 return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
03623 }
03624
03648 DBusDispatchStatus
03649 dbus_connection_dispatch (DBusConnection *connection)
03650 {
03651 DBusMessage *message;
03652 DBusList *link, *filter_list_copy, *message_link;
03653 DBusHandlerResult result;
03654 DBusPendingCall *pending;
03655 dbus_int32_t reply_serial;
03656 DBusDispatchStatus status;
03657
03658 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
03659
03660 _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME);
03661
03662 CONNECTION_LOCK (connection);
03663 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03664 if (status != DBUS_DISPATCH_DATA_REMAINS)
03665 {
03666
03667 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03668 return status;
03669 }
03670
03671
03672
03673
03674 _dbus_connection_ref_unlocked (connection);
03675
03676 _dbus_connection_acquire_dispatch (connection);
03677 HAVE_LOCK_CHECK (connection);
03678
03679 message_link = _dbus_connection_pop_message_link_unlocked (connection);
03680 if (message_link == NULL)
03681 {
03682
03683
03684 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
03685
03686 _dbus_connection_release_dispatch (connection);
03687
03688 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03689
03690 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03691
03692 dbus_connection_unref (connection);
03693
03694 return status;
03695 }
03696
03697 message = message_link->data;
03698
03699 _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n",
03700 message,
03701 dbus_message_get_type (message),
03702 dbus_message_get_interface (message) ?
03703 dbus_message_get_interface (message) :
03704 "no interface",
03705 dbus_message_get_member (message) ?
03706 dbus_message_get_member (message) :
03707 "no member",
03708 dbus_message_get_signature (message));
03709
03710 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
03711
03712
03713
03714
03715
03716
03717
03718
03719 reply_serial = dbus_message_get_reply_serial (message);
03720 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
03721 reply_serial);
03722 if (pending)
03723 {
03724 _dbus_verbose ("Dispatching a pending reply\n");
03725 complete_pending_call_and_unlock (connection, pending, message);
03726 pending = NULL;
03727
03728 CONNECTION_LOCK (connection);
03729 _dbus_verbose ("pending call completed in dispatch\n");
03730 result = DBUS_HANDLER_RESULT_HANDLED;
03731 goto out;
03732 }
03733
03734 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
03735 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03736 goto out;
03737
03738 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
03739 {
03740 _dbus_connection_release_dispatch (connection);
03741 HAVE_LOCK_CHECK (connection);
03742
03743 _dbus_connection_failed_pop (connection, message_link);
03744
03745
03746 _dbus_connection_update_dispatch_status_and_unlock (connection,
03747 DBUS_DISPATCH_NEED_MEMORY);
03748
03749 if (pending)
03750 dbus_pending_call_unref (pending);
03751 dbus_connection_unref (connection);
03752
03753 return DBUS_DISPATCH_NEED_MEMORY;
03754 }
03755
03756 _dbus_list_foreach (&filter_list_copy,
03757 (DBusForeachFunction)_dbus_message_filter_ref,
03758 NULL);
03759
03760
03761
03762
03763 CONNECTION_UNLOCK (connection);
03764
03765 link = _dbus_list_get_first_link (&filter_list_copy);
03766 while (link != NULL)
03767 {
03768 DBusMessageFilter *filter = link->data;
03769 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
03770
03771 if (filter->function == NULL)
03772 {
03773 _dbus_verbose (" filter was removed in a callback function\n");
03774 link = next;
03775 continue;
03776 }
03777
03778 _dbus_verbose (" running filter on message %p\n", message);
03779 result = (* filter->function) (connection, message, filter->user_data);
03780
03781 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03782 break;
03783
03784 link = next;
03785 }
03786
03787 _dbus_list_foreach (&filter_list_copy,
03788 (DBusForeachFunction)_dbus_message_filter_unref,
03789 NULL);
03790 _dbus_list_clear (&filter_list_copy);
03791
03792 CONNECTION_LOCK (connection);
03793
03794 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
03795 {
03796 _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME);
03797 goto out;
03798 }
03799 else if (result == DBUS_HANDLER_RESULT_HANDLED)
03800 {
03801 _dbus_verbose ("filter handled message in dispatch\n");
03802 goto out;
03803 }
03804
03805
03806
03807
03808 _dbus_verbose (" running object path dispatch on message %p (%d %s %s '%s')\n",
03809 message,
03810 dbus_message_get_type (message),
03811 dbus_message_get_interface (message) ?
03812 dbus_message_get_interface (message) :
03813 "no interface",
03814 dbus_message_get_member (message) ?
03815 dbus_message_get_member (message) :
03816 "no member",
03817 dbus_message_get_signature (message));
03818
03819 HAVE_LOCK_CHECK (connection);
03820 result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
03821 message);
03822
03823 CONNECTION_LOCK (connection);
03824
03825 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
03826 {
03827 _dbus_verbose ("object tree handled message in dispatch\n");
03828 goto out;
03829 }
03830
03831 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
03832 {
03833 DBusMessage *reply;
03834 DBusString str;
03835 DBusPreallocatedSend *preallocated;
03836
03837 _dbus_verbose (" sending error %s\n",
03838 DBUS_ERROR_UNKNOWN_METHOD);
03839
03840 if (!_dbus_string_init (&str))
03841 {
03842 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03843 _dbus_verbose ("no memory for error string in dispatch\n");
03844 goto out;
03845 }
03846
03847 if (!_dbus_string_append_printf (&str,
03848 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
03849 dbus_message_get_member (message),
03850 dbus_message_get_signature (message),
03851 dbus_message_get_interface (message)))
03852 {
03853 _dbus_string_free (&str);
03854 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03855 _dbus_verbose ("no memory for error string in dispatch\n");
03856 goto out;
03857 }
03858
03859 reply = dbus_message_new_error (message,
03860 DBUS_ERROR_UNKNOWN_METHOD,
03861 _dbus_string_get_const_data (&str));
03862 _dbus_string_free (&str);
03863
03864 if (reply == NULL)
03865 {
03866 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03867 _dbus_verbose ("no memory for error reply in dispatch\n");
03868 goto out;
03869 }
03870
03871 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03872
03873 if (preallocated == NULL)
03874 {
03875 dbus_message_unref (reply);
03876 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
03877 _dbus_verbose ("no memory for error send in dispatch\n");
03878 goto out;
03879 }
03880
03881 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
03882 reply, NULL);
03883
03884 dbus_message_unref (reply);
03885
03886 result = DBUS_HANDLER_RESULT_HANDLED;
03887 }
03888
03889 _dbus_verbose (" done dispatching %p (%d %s %s '%s') on connection %p\n", message,
03890 dbus_message_get_type (message),
03891 dbus_message_get_interface (message) ?
03892 dbus_message_get_interface (message) :
03893 "no interface",
03894 dbus_message_get_member (message) ?
03895 dbus_message_get_member (message) :
03896 "no member",
03897 dbus_message_get_signature (message),
03898 connection);
03899
03900 out:
03901 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
03902 {
03903 _dbus_verbose ("out of memory in %s\n", _DBUS_FUNCTION_NAME);
03904
03905
03906
03907
03908
03909 _dbus_connection_putback_message_link_unlocked (connection,
03910 message_link);
03911 }
03912 else
03913 {
03914 _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME);
03915
03916 if (dbus_message_is_signal (message,
03917 DBUS_INTERFACE_LOCAL,
03918 "Disconnected"))
03919 {
03920 _dbus_bus_check_connection_and_unref_unlocked (connection);
03921
03922 if (connection->exit_on_disconnect)
03923 {
03924 CONNECTION_UNLOCK (connection);
03925
03926 _dbus_verbose ("Exiting on Disconnected signal\n");
03927 _dbus_exit (1);
03928 _dbus_assert_not_reached ("Call to exit() returned");
03929 }
03930 }
03931
03932 _dbus_list_free_link (message_link);
03933 dbus_message_unref (message);
03934
03935
03936 }
03937
03938 _dbus_connection_release_dispatch (connection);
03939 HAVE_LOCK_CHECK (connection);
03940
03941 _dbus_verbose ("%s before final status update\n", _DBUS_FUNCTION_NAME);
03942 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03943
03944
03945 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03946
03947 dbus_connection_unref (connection);
03948
03949 return status;
03950 }
03951
04010 dbus_bool_t
04011 dbus_connection_set_watch_functions (DBusConnection *connection,
04012 DBusAddWatchFunction add_function,
04013 DBusRemoveWatchFunction remove_function,
04014 DBusWatchToggledFunction toggled_function,
04015 void *data,
04016 DBusFreeFunction free_data_function)
04017 {
04018 dbus_bool_t retval;
04019 DBusWatchList *watches;
04020
04021 _dbus_return_val_if_fail (connection != NULL, FALSE);
04022
04023 CONNECTION_LOCK (connection);
04024
04025 #ifndef DBUS_DISABLE_CHECKS
04026 if (connection->watches == NULL)
04027 {
04028 _dbus_warn ("Re-entrant call to %s is not allowed\n",
04029 _DBUS_FUNCTION_NAME);
04030 return FALSE;
04031 }
04032 #endif
04033
04034
04035 _dbus_connection_ref_unlocked (connection);
04036
04037
04038
04039
04040
04041 watches = connection->watches;
04042 connection->watches = NULL;
04043 CONNECTION_UNLOCK (connection);
04044
04045 retval = _dbus_watch_list_set_functions (watches,
04046 add_function, remove_function,
04047 toggled_function,
04048 data, free_data_function);
04049 CONNECTION_LOCK (connection);
04050 connection->watches = watches;
04051
04052 CONNECTION_UNLOCK (connection);
04053
04054 dbus_connection_unref (connection);
04055
04056 return retval;
04057 }
04058
04092 dbus_bool_t
04093 dbus_connection_set_timeout_functions (DBusConnection *connection,
04094 DBusAddTimeoutFunction add_function,
04095 DBusRemoveTimeoutFunction remove_function,
04096 DBusTimeoutToggledFunction toggled_function,
04097 void *data,
04098 DBusFreeFunction free_data_function)
04099 {
04100 dbus_bool_t retval;
04101 DBusTimeoutList *timeouts;
04102
04103 _dbus_return_val_if_fail (connection != NULL, FALSE);
04104
04105 CONNECTION_LOCK (connection);
04106
04107 #ifndef DBUS_DISABLE_CHECKS
04108 if (connection->timeouts == NULL)
04109 {
04110 _dbus_warn ("Re-entrant call to %s is not allowed\n",
04111 _DBUS_FUNCTION_NAME);
04112 return FALSE;
04113 }
04114 #endif
04115
04116
04117 _dbus_connection_ref_unlocked (connection);
04118
04119 timeouts = connection->timeouts;
04120 connection->timeouts = NULL;
04121 CONNECTION_UNLOCK (connection);
04122
04123 retval = _dbus_timeout_list_set_functions (timeouts,
04124 add_function, remove_function,
04125 toggled_function,
04126 data, free_data_function);
04127 CONNECTION_LOCK (connection);
04128 connection->timeouts = timeouts;
04129
04130 CONNECTION_UNLOCK (connection);
04131
04132 dbus_connection_unref (connection);
04133
04134 return retval;
04135 }
04136
04151 void
04152 dbus_connection_set_wakeup_main_function (DBusConnection *connection,
04153 DBusWakeupMainFunction wakeup_main_function,
04154 void *data,
04155 DBusFreeFunction free_data_function)
04156 {
04157 void *old_data;
04158 DBusFreeFunction old_free_data;
04159
04160 _dbus_return_if_fail (connection != NULL);
04161
04162 CONNECTION_LOCK (connection);
04163 old_data = connection->wakeup_main_data;
04164 old_free_data = connection->free_wakeup_main_data;
04165
04166 connection->wakeup_main_function = wakeup_main_function;
04167 connection->wakeup_main_data = data;
04168 connection->free_wakeup_main_data = free_data_function;
04169
04170 CONNECTION_UNLOCK (connection);
04171
04172
04173 if (old_free_data)
04174 (*old_free_data) (old_data);
04175 }
04176
04193 void
04194 dbus_connection_set_dispatch_status_function (DBusConnection *connection,
04195 DBusDispatchStatusFunction function,
04196 void *data,
04197 DBusFreeFunction free_data_function)
04198 {
04199 void *old_data;
04200 DBusFreeFunction old_free_data;
04201
04202 _dbus_return_if_fail (connection != NULL);
04203
04204 CONNECTION_LOCK (connection);
04205 old_data = connection->dispatch_status_data;
04206 old_free_data = connection->free_dispatch_status_data;
04207
04208 connection->dispatch_status_function = function;
04209 connection->dispatch_status_data = data;
04210 connection->free_dispatch_status_data = free_data_function;
04211
04212 CONNECTION_UNLOCK (connection);
04213
04214
04215 if (old_free_data)
04216 (*old_free_data) (old_data);
04217 }
04218
04231 dbus_bool_t
04232 dbus_connection_get_unix_fd (DBusConnection *connection,
04233 int *fd)
04234 {
04235 dbus_bool_t retval;
04236
04237 _dbus_return_val_if_fail (connection != NULL, FALSE);
04238 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
04239
04240 CONNECTION_LOCK (connection);
04241
04242 retval = _dbus_transport_get_unix_fd (connection->transport,
04243 fd);
04244
04245 CONNECTION_UNLOCK (connection);
04246
04247 return retval;
04248 }
04249
04261 dbus_bool_t
04262 dbus_connection_get_unix_user (DBusConnection *connection,
04263 unsigned long *uid)
04264 {
04265 dbus_bool_t result;
04266
04267 _dbus_return_val_if_fail (connection != NULL, FALSE);
04268 _dbus_return_val_if_fail (uid != NULL, FALSE);
04269
04270 CONNECTION_LOCK (connection);
04271
04272 if (!_dbus_transport_get_is_authenticated (connection->transport))
04273 result = FALSE;
04274 else
04275 result = _dbus_transport_get_unix_user (connection->transport,
04276 uid);
04277 CONNECTION_UNLOCK (connection);
04278
04279 return result;
04280 }
04281
04292 dbus_bool_t
04293 dbus_connection_get_unix_process_id (DBusConnection *connection,
04294 unsigned long *pid)
04295 {
04296 dbus_bool_t result;
04297
04298 _dbus_return_val_if_fail (connection != NULL, FALSE);
04299 _dbus_return_val_if_fail (pid != NULL, FALSE);
04300
04301 CONNECTION_LOCK (connection);
04302
04303 if (!_dbus_transport_get_is_authenticated (connection->transport))
04304 result = FALSE;
04305 else
04306 result = _dbus_transport_get_unix_process_id (connection->transport,
04307 pid);
04308 CONNECTION_UNLOCK (connection);
04309
04310 return result;
04311 }
04312
04329 void
04330 dbus_connection_set_unix_user_function (DBusConnection *connection,
04331 DBusAllowUnixUserFunction function,
04332 void *data,
04333 DBusFreeFunction free_data_function)
04334 {
04335 void *old_data = NULL;
04336 DBusFreeFunction old_free_function = NULL;
04337
04338 _dbus_return_if_fail (connection != NULL);
04339
04340 CONNECTION_LOCK (connection);
04341 _dbus_transport_set_unix_user_function (connection->transport,
04342 function, data, free_data_function,
04343 &old_data, &old_free_function);
04344 CONNECTION_UNLOCK (connection);
04345
04346 if (old_free_function != NULL)
04347 (* old_free_function) (old_data);
04348 }
04349
04371 dbus_bool_t
04372 dbus_connection_add_filter (DBusConnection *connection,
04373 DBusHandleMessageFunction function,
04374 void *user_data,
04375 DBusFreeFunction free_data_function)
04376 {
04377 DBusMessageFilter *filter;
04378
04379 _dbus_return_val_if_fail (connection != NULL, FALSE);
04380 _dbus_return_val_if_fail (function != NULL, FALSE);
04381
04382 filter = dbus_new0 (DBusMessageFilter, 1);
04383 if (filter == NULL)
04384 return FALSE;
04385
04386 filter->refcount.value = 1;
04387
04388 CONNECTION_LOCK (connection);
04389
04390 if (!_dbus_list_append (&connection->filter_list,
04391 filter))
04392 {
04393 _dbus_message_filter_unref (filter);
04394 CONNECTION_UNLOCK (connection);
04395 return FALSE;
04396 }
04397
04398
04399
04400
04401
04402
04403 filter->function = function;
04404 filter->user_data = user_data;
04405 filter->free_user_data_function = free_data_function;
04406
04407 CONNECTION_UNLOCK (connection);
04408 return TRUE;
04409 }
04410
04423 void
04424 dbus_connection_remove_filter (DBusConnection *connection,
04425 DBusHandleMessageFunction function,
04426 void *user_data)
04427 {
04428 DBusList *link;
04429 DBusMessageFilter *filter;
04430
04431 _dbus_return_if_fail (connection != NULL);
04432 _dbus_return_if_fail (function != NULL);
04433
04434 CONNECTION_LOCK (connection);
04435
04436 filter = NULL;
04437
04438 link = _dbus_list_get_last_link (&connection->filter_list);
04439 while (link != NULL)
04440 {
04441 filter = link->data;
04442
04443 if (filter->function == function &&
04444 filter->user_data == user_data)
04445 {
04446 _dbus_list_remove_link (&connection->filter_list, link);
04447 filter->function = NULL;
04448
04449 break;
04450 }
04451
04452 link = _dbus_list_get_prev_link (&connection->filter_list, link);
04453 }
04454
04455 CONNECTION_UNLOCK (connection);
04456
04457 #ifndef DBUS_DISABLE_CHECKS
04458 if (filter == NULL)
04459 {
04460 _dbus_warn ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
04461 function, user_data);
04462 return;
04463 }
04464 #endif
04465
04466
04467 if (filter->free_user_data_function)
04468 (* filter->free_user_data_function) (filter->user_data);
04469
04470 filter->free_user_data_function = NULL;
04471 filter->user_data = NULL;
04472
04473 _dbus_message_filter_unref (filter);
04474 }
04475
04487 dbus_bool_t
04488 dbus_connection_register_object_path (DBusConnection *connection,
04489 const char *path,
04490 const DBusObjectPathVTable *vtable,
04491 void *user_data)
04492 {
04493 char **decomposed_path;
04494 dbus_bool_t retval;
04495
04496 _dbus_return_val_if_fail (connection != NULL, FALSE);
04497 _dbus_return_val_if_fail (path != NULL, FALSE);
04498 _dbus_return_val_if_fail (path[0] == '/', FALSE);
04499 _dbus_return_val_if_fail (vtable != NULL, FALSE);
04500
04501 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04502 return FALSE;
04503
04504 CONNECTION_LOCK (connection);
04505
04506 retval = _dbus_object_tree_register (connection->objects,
04507 FALSE,
04508 (const char **) decomposed_path, vtable,
04509 user_data);
04510
04511 CONNECTION_UNLOCK (connection);
04512
04513 dbus_free_string_array (decomposed_path);
04514
04515 return retval;
04516 }
04517
04530 dbus_bool_t
04531 dbus_connection_register_fallback (DBusConnection *connection,
04532 const char *path,
04533 const DBusObjectPathVTable *vtable,
04534 void *user_data)
04535 {
04536 char **decomposed_path;
04537 dbus_bool_t retval;
04538
04539 _dbus_return_val_if_fail (connection != NULL, FALSE);
04540 _dbus_return_val_if_fail (path != NULL, FALSE);
04541 _dbus_return_val_if_fail (path[0] == '/', FALSE);
04542 _dbus_return_val_if_fail (vtable != NULL, FALSE);
04543
04544 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04545 return FALSE;
04546
04547 CONNECTION_LOCK (connection);
04548
04549 retval = _dbus_object_tree_register (connection->objects,
04550 TRUE,
04551 (const char **) decomposed_path, vtable,
04552 user_data);
04553
04554 CONNECTION_UNLOCK (connection);
04555
04556 dbus_free_string_array (decomposed_path);
04557
04558 return retval;
04559 }
04560
04570 dbus_bool_t
04571 dbus_connection_unregister_object_path (DBusConnection *connection,
04572 const char *path)
04573 {
04574 char **decomposed_path;
04575
04576 _dbus_return_val_if_fail (connection != NULL, FALSE);
04577 _dbus_return_val_if_fail (path != NULL, FALSE);
04578 _dbus_return_val_if_fail (path[0] == '/', FALSE);
04579
04580 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04581 return FALSE;
04582
04583 CONNECTION_LOCK (connection);
04584
04585 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
04586
04587 dbus_free_string_array (decomposed_path);
04588
04589 return TRUE;
04590 }
04591
04602 dbus_bool_t
04603 dbus_connection_get_object_path_data (DBusConnection *connection,
04604 const char *path,
04605 void **data_p)
04606 {
04607 char **decomposed_path;
04608
04609 _dbus_return_val_if_fail (connection != NULL, FALSE);
04610 _dbus_return_val_if_fail (path != NULL, FALSE);
04611 _dbus_return_val_if_fail (data_p != NULL, FALSE);
04612
04613 *data_p = NULL;
04614
04615 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
04616 return FALSE;
04617
04618 CONNECTION_LOCK (connection);
04619
04620 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
04621
04622 CONNECTION_UNLOCK (connection);
04623
04624 dbus_free_string_array (decomposed_path);
04625
04626 return TRUE;
04627 }
04628
04639 dbus_bool_t
04640 dbus_connection_list_registered (DBusConnection *connection,
04641 const char *parent_path,
04642 char ***child_entries)
04643 {
04644 char **decomposed_path;
04645 dbus_bool_t retval;
04646 _dbus_return_val_if_fail (connection != NULL, FALSE);
04647 _dbus_return_val_if_fail (parent_path != NULL, FALSE);
04648 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
04649 _dbus_return_val_if_fail (child_entries != NULL, FALSE);
04650
04651 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
04652 return FALSE;
04653
04654 CONNECTION_LOCK (connection);
04655
04656 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
04657 (const char **) decomposed_path,
04658 child_entries);
04659 dbus_free_string_array (decomposed_path);
04660
04661 return retval;
04662 }
04663
04664 static DBusDataSlotAllocator slot_allocator;
04665 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
04666
04681 dbus_bool_t
04682 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
04683 {
04684 return _dbus_data_slot_allocator_alloc (&slot_allocator,
04685 &_DBUS_LOCK_NAME (connection_slots),
04686 slot_p);
04687 }
04688
04700 void
04701 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
04702 {
04703 _dbus_return_if_fail (*slot_p >= 0);
04704
04705 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
04706 }
04707
04721 dbus_bool_t
04722 dbus_connection_set_data (DBusConnection *connection,
04723 dbus_int32_t slot,
04724 void *data,
04725 DBusFreeFunction free_data_func)
04726 {
04727 DBusFreeFunction old_free_func;
04728 void *old_data;
04729 dbus_bool_t retval;
04730
04731 _dbus_return_val_if_fail (connection != NULL, FALSE);
04732 _dbus_return_val_if_fail (slot >= 0, FALSE);
04733
04734 CONNECTION_LOCK (connection);
04735
04736 retval = _dbus_data_slot_list_set (&slot_allocator,
04737 &connection->slot_list,
04738 slot, data, free_data_func,
04739 &old_free_func, &old_data);
04740
04741 CONNECTION_UNLOCK (connection);
04742
04743 if (retval)
04744 {
04745
04746 if (old_free_func)
04747 (* old_free_func) (old_data);
04748 }
04749
04750 return retval;
04751 }
04752
04761 void*
04762 dbus_connection_get_data (DBusConnection *connection,
04763 dbus_int32_t slot)
04764 {
04765 void *res;
04766
04767 _dbus_return_val_if_fail (connection != NULL, NULL);
04768
04769 CONNECTION_LOCK (connection);
04770
04771 res = _dbus_data_slot_list_get (&slot_allocator,
04772 &connection->slot_list,
04773 slot);
04774
04775 CONNECTION_UNLOCK (connection);
04776
04777 return res;
04778 }
04779
04786 void
04787 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
04788 {
04789 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
04790 }
04791
04800 void
04801 dbus_connection_set_max_message_size (DBusConnection *connection,
04802 long size)
04803 {
04804 _dbus_return_if_fail (connection != NULL);
04805
04806 CONNECTION_LOCK (connection);
04807 _dbus_transport_set_max_message_size (connection->transport,
04808 size);
04809 CONNECTION_UNLOCK (connection);
04810 }
04811
04818 long
04819 dbus_connection_get_max_message_size (DBusConnection *connection)
04820 {
04821 long res;
04822
04823 _dbus_return_val_if_fail (connection != NULL, 0);
04824
04825 CONNECTION_LOCK (connection);
04826 res = _dbus_transport_get_max_message_size (connection->transport);
04827 CONNECTION_UNLOCK (connection);
04828 return res;
04829 }
04830
04856 void
04857 dbus_connection_set_max_received_size (DBusConnection *connection,
04858 long size)
04859 {
04860 _dbus_return_if_fail (connection != NULL);
04861
04862 CONNECTION_LOCK (connection);
04863 _dbus_transport_set_max_received_size (connection->transport,
04864 size);
04865 CONNECTION_UNLOCK (connection);
04866 }
04867
04874 long
04875 dbus_connection_get_max_received_size (DBusConnection *connection)
04876 {
04877 long res;
04878
04879 _dbus_return_val_if_fail (connection != NULL, 0);
04880
04881 CONNECTION_LOCK (connection);
04882 res = _dbus_transport_get_max_received_size (connection->transport);
04883 CONNECTION_UNLOCK (connection);
04884 return res;
04885 }
04886
04897 long
04898 dbus_connection_get_outgoing_size (DBusConnection *connection)
04899 {
04900 long res;
04901
04902 _dbus_return_val_if_fail (connection != NULL, 0);
04903
04904 CONNECTION_LOCK (connection);
04905 res = _dbus_counter_get_value (connection->outgoing_counter);
04906 CONNECTION_UNLOCK (connection);
04907 return res;
04908 }
04909