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-message-private.h"
00037 #include "dbus-threads.h"
00038 #include "dbus-protocol.h"
00039 #include "dbus-dataslot.h"
00040 #include "dbus-string.h"
00041 #include "dbus-pending-call.h"
00042 #include "dbus-object-tree.h"
00043 #include "dbus-threads-internal.h"
00044 #include "dbus-bus.h"
00045 #include "dbus-marshal-basic.h"
00046
00047 #ifdef DBUS_DISABLE_CHECKS
00048 #define TOOK_LOCK_CHECK(connection)
00049 #define RELEASING_LOCK_CHECK(connection)
00050 #define HAVE_LOCK_CHECK(connection)
00051 #else
00052 #define TOOK_LOCK_CHECK(connection) do { \
00053 _dbus_assert (!(connection)->have_connection_lock); \
00054 (connection)->have_connection_lock = TRUE; \
00055 } while (0)
00056 #define RELEASING_LOCK_CHECK(connection) do { \
00057 _dbus_assert ((connection)->have_connection_lock); \
00058 (connection)->have_connection_lock = FALSE; \
00059 } while (0)
00060 #define HAVE_LOCK_CHECK(connection) _dbus_assert ((connection)->have_connection_lock)
00061
00062 #endif
00063
00064 #define TRACE_LOCKS 1
00065
00066 #define CONNECTION_LOCK(connection) do { \
00067 if (TRACE_LOCKS) { _dbus_verbose ("LOCK\n"); } \
00068 _dbus_mutex_lock ((connection)->mutex); \
00069 TOOK_LOCK_CHECK (connection); \
00070 } while (0)
00071
00072 #define CONNECTION_UNLOCK(connection) do { \
00073 if (TRACE_LOCKS) { _dbus_verbose ("UNLOCK\n"); } \
00074 RELEASING_LOCK_CHECK (connection); \
00075 _dbus_mutex_unlock ((connection)->mutex); \
00076 } while (0)
00077
00078 #define SLOTS_LOCK(connection) do { \
00079 _dbus_mutex_lock ((connection)->slot_mutex); \
00080 } while (0)
00081
00082 #define SLOTS_UNLOCK(connection) do { \
00083 _dbus_mutex_unlock ((connection)->slot_mutex); \
00084 } while (0)
00085
00086 #define DISPATCH_STATUS_NAME(s) \
00087 ((s) == DBUS_DISPATCH_COMPLETE ? "complete" : \
00088 (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
00089 (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" : \
00090 "???")
00091
00212 typedef struct DBusMessageFilter DBusMessageFilter;
00213
00217 struct DBusMessageFilter
00218 {
00219 DBusAtomic refcount;
00220 DBusHandleMessageFunction function;
00221 void *user_data;
00222 DBusFreeFunction free_user_data_function;
00223 };
00224
00225
00229 struct DBusPreallocatedSend
00230 {
00231 DBusConnection *connection;
00232 DBusList *queue_link;
00233 DBusList *counter_link;
00234 };
00235
00236 #ifdef HAVE_DECL_MSG_NOSIGNAL
00237 static dbus_bool_t _dbus_modify_sigpipe = FALSE;
00238 #else
00239 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
00240 #endif
00241
00245 struct DBusConnection
00246 {
00247 DBusAtomic refcount;
00249 DBusMutex *mutex;
00251 DBusMutex *dispatch_mutex;
00252 DBusCondVar *dispatch_cond;
00253 DBusMutex *io_path_mutex;
00254 DBusCondVar *io_path_cond;
00256 DBusList *outgoing_messages;
00257 DBusList *incoming_messages;
00259 DBusMessage *message_borrowed;
00263 int n_outgoing;
00264 int n_incoming;
00266 DBusCounter *outgoing_counter;
00268 DBusTransport *transport;
00269 DBusWatchList *watches;
00270 DBusTimeoutList *timeouts;
00272 DBusList *filter_list;
00274 DBusMutex *slot_mutex;
00275 DBusDataSlotList slot_list;
00277 DBusHashTable *pending_replies;
00279 dbus_uint32_t client_serial;
00280 DBusList *disconnect_message_link;
00282 DBusWakeupMainFunction wakeup_main_function;
00283 void *wakeup_main_data;
00284 DBusFreeFunction free_wakeup_main_data;
00286 DBusDispatchStatusFunction dispatch_status_function;
00287 void *dispatch_status_data;
00288 DBusFreeFunction free_dispatch_status_data;
00290 DBusDispatchStatus last_dispatch_status;
00292 DBusList *link_cache;
00295 DBusObjectTree *objects;
00297 char *server_guid;
00299
00300
00301
00302
00303 dbus_bool_t dispatch_acquired;
00304 dbus_bool_t io_path_acquired;
00306 unsigned int shareable : 1;
00308 unsigned int exit_on_disconnect : 1;
00310 unsigned int route_peer_messages : 1;
00312 unsigned int disconnected_message_arrived : 1;
00316 unsigned int disconnected_message_processed : 1;
00320 #ifndef DBUS_DISABLE_CHECKS
00321 unsigned int have_connection_lock : 1;
00322 #endif
00323
00324 #ifndef DBUS_DISABLE_CHECKS
00325 int generation;
00326 #endif
00327 };
00328
00329 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection);
00330 static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
00331 DBusDispatchStatus new_status);
00332 static void _dbus_connection_last_unref (DBusConnection *connection);
00333 static void _dbus_connection_acquire_dispatch (DBusConnection *connection);
00334 static void _dbus_connection_release_dispatch (DBusConnection *connection);
00335 static DBusDispatchStatus _dbus_connection_flush_unlocked (DBusConnection *connection);
00336 static void _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection);
00337 static dbus_bool_t _dbus_connection_get_is_connected_unlocked (DBusConnection *connection);
00338 static dbus_bool_t _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
00339 dbus_uint32_t client_serial);
00340
00341 static DBusMessageFilter *
00342 _dbus_message_filter_ref (DBusMessageFilter *filter)
00343 {
00344 _dbus_assert (filter->refcount.value > 0);
00345 _dbus_atomic_inc (&filter->refcount);
00346
00347 return filter;
00348 }
00349
00350 static void
00351 _dbus_message_filter_unref (DBusMessageFilter *filter)
00352 {
00353 _dbus_assert (filter->refcount.value > 0);
00354
00355 if (_dbus_atomic_dec (&filter->refcount) == 1)
00356 {
00357 if (filter->free_user_data_function)
00358 (* filter->free_user_data_function) (filter->user_data);
00359
00360 dbus_free (filter);
00361 }
00362 }
00363
00369 void
00370 _dbus_connection_lock (DBusConnection *connection)
00371 {
00372 CONNECTION_LOCK (connection);
00373 }
00374
00380 void
00381 _dbus_connection_unlock (DBusConnection *connection)
00382 {
00383 CONNECTION_UNLOCK (connection);
00384 }
00385
00393 static void
00394 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
00395 {
00396 if (connection->wakeup_main_function)
00397 (*connection->wakeup_main_function) (connection->wakeup_main_data);
00398 }
00399
00400 #ifdef DBUS_BUILD_TESTS
00401
00411 dbus_bool_t
00412 _dbus_connection_queue_received_message (DBusConnection *connection,
00413 DBusMessage *message)
00414 {
00415 DBusList *link;
00416
00417 link = _dbus_list_alloc_link (message);
00418 if (link == NULL)
00419 return FALSE;
00420
00421 dbus_message_ref (message);
00422 _dbus_connection_queue_received_message_link (connection, link);
00423
00424 return TRUE;
00425 }
00426
00439 void
00440 _dbus_connection_test_get_locks (DBusConnection *connection,
00441 DBusMutex **mutex_loc,
00442 DBusMutex **dispatch_mutex_loc,
00443 DBusMutex **io_path_mutex_loc,
00444 DBusCondVar **dispatch_cond_loc,
00445 DBusCondVar **io_path_cond_loc)
00446 {
00447 *mutex_loc = connection->mutex;
00448 *dispatch_mutex_loc = connection->dispatch_mutex;
00449 *io_path_mutex_loc = connection->io_path_mutex;
00450 *dispatch_cond_loc = connection->dispatch_cond;
00451 *io_path_cond_loc = connection->io_path_cond;
00452 }
00453 #endif
00454
00463 void
00464 _dbus_connection_queue_received_message_link (DBusConnection *connection,
00465 DBusList *link)
00466 {
00467 DBusPendingCall *pending;
00468 dbus_uint32_t reply_serial;
00469 DBusMessage *message;
00470
00471 _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
00472
00473 _dbus_list_append_link (&connection->incoming_messages,
00474 link);
00475 message = link->data;
00476
00477
00478 reply_serial = dbus_message_get_reply_serial (message);
00479 if (reply_serial != 0)
00480 {
00481 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
00482 reply_serial);
00483 if (pending != NULL)
00484 {
00485 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00486 _dbus_connection_remove_timeout_unlocked (connection,
00487 _dbus_pending_call_get_timeout_unlocked (pending));
00488
00489 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00490 }
00491 }
00492
00493
00494
00495 connection->n_incoming += 1;
00496
00497 _dbus_connection_wakeup_mainloop (connection);
00498
00499 _dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
00500 message,
00501 dbus_message_type_to_string (dbus_message_get_type (message)),
00502 dbus_message_get_path (message) ?
00503 dbus_message_get_path (message) :
00504 "no path",
00505 dbus_message_get_interface (message) ?
00506 dbus_message_get_interface (message) :
00507 "no interface",
00508 dbus_message_get_member (message) ?
00509 dbus_message_get_member (message) :
00510 "no member",
00511 dbus_message_get_signature (message),
00512 dbus_message_get_reply_serial (message),
00513 connection,
00514 connection->n_incoming);}
00515
00524 void
00525 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
00526 DBusList *link)
00527 {
00528 HAVE_LOCK_CHECK (connection);
00529
00530 _dbus_list_append_link (&connection->incoming_messages, link);
00531
00532 connection->n_incoming += 1;
00533
00534 _dbus_connection_wakeup_mainloop (connection);
00535
00536 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
00537 link->data, connection, connection->n_incoming);
00538 }
00539
00540
00548 dbus_bool_t
00549 _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection)
00550 {
00551 HAVE_LOCK_CHECK (connection);
00552 return connection->outgoing_messages != NULL;
00553 }
00554
00564 dbus_bool_t
00565 dbus_connection_has_messages_to_send (DBusConnection *connection)
00566 {
00567 dbus_bool_t v;
00568
00569 _dbus_return_val_if_fail (connection != NULL, FALSE);
00570
00571 CONNECTION_LOCK (connection);
00572 v = _dbus_connection_has_messages_to_send_unlocked (connection);
00573 CONNECTION_UNLOCK (connection);
00574
00575 return v;
00576 }
00577
00585 DBusMessage*
00586 _dbus_connection_get_message_to_send (DBusConnection *connection)
00587 {
00588 HAVE_LOCK_CHECK (connection);
00589
00590 return _dbus_list_get_last (&connection->outgoing_messages);
00591 }
00592
00601 void
00602 _dbus_connection_message_sent (DBusConnection *connection,
00603 DBusMessage *message)
00604 {
00605 DBusList *link;
00606
00607 HAVE_LOCK_CHECK (connection);
00608
00609
00610
00611
00612
00613
00614 link = _dbus_list_get_last_link (&connection->outgoing_messages);
00615 _dbus_assert (link != NULL);
00616 _dbus_assert (link->data == message);
00617
00618
00619 _dbus_list_unlink (&connection->outgoing_messages,
00620 link);
00621 _dbus_list_prepend_link (&connection->link_cache, link);
00622
00623 connection->n_outgoing -= 1;
00624
00625 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
00626 message,
00627 dbus_message_type_to_string (dbus_message_get_type (message)),
00628 dbus_message_get_path (message) ?
00629 dbus_message_get_path (message) :
00630 "no path",
00631 dbus_message_get_interface (message) ?
00632 dbus_message_get_interface (message) :
00633 "no interface",
00634 dbus_message_get_member (message) ?
00635 dbus_message_get_member (message) :
00636 "no member",
00637 dbus_message_get_signature (message),
00638 connection, connection->n_outgoing);
00639
00640
00641 _dbus_message_remove_counter (message, connection->outgoing_counter,
00642 &link);
00643 _dbus_list_prepend_link (&connection->link_cache, link);
00644
00645 dbus_message_unref (message);
00646 }
00647
00649 typedef dbus_bool_t (* DBusWatchAddFunction) (DBusWatchList *list,
00650 DBusWatch *watch);
00652 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list,
00653 DBusWatch *watch);
00655 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list,
00656 DBusWatch *watch,
00657 dbus_bool_t enabled);
00658
00659 static dbus_bool_t
00660 protected_change_watch (DBusConnection *connection,
00661 DBusWatch *watch,
00662 DBusWatchAddFunction add_function,
00663 DBusWatchRemoveFunction remove_function,
00664 DBusWatchToggleFunction toggle_function,
00665 dbus_bool_t enabled)
00666 {
00667 dbus_bool_t retval;
00668
00669 HAVE_LOCK_CHECK (connection);
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689 if (connection->watches)
00690 {
00691 if (add_function)
00692 retval = (* add_function) (connection->watches, watch);
00693 else if (remove_function)
00694 {
00695 retval = TRUE;
00696 (* remove_function) (connection->watches, watch);
00697 }
00698 else
00699 {
00700 retval = TRUE;
00701 (* toggle_function) (connection->watches, watch, enabled);
00702 }
00703 return retval;
00704 }
00705 else
00706 return FALSE;
00707 }
00708
00709
00721 dbus_bool_t
00722 _dbus_connection_add_watch_unlocked (DBusConnection *connection,
00723 DBusWatch *watch)
00724 {
00725 return protected_change_watch (connection, watch,
00726 _dbus_watch_list_add_watch,
00727 NULL, NULL, FALSE);
00728 }
00729
00739 void
00740 _dbus_connection_remove_watch_unlocked (DBusConnection *connection,
00741 DBusWatch *watch)
00742 {
00743 protected_change_watch (connection, watch,
00744 NULL,
00745 _dbus_watch_list_remove_watch,
00746 NULL, FALSE);
00747 }
00748
00759 void
00760 _dbus_connection_toggle_watch_unlocked (DBusConnection *connection,
00761 DBusWatch *watch,
00762 dbus_bool_t enabled)
00763 {
00764 _dbus_assert (watch != NULL);
00765
00766 protected_change_watch (connection, watch,
00767 NULL, NULL,
00768 _dbus_watch_list_toggle_watch,
00769 enabled);
00770 }
00771
00773 typedef dbus_bool_t (* DBusTimeoutAddFunction) (DBusTimeoutList *list,
00774 DBusTimeout *timeout);
00776 typedef void (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
00777 DBusTimeout *timeout);
00779 typedef void (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
00780 DBusTimeout *timeout,
00781 dbus_bool_t enabled);
00782
00783 static dbus_bool_t
00784 protected_change_timeout (DBusConnection *connection,
00785 DBusTimeout *timeout,
00786 DBusTimeoutAddFunction add_function,
00787 DBusTimeoutRemoveFunction remove_function,
00788 DBusTimeoutToggleFunction toggle_function,
00789 dbus_bool_t enabled)
00790 {
00791 dbus_bool_t retval;
00792
00793 HAVE_LOCK_CHECK (connection);
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813 if (connection->timeouts)
00814 {
00815 if (add_function)
00816 retval = (* add_function) (connection->timeouts, timeout);
00817 else if (remove_function)
00818 {
00819 retval = TRUE;
00820 (* remove_function) (connection->timeouts, timeout);
00821 }
00822 else
00823 {
00824 retval = TRUE;
00825 (* toggle_function) (connection->timeouts, timeout, enabled);
00826 }
00827 return retval;
00828 }
00829 else
00830 return FALSE;
00831 }
00832
00845 dbus_bool_t
00846 _dbus_connection_add_timeout_unlocked (DBusConnection *connection,
00847 DBusTimeout *timeout)
00848 {
00849 return protected_change_timeout (connection, timeout,
00850 _dbus_timeout_list_add_timeout,
00851 NULL, NULL, FALSE);
00852 }
00853
00863 void
00864 _dbus_connection_remove_timeout_unlocked (DBusConnection *connection,
00865 DBusTimeout *timeout)
00866 {
00867 protected_change_timeout (connection, timeout,
00868 NULL,
00869 _dbus_timeout_list_remove_timeout,
00870 NULL, FALSE);
00871 }
00872
00883 void
00884 _dbus_connection_toggle_timeout_unlocked (DBusConnection *connection,
00885 DBusTimeout *timeout,
00886 dbus_bool_t enabled)
00887 {
00888 protected_change_timeout (connection, timeout,
00889 NULL, NULL,
00890 _dbus_timeout_list_toggle_timeout,
00891 enabled);
00892 }
00893
00894 static dbus_bool_t
00895 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection,
00896 DBusPendingCall *pending)
00897 {
00898 dbus_uint32_t reply_serial;
00899 DBusTimeout *timeout;
00900
00901 HAVE_LOCK_CHECK (connection);
00902
00903 reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
00904
00905 _dbus_assert (reply_serial != 0);
00906
00907 timeout = _dbus_pending_call_get_timeout_unlocked (pending);
00908
00909 if (timeout)
00910 {
00911 if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
00912 return FALSE;
00913
00914 if (!_dbus_hash_table_insert_int (connection->pending_replies,
00915 reply_serial,
00916 pending))
00917 {
00918 _dbus_connection_remove_timeout_unlocked (connection, timeout);
00919
00920 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00921 HAVE_LOCK_CHECK (connection);
00922 return FALSE;
00923 }
00924
00925 _dbus_pending_call_set_timeout_added_unlocked (pending, TRUE);
00926 }
00927 else
00928 {
00929 if (!_dbus_hash_table_insert_int (connection->pending_replies,
00930 reply_serial,
00931 pending))
00932 {
00933 HAVE_LOCK_CHECK (connection);
00934 return FALSE;
00935 }
00936 }
00937
00938 _dbus_pending_call_ref_unlocked (pending);
00939
00940 HAVE_LOCK_CHECK (connection);
00941
00942 return TRUE;
00943 }
00944
00945 static void
00946 free_pending_call_on_hash_removal (void *data)
00947 {
00948 DBusPendingCall *pending;
00949 DBusConnection *connection;
00950
00951 if (data == NULL)
00952 return;
00953
00954 pending = data;
00955
00956 connection = _dbus_pending_call_get_connection_unlocked (pending);
00957
00958 HAVE_LOCK_CHECK (connection);
00959
00960 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
00961 {
00962 _dbus_connection_remove_timeout_unlocked (connection,
00963 _dbus_pending_call_get_timeout_unlocked (pending));
00964
00965 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
00966 }
00967
00968
00969
00970
00971
00972
00973 _dbus_connection_ref_unlocked (connection);
00974 _dbus_pending_call_unref_and_unlock (pending);
00975 CONNECTION_LOCK (connection);
00976 _dbus_connection_unref_unlocked (connection);
00977 }
00978
00979 static void
00980 _dbus_connection_detach_pending_call_unlocked (DBusConnection *connection,
00981 DBusPendingCall *pending)
00982 {
00983
00984
00985
00986 _dbus_hash_table_remove_int (connection->pending_replies,
00987 _dbus_pending_call_get_reply_serial_unlocked (pending));
00988 }
00989
00990 static void
00991 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection,
00992 DBusPendingCall *pending)
00993 {
00994
00995
00996
00997
00998
00999
01000
01001 _dbus_pending_call_ref_unlocked (pending);
01002 _dbus_hash_table_remove_int (connection->pending_replies,
01003 _dbus_pending_call_get_reply_serial_unlocked (pending));
01004
01005 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
01006 _dbus_connection_remove_timeout_unlocked (connection,
01007 _dbus_pending_call_get_timeout_unlocked (pending));
01008
01009 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
01010
01011 _dbus_pending_call_unref_and_unlock (pending);
01012 }
01013
01022 void
01023 _dbus_connection_remove_pending_call (DBusConnection *connection,
01024 DBusPendingCall *pending)
01025 {
01026 CONNECTION_LOCK (connection);
01027 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
01028 }
01029
01039 static dbus_bool_t
01040 _dbus_connection_acquire_io_path (DBusConnection *connection,
01041 int timeout_milliseconds)
01042 {
01043 dbus_bool_t we_acquired;
01044
01045 HAVE_LOCK_CHECK (connection);
01046
01047
01048 _dbus_connection_ref_unlocked (connection);
01049
01050
01051 CONNECTION_UNLOCK (connection);
01052
01053 _dbus_verbose ("locking io_path_mutex\n");
01054 _dbus_mutex_lock (connection->io_path_mutex);
01055
01056 _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n",
01057 connection->io_path_acquired, timeout_milliseconds);
01058
01059 we_acquired = FALSE;
01060
01061 if (connection->io_path_acquired)
01062 {
01063 if (timeout_milliseconds != -1)
01064 {
01065 _dbus_verbose ("waiting %d for IO path to be acquirable\n",
01066 timeout_milliseconds);
01067
01068 if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
01069 connection->io_path_mutex,
01070 timeout_milliseconds))
01071 {
01072
01073
01074
01075
01076
01077
01078
01079
01080 }
01081 }
01082 else
01083 {
01084 while (connection->io_path_acquired)
01085 {
01086 _dbus_verbose ("waiting for IO path to be acquirable\n");
01087 _dbus_condvar_wait (connection->io_path_cond,
01088 connection->io_path_mutex);
01089 }
01090 }
01091 }
01092
01093 if (!connection->io_path_acquired)
01094 {
01095 we_acquired = TRUE;
01096 connection->io_path_acquired = TRUE;
01097 }
01098
01099 _dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n",
01100 connection->io_path_acquired, we_acquired);
01101
01102 _dbus_verbose ("unlocking io_path_mutex\n");
01103 _dbus_mutex_unlock (connection->io_path_mutex);
01104
01105 CONNECTION_LOCK (connection);
01106
01107 HAVE_LOCK_CHECK (connection);
01108
01109 _dbus_connection_unref_unlocked (connection);
01110
01111 return we_acquired;
01112 }
01113
01121 static void
01122 _dbus_connection_release_io_path (DBusConnection *connection)
01123 {
01124 HAVE_LOCK_CHECK (connection);
01125
01126 _dbus_verbose ("locking io_path_mutex\n");
01127 _dbus_mutex_lock (connection->io_path_mutex);
01128
01129 _dbus_assert (connection->io_path_acquired);
01130
01131 _dbus_verbose ("start connection->io_path_acquired = %d\n",
01132 connection->io_path_acquired);
01133
01134 connection->io_path_acquired = FALSE;
01135 _dbus_condvar_wake_one (connection->io_path_cond);
01136
01137 _dbus_verbose ("unlocking io_path_mutex\n");
01138 _dbus_mutex_unlock (connection->io_path_mutex);
01139 }
01140
01176 void
01177 _dbus_connection_do_iteration_unlocked (DBusConnection *connection,
01178 DBusPendingCall *pending,
01179 unsigned int flags,
01180 int timeout_milliseconds)
01181 {
01182 _dbus_verbose ("start\n");
01183
01184 HAVE_LOCK_CHECK (connection);
01185
01186 if (connection->n_outgoing == 0)
01187 flags &= ~DBUS_ITERATION_DO_WRITING;
01188
01189 if (_dbus_connection_acquire_io_path (connection,
01190 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
01191 {
01192 HAVE_LOCK_CHECK (connection);
01193
01194 if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending))
01195 {
01196 _dbus_verbose ("pending call completed while acquiring I/O path");
01197 }
01198 else if ( (pending != NULL) &&
01199 _dbus_connection_peek_for_reply_unlocked (connection,
01200 _dbus_pending_call_get_reply_serial_unlocked (pending)))
01201 {
01202 _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)");
01203 }
01204 else
01205 {
01206 _dbus_transport_do_iteration (connection->transport,
01207 flags, timeout_milliseconds);
01208 }
01209
01210 _dbus_connection_release_io_path (connection);
01211 }
01212
01213 HAVE_LOCK_CHECK (connection);
01214
01215 _dbus_verbose ("end\n");
01216 }
01217
01227 DBusConnection*
01228 _dbus_connection_new_for_transport (DBusTransport *transport)
01229 {
01230 DBusConnection *connection;
01231 DBusWatchList *watch_list;
01232 DBusTimeoutList *timeout_list;
01233 DBusHashTable *pending_replies;
01234 DBusList *disconnect_link;
01235 DBusMessage *disconnect_message;
01236 DBusCounter *outgoing_counter;
01237 DBusObjectTree *objects;
01238
01239 watch_list = NULL;
01240 connection = NULL;
01241 pending_replies = NULL;
01242 timeout_list = NULL;
01243 disconnect_link = NULL;
01244 disconnect_message = NULL;
01245 outgoing_counter = NULL;
01246 objects = NULL;
01247
01248 watch_list = _dbus_watch_list_new ();
01249 if (watch_list == NULL)
01250 goto error;
01251
01252 timeout_list = _dbus_timeout_list_new ();
01253 if (timeout_list == NULL)
01254 goto error;
01255
01256 pending_replies =
01257 _dbus_hash_table_new (DBUS_HASH_INT,
01258 NULL,
01259 (DBusFreeFunction)free_pending_call_on_hash_removal);
01260 if (pending_replies == NULL)
01261 goto error;
01262
01263 connection = dbus_new0 (DBusConnection, 1);
01264 if (connection == NULL)
01265 goto error;
01266
01267 _dbus_mutex_new_at_location (&connection->mutex);
01268 if (connection->mutex == NULL)
01269 goto error;
01270
01271 _dbus_mutex_new_at_location (&connection->io_path_mutex);
01272 if (connection->io_path_mutex == NULL)
01273 goto error;
01274
01275 _dbus_mutex_new_at_location (&connection->dispatch_mutex);
01276 if (connection->dispatch_mutex == NULL)
01277 goto error;
01278
01279 _dbus_condvar_new_at_location (&connection->dispatch_cond);
01280 if (connection->dispatch_cond == NULL)
01281 goto error;
01282
01283 _dbus_condvar_new_at_location (&connection->io_path_cond);
01284 if (connection->io_path_cond == NULL)
01285 goto error;
01286
01287 _dbus_mutex_new_at_location (&connection->slot_mutex);
01288 if (connection->slot_mutex == NULL)
01289 goto error;
01290
01291 disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
01292 DBUS_INTERFACE_LOCAL,
01293 "Disconnected");
01294
01295 if (disconnect_message == NULL)
01296 goto error;
01297
01298 disconnect_link = _dbus_list_alloc_link (disconnect_message);
01299 if (disconnect_link == NULL)
01300 goto error;
01301
01302 outgoing_counter = _dbus_counter_new ();
01303 if (outgoing_counter == NULL)
01304 goto error;
01305
01306 objects = _dbus_object_tree_new (connection);
01307 if (objects == NULL)
01308 goto error;
01309
01310 if (_dbus_modify_sigpipe)
01311 _dbus_disable_sigpipe ();
01312
01313 connection->refcount.value = 1;
01314 connection->transport = transport;
01315 connection->watches = watch_list;
01316 connection->timeouts = timeout_list;
01317 connection->pending_replies = pending_replies;
01318 connection->outgoing_counter = outgoing_counter;
01319 connection->filter_list = NULL;
01320 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE;
01321 connection->objects = objects;
01322 connection->exit_on_disconnect = FALSE;
01323 connection->shareable = FALSE;
01324 connection->route_peer_messages = FALSE;
01325 connection->disconnected_message_arrived = FALSE;
01326 connection->disconnected_message_processed = FALSE;
01327
01328 #ifndef DBUS_DISABLE_CHECKS
01329 connection->generation = _dbus_current_generation;
01330 #endif
01331
01332 _dbus_data_slot_list_init (&connection->slot_list);
01333
01334 connection->client_serial = 1;
01335
01336 connection->disconnect_message_link = disconnect_link;
01337
01338 CONNECTION_LOCK (connection);
01339
01340 if (!_dbus_transport_set_connection (transport, connection))
01341 {
01342 CONNECTION_UNLOCK (connection);
01343
01344 goto error;
01345 }
01346
01347 _dbus_transport_ref (transport);
01348
01349 CONNECTION_UNLOCK (connection);
01350
01351 return connection;
01352
01353 error:
01354 if (disconnect_message != NULL)
01355 dbus_message_unref (disconnect_message);
01356
01357 if (disconnect_link != NULL)
01358 _dbus_list_free_link (disconnect_link);
01359
01360 if (connection != NULL)
01361 {
01362 _dbus_condvar_free_at_location (&connection->io_path_cond);
01363 _dbus_condvar_free_at_location (&connection->dispatch_cond);
01364 _dbus_mutex_free_at_location (&connection->mutex);
01365 _dbus_mutex_free_at_location (&connection->io_path_mutex);
01366 _dbus_mutex_free_at_location (&connection->dispatch_mutex);
01367 _dbus_mutex_free_at_location (&connection->slot_mutex);
01368 dbus_free (connection);
01369 }
01370 if (pending_replies)
01371 _dbus_hash_table_unref (pending_replies);
01372
01373 if (watch_list)
01374 _dbus_watch_list_free (watch_list);
01375
01376 if (timeout_list)
01377 _dbus_timeout_list_free (timeout_list);
01378
01379 if (outgoing_counter)
01380 _dbus_counter_unref (outgoing_counter);
01381
01382 if (objects)
01383 _dbus_object_tree_unref (objects);
01384
01385 return NULL;
01386 }
01387
01395 DBusConnection *
01396 _dbus_connection_ref_unlocked (DBusConnection *connection)
01397 {
01398 _dbus_assert (connection != NULL);
01399 _dbus_assert (connection->generation == _dbus_current_generation);
01400
01401 HAVE_LOCK_CHECK (connection);
01402
01403 #ifdef DBUS_HAVE_ATOMIC_INT
01404 _dbus_atomic_inc (&connection->refcount);
01405 #else
01406 _dbus_assert (connection->refcount.value > 0);
01407 connection->refcount.value += 1;
01408 #endif
01409
01410 return connection;
01411 }
01412
01419 void
01420 _dbus_connection_unref_unlocked (DBusConnection *connection)
01421 {
01422 dbus_bool_t last_unref;
01423
01424 HAVE_LOCK_CHECK (connection);
01425
01426 _dbus_assert (connection != NULL);
01427
01428
01429
01430
01431
01432 #ifdef DBUS_HAVE_ATOMIC_INT
01433 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
01434 #else
01435 _dbus_assert (connection->refcount.value > 0);
01436
01437 connection->refcount.value -= 1;
01438 last_unref = (connection->refcount.value == 0);
01439 #if 0
01440 printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value);
01441 #endif
01442 #endif
01443
01444 if (last_unref)
01445 _dbus_connection_last_unref (connection);
01446 }
01447
01448 static dbus_uint32_t
01449 _dbus_connection_get_next_client_serial (DBusConnection *connection)
01450 {
01451 dbus_uint32_t serial;
01452
01453 serial = connection->client_serial++;
01454
01455 if (connection->client_serial == 0)
01456 connection->client_serial = 1;
01457
01458 return serial;
01459 }
01460
01474 dbus_bool_t
01475 _dbus_connection_handle_watch (DBusWatch *watch,
01476 unsigned int condition,
01477 void *data)
01478 {
01479 DBusConnection *connection;
01480 dbus_bool_t retval;
01481 DBusDispatchStatus status;
01482
01483 connection = data;
01484
01485 _dbus_verbose ("start\n");
01486
01487 CONNECTION_LOCK (connection);
01488
01489 if (!_dbus_connection_acquire_io_path (connection, 1))
01490 {
01491
01492 CONNECTION_UNLOCK (connection);
01493 return TRUE;
01494 }
01495
01496 HAVE_LOCK_CHECK (connection);
01497 retval = _dbus_transport_handle_watch (connection->transport,
01498 watch, condition);
01499
01500 _dbus_connection_release_io_path (connection);
01501
01502 HAVE_LOCK_CHECK (connection);
01503
01504 _dbus_verbose ("middle\n");
01505
01506 status = _dbus_connection_get_dispatch_status_unlocked (connection);
01507
01508
01509 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
01510
01511 _dbus_verbose ("end\n");
01512
01513 return retval;
01514 }
01515
01516 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
01517 static DBusHashTable *shared_connections = NULL;
01518 static DBusList *shared_connections_no_guid = NULL;
01519
01520 static void
01521 close_connection_on_shutdown (DBusConnection *connection)
01522 {
01523 DBusMessage *message;
01524
01525 dbus_connection_ref (connection);
01526 _dbus_connection_close_possibly_shared (connection);
01527
01528
01529 while ((message = dbus_connection_pop_message (connection)))
01530 {
01531 dbus_message_unref (message);
01532 }
01533 dbus_connection_unref (connection);
01534 }
01535
01536 static void
01537 shared_connections_shutdown (void *data)
01538 {
01539 int n_entries;
01540
01541 _DBUS_LOCK (shared_connections);
01542
01543
01544 while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
01545 {
01546 DBusConnection *connection;
01547 DBusHashIter iter;
01548
01549 _dbus_hash_iter_init (shared_connections, &iter);
01550 _dbus_hash_iter_next (&iter);
01551
01552 connection = _dbus_hash_iter_get_value (&iter);
01553
01554 _DBUS_UNLOCK (shared_connections);
01555 close_connection_on_shutdown (connection);
01556 _DBUS_LOCK (shared_connections);
01557
01558
01559 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
01560 }
01561
01562 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
01563
01564 _dbus_hash_table_unref (shared_connections);
01565 shared_connections = NULL;
01566
01567 if (shared_connections_no_guid != NULL)
01568 {
01569 DBusConnection *connection;
01570 connection = _dbus_list_pop_first (&shared_connections_no_guid);
01571 while (connection != NULL)
01572 {
01573 _DBUS_UNLOCK (shared_connections);
01574 close_connection_on_shutdown (connection);
01575 _DBUS_LOCK (shared_connections);
01576 connection = _dbus_list_pop_first (&shared_connections_no_guid);
01577 }
01578 }
01579
01580 shared_connections_no_guid = NULL;
01581
01582 _DBUS_UNLOCK (shared_connections);
01583 }
01584
01585 static dbus_bool_t
01586 connection_lookup_shared (DBusAddressEntry *entry,
01587 DBusConnection **result)
01588 {
01589 _dbus_verbose ("checking for existing connection\n");
01590
01591 *result = NULL;
01592
01593 _DBUS_LOCK (shared_connections);
01594
01595 if (shared_connections == NULL)
01596 {
01597 _dbus_verbose ("creating shared_connections hash table\n");
01598
01599 shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
01600 dbus_free,
01601 NULL);
01602 if (shared_connections == NULL)
01603 {
01604 _DBUS_UNLOCK (shared_connections);
01605 return FALSE;
01606 }
01607
01608 if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
01609 {
01610 _dbus_hash_table_unref (shared_connections);
01611 shared_connections = NULL;
01612 _DBUS_UNLOCK (shared_connections);
01613 return FALSE;
01614 }
01615
01616 _dbus_verbose (" successfully created shared_connections\n");
01617
01618 _DBUS_UNLOCK (shared_connections);
01619 return TRUE;
01620 }
01621 else
01622 {
01623 const char *guid;
01624
01625 guid = dbus_address_entry_get_value (entry, "guid");
01626
01627 if (guid != NULL)
01628 {
01629 DBusConnection *connection;
01630
01631 connection = _dbus_hash_table_lookup_string (shared_connections,
01632 guid);
01633
01634 if (connection)
01635 {
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650 CONNECTION_LOCK (connection);
01651 if (_dbus_connection_get_is_connected_unlocked (connection))
01652 {
01653 _dbus_connection_ref_unlocked (connection);
01654 *result = connection;
01655 _dbus_verbose ("looked up existing connection to server guid %s\n",
01656 guid);
01657 }
01658 else
01659 {
01660 _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
01661 guid);
01662 }
01663 CONNECTION_UNLOCK (connection);
01664 }
01665 }
01666
01667 _DBUS_UNLOCK (shared_connections);
01668 return TRUE;
01669 }
01670 }
01671
01672 static dbus_bool_t
01673 connection_record_shared_unlocked (DBusConnection *connection,
01674 const char *guid)
01675 {
01676 char *guid_key;
01677 char *guid_in_connection;
01678
01679 HAVE_LOCK_CHECK (connection);
01680 _dbus_assert (connection->server_guid == NULL);
01681 _dbus_assert (connection->shareable);
01682
01683
01684
01685
01686
01687 _dbus_connection_ref_unlocked (connection);
01688
01689 if (guid == NULL)
01690 {
01691 _DBUS_LOCK (shared_connections);
01692
01693 if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
01694 {
01695 _DBUS_UNLOCK (shared_connections);
01696 return FALSE;
01697 }
01698
01699 _DBUS_UNLOCK (shared_connections);
01700 return TRUE;
01701 }
01702
01703
01704
01705
01706
01707
01708 guid_key = _dbus_strdup (guid);
01709 if (guid_key == NULL)
01710 return FALSE;
01711
01712 guid_in_connection = _dbus_strdup (guid);
01713 if (guid_in_connection == NULL)
01714 {
01715 dbus_free (guid_key);
01716 return FALSE;
01717 }
01718
01719 _DBUS_LOCK (shared_connections);
01720 _dbus_assert (shared_connections != NULL);
01721
01722 if (!_dbus_hash_table_insert_string (shared_connections,
01723 guid_key, connection))
01724 {
01725 dbus_free (guid_key);
01726 dbus_free (guid_in_connection);
01727 _DBUS_UNLOCK (shared_connections);
01728 return FALSE;
01729 }
01730
01731 connection->server_guid = guid_in_connection;
01732
01733 _dbus_verbose ("stored connection to %s to be shared\n",
01734 connection->server_guid);
01735
01736 _DBUS_UNLOCK (shared_connections);
01737
01738 _dbus_assert (connection->server_guid != NULL);
01739
01740 return TRUE;
01741 }
01742
01743 static void
01744 connection_forget_shared_unlocked (DBusConnection *connection)
01745 {
01746 HAVE_LOCK_CHECK (connection);
01747
01748 if (!connection->shareable)
01749 return;
01750
01751 _DBUS_LOCK (shared_connections);
01752
01753 if (connection->server_guid != NULL)
01754 {
01755 _dbus_verbose ("dropping connection to %s out of the shared table\n",
01756 connection->server_guid);
01757
01758 if (!_dbus_hash_table_remove_string (shared_connections,
01759 connection->server_guid))
01760 _dbus_assert_not_reached ("connection was not in the shared table");
01761
01762 dbus_free (connection->server_guid);
01763 connection->server_guid = NULL;
01764 }
01765 else
01766 {
01767 _dbus_list_remove (&shared_connections_no_guid, connection);
01768 }
01769
01770 _DBUS_UNLOCK (shared_connections);
01771
01772
01773 _dbus_connection_unref_unlocked (connection);
01774 }
01775
01776 static DBusConnection*
01777 connection_try_from_address_entry (DBusAddressEntry *entry,
01778 DBusError *error)
01779 {
01780 DBusTransport *transport;
01781 DBusConnection *connection;
01782
01783 transport = _dbus_transport_open (entry, error);
01784
01785 if (transport == NULL)
01786 {
01787 _DBUS_ASSERT_ERROR_IS_SET (error);
01788 return NULL;
01789 }
01790
01791 connection = _dbus_connection_new_for_transport (transport);
01792
01793 _dbus_transport_unref (transport);
01794
01795 if (connection == NULL)
01796 {
01797 _DBUS_SET_OOM (error);
01798 return NULL;
01799 }
01800
01801 #ifndef DBUS_DISABLE_CHECKS
01802 _dbus_assert (!connection->have_connection_lock);
01803 #endif
01804 return connection;
01805 }
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819 static DBusConnection*
01820 _dbus_connection_open_internal (const char *address,
01821 dbus_bool_t shared,
01822 DBusError *error)
01823 {
01824 DBusConnection *connection;
01825 DBusAddressEntry **entries;
01826 DBusError tmp_error = DBUS_ERROR_INIT;
01827 DBusError first_error = DBUS_ERROR_INIT;
01828 int len, i;
01829
01830 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01831
01832 _dbus_verbose ("opening %s connection to: %s\n",
01833 shared ? "shared" : "private", address);
01834
01835 if (!dbus_parse_address (address, &entries, &len, error))
01836 return NULL;
01837
01838 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01839
01840 connection = NULL;
01841
01842 for (i = 0; i < len; i++)
01843 {
01844 if (shared)
01845 {
01846 if (!connection_lookup_shared (entries[i], &connection))
01847 _DBUS_SET_OOM (&tmp_error);
01848 }
01849
01850 if (connection == NULL)
01851 {
01852 connection = connection_try_from_address_entry (entries[i],
01853 &tmp_error);
01854
01855 if (connection != NULL && shared)
01856 {
01857 const char *guid;
01858
01859 connection->shareable = TRUE;
01860
01861
01862 guid = dbus_address_entry_get_value (entries[i], "guid");
01863
01864 CONNECTION_LOCK (connection);
01865
01866 if (!connection_record_shared_unlocked (connection, guid))
01867 {
01868 _DBUS_SET_OOM (&tmp_error);
01869 _dbus_connection_close_possibly_shared_and_unlock (connection);
01870 dbus_connection_unref (connection);
01871 connection = NULL;
01872 }
01873 else
01874 CONNECTION_UNLOCK (connection);
01875 }
01876 }
01877
01878 if (connection)
01879 break;
01880
01881 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01882
01883 if (i == 0)
01884 dbus_move_error (&tmp_error, &first_error);
01885 else
01886 dbus_error_free (&tmp_error);
01887 }
01888
01889 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01890 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01891
01892 if (connection == NULL)
01893 {
01894 _DBUS_ASSERT_ERROR_IS_SET (&first_error);
01895 dbus_move_error (&first_error, error);
01896 }
01897 else
01898 dbus_error_free (&first_error);
01899
01900 dbus_address_entries_free (entries);
01901 return connection;
01902 }
01903
01912 void
01913 _dbus_connection_close_possibly_shared (DBusConnection *connection)
01914 {
01915 _dbus_assert (connection != NULL);
01916 _dbus_assert (connection->generation == _dbus_current_generation);
01917
01918 CONNECTION_LOCK (connection);
01919 _dbus_connection_close_possibly_shared_and_unlock (connection);
01920 }
01921
01922 static DBusPreallocatedSend*
01923 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
01924 {
01925 DBusPreallocatedSend *preallocated;
01926
01927 HAVE_LOCK_CHECK (connection);
01928
01929 _dbus_assert (connection != NULL);
01930
01931 preallocated = dbus_new (DBusPreallocatedSend, 1);
01932 if (preallocated == NULL)
01933 return NULL;
01934
01935 if (connection->link_cache != NULL)
01936 {
01937 preallocated->queue_link =
01938 _dbus_list_pop_first_link (&connection->link_cache);
01939 preallocated->queue_link->data = NULL;
01940 }
01941 else
01942 {
01943 preallocated->queue_link = _dbus_list_alloc_link (NULL);
01944 if (preallocated->queue_link == NULL)
01945 goto failed_0;
01946 }
01947
01948 if (connection->link_cache != NULL)
01949 {
01950 preallocated->counter_link =
01951 _dbus_list_pop_first_link (&connection->link_cache);
01952 preallocated->counter_link->data = connection->outgoing_counter;
01953 }
01954 else
01955 {
01956 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
01957 if (preallocated->counter_link == NULL)
01958 goto failed_1;
01959 }
01960
01961 _dbus_counter_ref (preallocated->counter_link->data);
01962
01963 preallocated->connection = connection;
01964
01965 return preallocated;
01966
01967 failed_1:
01968 _dbus_list_free_link (preallocated->queue_link);
01969 failed_0:
01970 dbus_free (preallocated);
01971
01972 return NULL;
01973 }
01974
01975
01976 static void
01977 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection,
01978 DBusPreallocatedSend *preallocated,
01979 DBusMessage *message,
01980 dbus_uint32_t *client_serial)
01981 {
01982 dbus_uint32_t serial;
01983 const char *sig;
01984
01985 preallocated->queue_link->data = message;
01986 _dbus_list_prepend_link (&connection->outgoing_messages,
01987 preallocated->queue_link);
01988
01989 _dbus_message_add_counter_link (message,
01990 preallocated->counter_link);
01991
01992 dbus_free (preallocated);
01993 preallocated = NULL;
01994
01995 dbus_message_ref (message);
01996
01997 connection->n_outgoing += 1;
01998
01999 sig = dbus_message_get_signature (message);
02000
02001 _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
02002 message,
02003 dbus_message_type_to_string (dbus_message_get_type (message)),
02004 dbus_message_get_path (message) ?
02005 dbus_message_get_path (message) :
02006 "no path",
02007 dbus_message_get_interface (message) ?
02008 dbus_message_get_interface (message) :
02009 "no interface",
02010 dbus_message_get_member (message) ?
02011 dbus_message_get_member (message) :
02012 "no member",
02013 sig,
02014 dbus_message_get_destination (message) ?
02015 dbus_message_get_destination (message) :
02016 "null",
02017 connection,
02018 connection->n_outgoing);
02019
02020 if (dbus_message_get_serial (message) == 0)
02021 {
02022 serial = _dbus_connection_get_next_client_serial (connection);
02023 dbus_message_set_serial (message, serial);
02024 if (client_serial)
02025 *client_serial = serial;
02026 }
02027 else
02028 {
02029 if (client_serial)
02030 *client_serial = dbus_message_get_serial (message);
02031 }
02032
02033 _dbus_verbose ("Message %p serial is %u\n",
02034 message, dbus_message_get_serial (message));
02035
02036 dbus_message_lock (message);
02037
02038
02039
02040
02041 _dbus_connection_do_iteration_unlocked (connection,
02042 NULL,
02043 DBUS_ITERATION_DO_WRITING,
02044 -1);
02045
02046
02047 if (connection->n_outgoing > 0)
02048 _dbus_connection_wakeup_mainloop (connection);
02049 }
02050
02051 static void
02052 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection,
02053 DBusPreallocatedSend *preallocated,
02054 DBusMessage *message,
02055 dbus_uint32_t *client_serial)
02056 {
02057 DBusDispatchStatus status;
02058
02059 HAVE_LOCK_CHECK (connection);
02060
02061 _dbus_connection_send_preallocated_unlocked_no_update (connection,
02062 preallocated,
02063 message, client_serial);
02064
02065 _dbus_verbose ("middle\n");
02066 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02067
02068
02069 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02070 }
02071
02081 dbus_bool_t
02082 _dbus_connection_send_and_unlock (DBusConnection *connection,
02083 DBusMessage *message,
02084 dbus_uint32_t *client_serial)
02085 {
02086 DBusPreallocatedSend *preallocated;
02087
02088 _dbus_assert (connection != NULL);
02089 _dbus_assert (message != NULL);
02090
02091 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
02092 if (preallocated == NULL)
02093 {
02094 CONNECTION_UNLOCK (connection);
02095 return FALSE;
02096 }
02097
02098 _dbus_connection_send_preallocated_and_unlock (connection,
02099 preallocated,
02100 message,
02101 client_serial);
02102 return TRUE;
02103 }
02104
02129 void
02130 _dbus_connection_close_if_only_one_ref (DBusConnection *connection)
02131 {
02132 CONNECTION_LOCK (connection);
02133
02134 _dbus_assert (connection->refcount.value > 0);
02135
02136 if (connection->refcount.value == 1)
02137 _dbus_connection_close_possibly_shared_and_unlock (connection);
02138 else
02139 CONNECTION_UNLOCK (connection);
02140 }
02141
02142
02152 static void
02153 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
02154 {
02155 if (timeout_milliseconds == -1)
02156 _dbus_sleep_milliseconds (1000);
02157 else if (timeout_milliseconds < 100)
02158 ;
02159 else if (timeout_milliseconds <= 1000)
02160 _dbus_sleep_milliseconds (timeout_milliseconds / 3);
02161 else
02162 _dbus_sleep_milliseconds (1000);
02163 }
02164
02165 static DBusMessage *
02166 generate_local_error_message (dbus_uint32_t serial,
02167 char *error_name,
02168 char *error_msg)
02169 {
02170 DBusMessage *message;
02171 message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
02172 if (!message)
02173 goto out;
02174
02175 if (!dbus_message_set_error_name (message, error_name))
02176 {
02177 dbus_message_unref (message);
02178 message = NULL;
02179 goto out;
02180 }
02181
02182 dbus_message_set_no_reply (message, TRUE);
02183
02184 if (!dbus_message_set_reply_serial (message,
02185 serial))
02186 {
02187 dbus_message_unref (message);
02188 message = NULL;
02189 goto out;
02190 }
02191
02192 if (error_msg != NULL)
02193 {
02194 DBusMessageIter iter;
02195
02196 dbus_message_iter_init_append (message, &iter);
02197 if (!dbus_message_iter_append_basic (&iter,
02198 DBUS_TYPE_STRING,
02199 &error_msg))
02200 {
02201 dbus_message_unref (message);
02202 message = NULL;
02203 goto out;
02204 }
02205 }
02206
02207 out:
02208 return message;
02209 }
02210
02211
02212
02213
02214 static dbus_bool_t
02215 _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
02216 dbus_uint32_t client_serial)
02217 {
02218 DBusList *link;
02219 HAVE_LOCK_CHECK (connection);
02220
02221 link = _dbus_list_get_first_link (&connection->incoming_messages);
02222
02223 while (link != NULL)
02224 {
02225 DBusMessage *reply = link->data;
02226
02227 if (dbus_message_get_reply_serial (reply) == client_serial)
02228 {
02229 _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial);
02230 return TRUE;
02231 }
02232 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02233 }
02234
02235 return FALSE;
02236 }
02237
02238
02239
02240
02241 static DBusMessage*
02242 check_for_reply_unlocked (DBusConnection *connection,
02243 dbus_uint32_t client_serial)
02244 {
02245 DBusList *link;
02246
02247 HAVE_LOCK_CHECK (connection);
02248
02249 link = _dbus_list_get_first_link (&connection->incoming_messages);
02250
02251 while (link != NULL)
02252 {
02253 DBusMessage *reply = link->data;
02254
02255 if (dbus_message_get_reply_serial (reply) == client_serial)
02256 {
02257 _dbus_list_remove_link (&connection->incoming_messages, link);
02258 connection->n_incoming -= 1;
02259 return reply;
02260 }
02261 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
02262 }
02263
02264 return NULL;
02265 }
02266
02267 static void
02268 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
02269 {
02270
02271
02272
02273
02274
02275 while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
02276 {
02277 DBusPendingCall *pending;
02278 DBusHashIter iter;
02279
02280 _dbus_hash_iter_init (connection->pending_replies, &iter);
02281 _dbus_hash_iter_next (&iter);
02282
02283 pending = _dbus_hash_iter_get_value (&iter);
02284 _dbus_pending_call_ref_unlocked (pending);
02285
02286 _dbus_pending_call_queue_timeout_error_unlocked (pending,
02287 connection);
02288
02289 if (_dbus_pending_call_is_timeout_added_unlocked (pending))
02290 _dbus_connection_remove_timeout_unlocked (connection,
02291 _dbus_pending_call_get_timeout_unlocked (pending));
02292 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
02293 _dbus_hash_iter_remove_entry (&iter);
02294
02295 _dbus_pending_call_unref_and_unlock (pending);
02296 CONNECTION_LOCK (connection);
02297 }
02298 HAVE_LOCK_CHECK (connection);
02299 }
02300
02301 static void
02302 complete_pending_call_and_unlock (DBusConnection *connection,
02303 DBusPendingCall *pending,
02304 DBusMessage *message)
02305 {
02306 _dbus_pending_call_set_reply_unlocked (pending, message);
02307 _dbus_pending_call_ref_unlocked (pending);
02308 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
02309
02310
02311 _dbus_pending_call_complete (pending);
02312 dbus_pending_call_unref (pending);
02313 }
02314
02315 static dbus_bool_t
02316 check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection,
02317 DBusPendingCall *pending)
02318 {
02319 DBusMessage *reply;
02320 DBusDispatchStatus status;
02321
02322 reply = check_for_reply_unlocked (connection,
02323 _dbus_pending_call_get_reply_serial_unlocked (pending));
02324 if (reply != NULL)
02325 {
02326 _dbus_verbose ("checked for reply\n");
02327
02328 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
02329
02330 complete_pending_call_and_unlock (connection, pending, reply);
02331 dbus_message_unref (reply);
02332
02333 CONNECTION_LOCK (connection);
02334 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02335 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02336 dbus_pending_call_unref (pending);
02337
02338 return TRUE;
02339 }
02340
02341 return FALSE;
02342 }
02343
02358 void
02359 _dbus_connection_block_pending_call (DBusPendingCall *pending)
02360 {
02361 long start_tv_sec, start_tv_usec;
02362 long tv_sec, tv_usec;
02363 DBusDispatchStatus status;
02364 DBusConnection *connection;
02365 dbus_uint32_t client_serial;
02366 DBusTimeout *timeout;
02367 int timeout_milliseconds, elapsed_milliseconds;
02368
02369 _dbus_assert (pending != NULL);
02370
02371 if (dbus_pending_call_get_completed (pending))
02372 return;
02373
02374 dbus_pending_call_ref (pending);
02375
02376 connection = _dbus_pending_call_get_connection_and_lock (pending);
02377
02378
02379 _dbus_connection_flush_unlocked (connection);
02380
02381 client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
02382
02383
02384
02385
02386
02387 timeout = _dbus_pending_call_get_timeout_unlocked (pending);
02388 if (timeout)
02389 {
02390 timeout_milliseconds = dbus_timeout_get_interval (timeout);
02391 _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
02392
02393 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n",
02394 timeout_milliseconds,
02395 client_serial,
02396 start_tv_sec, start_tv_usec);
02397 }
02398 else
02399 {
02400 timeout_milliseconds = -1;
02401
02402 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial);
02403 }
02404
02405
02406
02407 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02408 return;
02409
02410
02411
02412 _dbus_connection_do_iteration_unlocked (connection,
02413 pending,
02414 DBUS_ITERATION_DO_READING |
02415 DBUS_ITERATION_BLOCK,
02416 timeout_milliseconds);
02417
02418 recheck_status:
02419
02420 _dbus_verbose ("top of recheck\n");
02421
02422 HAVE_LOCK_CHECK (connection);
02423
02424
02425
02426 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02427
02428
02429
02430
02431 if (_dbus_pending_call_get_completed_unlocked (pending))
02432 {
02433 _dbus_verbose ("Pending call completed by dispatch\n");
02434 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02435 dbus_pending_call_unref (pending);
02436 return;
02437 }
02438
02439 if (status == DBUS_DISPATCH_DATA_REMAINS)
02440 {
02441 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
02442 return;
02443 }
02444
02445 _dbus_get_current_time (&tv_sec, &tv_usec);
02446 elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
02447 (tv_usec - start_tv_usec) / 1000;
02448
02449 if (!_dbus_connection_get_is_connected_unlocked (connection))
02450 {
02451 DBusMessage *error_msg;
02452
02453 error_msg = generate_local_error_message (client_serial,
02454 DBUS_ERROR_DISCONNECTED,
02455 "Connection was disconnected before a reply was received");
02456
02457
02458 complete_pending_call_and_unlock (connection, pending, error_msg);
02459 dbus_pending_call_unref (pending);
02460 return;
02461 }
02462 else if (connection->disconnect_message_link == NULL)
02463 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
02464 else if (timeout == NULL)
02465 {
02466 if (status == DBUS_DISPATCH_NEED_MEMORY)
02467 {
02468
02469
02470
02471
02472 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02473
02474 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02475 }
02476 else
02477 {
02478
02479 _dbus_connection_do_iteration_unlocked (connection,
02480 pending,
02481 DBUS_ITERATION_DO_READING |
02482 DBUS_ITERATION_BLOCK,
02483 timeout_milliseconds - elapsed_milliseconds);
02484 }
02485
02486 goto recheck_status;
02487 }
02488 else if (tv_sec < start_tv_sec)
02489 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
02490 else if (elapsed_milliseconds < timeout_milliseconds)
02491 {
02492 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds);
02493
02494 if (status == DBUS_DISPATCH_NEED_MEMORY)
02495 {
02496
02497
02498
02499
02500 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
02501
02502 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
02503 }
02504 else
02505 {
02506
02507 _dbus_connection_do_iteration_unlocked (connection,
02508 NULL,
02509 DBUS_ITERATION_DO_READING |
02510 DBUS_ITERATION_BLOCK,
02511 timeout_milliseconds - elapsed_milliseconds);
02512 }
02513
02514 goto recheck_status;
02515 }
02516
02517 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n",
02518 elapsed_milliseconds);
02519
02520 _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending));
02521
02522
02523 complete_pending_call_and_unlock (connection, pending, NULL);
02524
02525
02526 CONNECTION_LOCK (connection);
02527 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02528 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02529 dbus_pending_call_unref (pending);
02530 }
02531
02568 DBusConnection*
02569 dbus_connection_open (const char *address,
02570 DBusError *error)
02571 {
02572 DBusConnection *connection;
02573
02574 _dbus_return_val_if_fail (address != NULL, NULL);
02575 _dbus_return_val_if_error_is_set (error, NULL);
02576
02577 connection = _dbus_connection_open_internal (address,
02578 TRUE,
02579 error);
02580
02581 return connection;
02582 }
02583
02611 DBusConnection*
02612 dbus_connection_open_private (const char *address,
02613 DBusError *error)
02614 {
02615 DBusConnection *connection;
02616
02617 _dbus_return_val_if_fail (address != NULL, NULL);
02618 _dbus_return_val_if_error_is_set (error, NULL);
02619
02620 connection = _dbus_connection_open_internal (address,
02621 FALSE,
02622 error);
02623
02624 return connection;
02625 }
02626
02633 DBusConnection *
02634 dbus_connection_ref (DBusConnection *connection)
02635 {
02636 _dbus_return_val_if_fail (connection != NULL, NULL);
02637 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647
02648 #if 1
02649 _dbus_atomic_inc (&connection->refcount);
02650 #else
02651 CONNECTION_LOCK (connection);
02652 _dbus_assert (connection->refcount.value > 0);
02653
02654 connection->refcount.value += 1;
02655 CONNECTION_UNLOCK (connection);
02656 #endif
02657
02658 return connection;
02659 }
02660
02661 static void
02662 free_outgoing_message (void *element,
02663 void *data)
02664 {
02665 DBusMessage *message = element;
02666 DBusConnection *connection = data;
02667
02668 _dbus_message_remove_counter (message,
02669 connection->outgoing_counter,
02670 NULL);
02671 dbus_message_unref (message);
02672 }
02673
02674
02675
02676
02677
02678 static void
02679 _dbus_connection_last_unref (DBusConnection *connection)
02680 {
02681 DBusList *link;
02682
02683 _dbus_verbose ("Finalizing connection %p\n", connection);
02684
02685 _dbus_assert (connection->refcount.value == 0);
02686
02687
02688
02689
02690 _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
02691 _dbus_assert (connection->server_guid == NULL);
02692
02693
02694 _dbus_object_tree_free_all_unlocked (connection->objects);
02695
02696 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
02697 dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
02698 dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
02699
02700 _dbus_watch_list_free (connection->watches);
02701 connection->watches = NULL;
02702
02703 _dbus_timeout_list_free (connection->timeouts);
02704 connection->timeouts = NULL;
02705
02706 _dbus_data_slot_list_free (&connection->slot_list);
02707
02708 link = _dbus_list_get_first_link (&connection->filter_list);
02709 while (link != NULL)
02710 {
02711 DBusMessageFilter *filter = link->data;
02712 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
02713
02714 filter->function = NULL;
02715 _dbus_message_filter_unref (filter);
02716 link->data = NULL;
02717
02718 link = next;
02719 }
02720 _dbus_list_clear (&connection->filter_list);
02721
02722
02723
02724 _dbus_object_tree_unref (connection->objects);
02725
02726 _dbus_hash_table_unref (connection->pending_replies);
02727 connection->pending_replies = NULL;
02728
02729 _dbus_list_clear (&connection->filter_list);
02730
02731 _dbus_list_foreach (&connection->outgoing_messages,
02732 free_outgoing_message,
02733 connection);
02734 _dbus_list_clear (&connection->outgoing_messages);
02735
02736 _dbus_list_foreach (&connection->incoming_messages,
02737 (DBusForeachFunction) dbus_message_unref,
02738 NULL);
02739 _dbus_list_clear (&connection->incoming_messages);
02740
02741 _dbus_counter_unref (connection->outgoing_counter);
02742
02743 _dbus_transport_unref (connection->transport);
02744
02745 if (connection->disconnect_message_link)
02746 {
02747 DBusMessage *message = connection->disconnect_message_link->data;
02748 dbus_message_unref (message);
02749 _dbus_list_free_link (connection->disconnect_message_link);
02750 }
02751
02752 _dbus_list_clear (&connection->link_cache);
02753
02754 _dbus_condvar_free_at_location (&connection->dispatch_cond);
02755 _dbus_condvar_free_at_location (&connection->io_path_cond);
02756
02757 _dbus_mutex_free_at_location (&connection->io_path_mutex);
02758 _dbus_mutex_free_at_location (&connection->dispatch_mutex);
02759
02760 _dbus_mutex_free_at_location (&connection->slot_mutex);
02761
02762 _dbus_mutex_free_at_location (&connection->mutex);
02763
02764 dbus_free (connection);
02765 }
02766
02786 void
02787 dbus_connection_unref (DBusConnection *connection)
02788 {
02789 dbus_bool_t last_unref;
02790
02791 _dbus_return_if_fail (connection != NULL);
02792 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02793
02794
02795
02796
02797
02798
02799
02800
02801
02802
02803 #if 1
02804 last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
02805 #else
02806 CONNECTION_LOCK (connection);
02807
02808 _dbus_assert (connection->refcount.value > 0);
02809
02810 connection->refcount.value -= 1;
02811 last_unref = (connection->refcount.value == 0);
02812
02813 #if 0
02814 printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
02815 #endif
02816
02817 CONNECTION_UNLOCK (connection);
02818 #endif
02819
02820 if (last_unref)
02821 {
02822 #ifndef DBUS_DISABLE_CHECKS
02823 if (_dbus_transport_get_is_connected (connection->transport))
02824 {
02825 _dbus_warn_check_failed ("The last reference on a connection was dropped without closing the connection. This is a bug in an application. See dbus_connection_unref() documentation for details.\n%s",
02826 connection->shareable ?
02827 "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" :
02828 "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
02829 return;
02830 }
02831 #endif
02832 _dbus_connection_last_unref (connection);
02833 }
02834 }
02835
02836
02837
02838
02839
02840
02841
02842
02843
02844
02845 static void
02846 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
02847 {
02848 DBusDispatchStatus status;
02849
02850 HAVE_LOCK_CHECK (connection);
02851
02852 _dbus_verbose ("Disconnecting %p\n", connection);
02853
02854
02855
02856
02857
02858 _dbus_connection_ref_unlocked (connection);
02859
02860 _dbus_transport_disconnect (connection->transport);
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871 status = _dbus_connection_get_dispatch_status_unlocked (connection);
02872
02873
02874 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
02875
02876
02877 dbus_connection_unref (connection);
02878 }
02879
02922 void
02923 dbus_connection_close (DBusConnection *connection)
02924 {
02925 _dbus_return_if_fail (connection != NULL);
02926 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
02927
02928 CONNECTION_LOCK (connection);
02929
02930 #ifndef DBUS_DISABLE_CHECKS
02931 if (connection->shareable)
02932 {
02933 CONNECTION_UNLOCK (connection);
02934
02935 _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
02936 return;
02937 }
02938 #endif
02939
02940 _dbus_connection_close_possibly_shared_and_unlock (connection);
02941 }
02942
02943 static dbus_bool_t
02944 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
02945 {
02946 HAVE_LOCK_CHECK (connection);
02947 return _dbus_transport_get_is_connected (connection->transport);
02948 }
02949
02963 dbus_bool_t
02964 dbus_connection_get_is_connected (DBusConnection *connection)
02965 {
02966 dbus_bool_t res;
02967
02968 _dbus_return_val_if_fail (connection != NULL, FALSE);
02969
02970 CONNECTION_LOCK (connection);
02971 res = _dbus_connection_get_is_connected_unlocked (connection);
02972 CONNECTION_UNLOCK (connection);
02973
02974 return res;
02975 }
02976
02985 dbus_bool_t
02986 dbus_connection_get_is_authenticated (DBusConnection *connection)
02987 {
02988 dbus_bool_t res;
02989
02990 _dbus_return_val_if_fail (connection != NULL, FALSE);
02991
02992 CONNECTION_LOCK (connection);
02993 res = _dbus_transport_get_is_authenticated (connection->transport);
02994 CONNECTION_UNLOCK (connection);
02995
02996 return res;
02997 }
02998
03019 dbus_bool_t
03020 dbus_connection_get_is_anonymous (DBusConnection *connection)
03021 {
03022 dbus_bool_t res;
03023
03024 _dbus_return_val_if_fail (connection != NULL, FALSE);
03025
03026 CONNECTION_LOCK (connection);
03027 res = _dbus_transport_get_is_anonymous (connection->transport);
03028 CONNECTION_UNLOCK (connection);
03029
03030 return res;
03031 }
03032
03064 char*
03065 dbus_connection_get_server_id (DBusConnection *connection)
03066 {
03067 char *id;
03068
03069 _dbus_return_val_if_fail (connection != NULL, NULL);
03070
03071 CONNECTION_LOCK (connection);
03072 id = _dbus_strdup (_dbus_transport_get_server_id (connection->transport));
03073 CONNECTION_UNLOCK (connection);
03074
03075 return id;
03076 }
03077
03095 dbus_bool_t
03096 dbus_connection_can_send_type(DBusConnection *connection,
03097 int type)
03098 {
03099 _dbus_return_val_if_fail (connection != NULL, FALSE);
03100
03101 if (!_dbus_type_is_valid(type))
03102 return FALSE;
03103
03104 if (type != DBUS_TYPE_UNIX_FD)
03105 return TRUE;
03106
03107 #ifdef HAVE_UNIX_FD_PASSING
03108 {
03109 dbus_bool_t b;
03110
03111 CONNECTION_LOCK(connection);
03112 b = _dbus_transport_can_pass_unix_fd(connection->transport);
03113 CONNECTION_UNLOCK(connection);
03114
03115 return b;
03116 }
03117 #endif
03118
03119 return FALSE;
03120 }
03121
03135 void
03136 dbus_connection_set_exit_on_disconnect (DBusConnection *connection,
03137 dbus_bool_t exit_on_disconnect)
03138 {
03139 _dbus_return_if_fail (connection != NULL);
03140
03141 CONNECTION_LOCK (connection);
03142 connection->exit_on_disconnect = exit_on_disconnect != FALSE;
03143 CONNECTION_UNLOCK (connection);
03144 }
03145
03155 DBusPreallocatedSend*
03156 dbus_connection_preallocate_send (DBusConnection *connection)
03157 {
03158 DBusPreallocatedSend *preallocated;
03159
03160 _dbus_return_val_if_fail (connection != NULL, NULL);
03161
03162 CONNECTION_LOCK (connection);
03163
03164 preallocated =
03165 _dbus_connection_preallocate_send_unlocked (connection);
03166
03167 CONNECTION_UNLOCK (connection);
03168
03169 return preallocated;
03170 }
03171
03181 void
03182 dbus_connection_free_preallocated_send (DBusConnection *connection,
03183 DBusPreallocatedSend *preallocated)
03184 {
03185 _dbus_return_if_fail (connection != NULL);
03186 _dbus_return_if_fail (preallocated != NULL);
03187 _dbus_return_if_fail (connection == preallocated->connection);
03188
03189 _dbus_list_free_link (preallocated->queue_link);
03190 _dbus_counter_unref (preallocated->counter_link->data);
03191 _dbus_list_free_link (preallocated->counter_link);
03192 dbus_free (preallocated);
03193 }
03194
03207 void
03208 dbus_connection_send_preallocated (DBusConnection *connection,
03209 DBusPreallocatedSend *preallocated,
03210 DBusMessage *message,
03211 dbus_uint32_t *client_serial)
03212 {
03213 _dbus_return_if_fail (connection != NULL);
03214 _dbus_return_if_fail (preallocated != NULL);
03215 _dbus_return_if_fail (message != NULL);
03216 _dbus_return_if_fail (preallocated->connection == connection);
03217 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
03218 dbus_message_get_member (message) != NULL);
03219 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
03220 (dbus_message_get_interface (message) != NULL &&
03221 dbus_message_get_member (message) != NULL));
03222
03223 CONNECTION_LOCK (connection);
03224
03225 #ifdef HAVE_UNIX_FD_PASSING
03226
03227 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03228 message->n_unix_fds > 0)
03229 {
03230
03231
03232
03233 CONNECTION_UNLOCK (connection);
03234 return;
03235 }
03236
03237 #endif
03238
03239 _dbus_connection_send_preallocated_and_unlock (connection,
03240 preallocated,
03241 message, client_serial);
03242 }
03243
03244 static dbus_bool_t
03245 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
03246 DBusMessage *message,
03247 dbus_uint32_t *client_serial)
03248 {
03249 DBusPreallocatedSend *preallocated;
03250
03251 _dbus_assert (connection != NULL);
03252 _dbus_assert (message != NULL);
03253
03254 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
03255 if (preallocated == NULL)
03256 return FALSE;
03257
03258 _dbus_connection_send_preallocated_unlocked_no_update (connection,
03259 preallocated,
03260 message,
03261 client_serial);
03262 return TRUE;
03263 }
03264
03292 dbus_bool_t
03293 dbus_connection_send (DBusConnection *connection,
03294 DBusMessage *message,
03295 dbus_uint32_t *serial)
03296 {
03297 _dbus_return_val_if_fail (connection != NULL, FALSE);
03298 _dbus_return_val_if_fail (message != NULL, FALSE);
03299
03300 CONNECTION_LOCK (connection);
03301
03302 #ifdef HAVE_UNIX_FD_PASSING
03303
03304 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03305 message->n_unix_fds > 0)
03306 {
03307
03308
03309
03310 CONNECTION_UNLOCK (connection);
03311 return FALSE;
03312 }
03313
03314 #endif
03315
03316 return _dbus_connection_send_and_unlock (connection,
03317 message,
03318 serial);
03319 }
03320
03321 static dbus_bool_t
03322 reply_handler_timeout (void *data)
03323 {
03324 DBusConnection *connection;
03325 DBusDispatchStatus status;
03326 DBusPendingCall *pending = data;
03327
03328 connection = _dbus_pending_call_get_connection_and_lock (pending);
03329
03330 _dbus_pending_call_queue_timeout_error_unlocked (pending,
03331 connection);
03332 _dbus_connection_remove_timeout_unlocked (connection,
03333 _dbus_pending_call_get_timeout_unlocked (pending));
03334 _dbus_pending_call_set_timeout_added_unlocked (pending, FALSE);
03335
03336 _dbus_verbose ("middle\n");
03337 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03338
03339
03340 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03341
03342 return TRUE;
03343 }
03344
03384 dbus_bool_t
03385 dbus_connection_send_with_reply (DBusConnection *connection,
03386 DBusMessage *message,
03387 DBusPendingCall **pending_return,
03388 int timeout_milliseconds)
03389 {
03390 DBusPendingCall *pending;
03391 dbus_int32_t serial = -1;
03392 DBusDispatchStatus status;
03393
03394 _dbus_return_val_if_fail (connection != NULL, FALSE);
03395 _dbus_return_val_if_fail (message != NULL, FALSE);
03396 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03397
03398 if (pending_return)
03399 *pending_return = NULL;
03400
03401 CONNECTION_LOCK (connection);
03402
03403 #ifdef HAVE_UNIX_FD_PASSING
03404
03405 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03406 message->n_unix_fds > 0)
03407 {
03408
03409
03410
03411
03412 CONNECTION_UNLOCK (connection);
03413 return TRUE;
03414 }
03415
03416 #endif
03417
03418 if (!_dbus_connection_get_is_connected_unlocked (connection))
03419 {
03420 CONNECTION_UNLOCK (connection);
03421
03422 return TRUE;
03423 }
03424
03425 pending = _dbus_pending_call_new_unlocked (connection,
03426 timeout_milliseconds,
03427 reply_handler_timeout);
03428
03429 if (pending == NULL)
03430 {
03431 CONNECTION_UNLOCK (connection);
03432 return FALSE;
03433 }
03434
03435
03436 serial = dbus_message_get_serial (message);
03437 if (serial == 0)
03438 {
03439 serial = _dbus_connection_get_next_client_serial (connection);
03440 dbus_message_set_serial (message, serial);
03441 }
03442
03443 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
03444 goto error;
03445
03446
03447
03448
03449
03450 if (!_dbus_connection_attach_pending_call_unlocked (connection,
03451 pending))
03452 goto error;
03453
03454 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
03455 {
03456 _dbus_connection_detach_pending_call_and_unlock (connection,
03457 pending);
03458 goto error_unlocked;
03459 }
03460
03461 if (pending_return)
03462 *pending_return = pending;
03463 else
03464 {
03465 _dbus_connection_detach_pending_call_unlocked (connection, pending);
03466
03467
03468
03469 }
03470
03471 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03472
03473
03474 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03475
03476 if (pending_return == NULL)
03477 dbus_pending_call_unref (pending);
03478
03479 return TRUE;
03480
03481 error:
03482 CONNECTION_UNLOCK (connection);
03483 error_unlocked:
03484 dbus_pending_call_unref (pending);
03485 return FALSE;
03486 }
03487
03518 DBusMessage*
03519 dbus_connection_send_with_reply_and_block (DBusConnection *connection,
03520 DBusMessage *message,
03521 int timeout_milliseconds,
03522 DBusError *error)
03523 {
03524 DBusMessage *reply;
03525 DBusPendingCall *pending;
03526
03527 _dbus_return_val_if_fail (connection != NULL, NULL);
03528 _dbus_return_val_if_fail (message != NULL, NULL);
03529 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
03530 _dbus_return_val_if_error_is_set (error, NULL);
03531
03532 #ifdef HAVE_UNIX_FD_PASSING
03533
03534 CONNECTION_LOCK (connection);
03535 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
03536 message->n_unix_fds > 0)
03537 {
03538 CONNECTION_UNLOCK (connection);
03539 dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection.");
03540 return NULL;
03541 }
03542 CONNECTION_UNLOCK (connection);
03543
03544 #endif
03545
03546 if (!dbus_connection_send_with_reply (connection, message,
03547 &pending, timeout_milliseconds))
03548 {
03549 _DBUS_SET_OOM (error);
03550 return NULL;
03551 }
03552
03553 if (pending == NULL)
03554 {
03555 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
03556 return NULL;
03557 }
03558
03559 dbus_pending_call_block (pending);
03560
03561 reply = dbus_pending_call_steal_reply (pending);
03562 dbus_pending_call_unref (pending);
03563
03564
03565
03566
03567 _dbus_assert (reply != NULL);
03568
03569 if (dbus_set_error_from_message (error, reply))
03570 {
03571 dbus_message_unref (reply);
03572 return NULL;
03573 }
03574 else
03575 return reply;
03576 }
03577
03586 static DBusDispatchStatus
03587 _dbus_connection_flush_unlocked (DBusConnection *connection)
03588 {
03589
03590
03591
03592
03593
03594 DBusDispatchStatus status;
03595
03596 HAVE_LOCK_CHECK (connection);
03597
03598 while (connection->n_outgoing > 0 &&
03599 _dbus_connection_get_is_connected_unlocked (connection))
03600 {
03601 _dbus_verbose ("doing iteration in\n");
03602 HAVE_LOCK_CHECK (connection);
03603 _dbus_connection_do_iteration_unlocked (connection,
03604 NULL,
03605 DBUS_ITERATION_DO_READING |
03606 DBUS_ITERATION_DO_WRITING |
03607 DBUS_ITERATION_BLOCK,
03608 -1);
03609 }
03610
03611 HAVE_LOCK_CHECK (connection);
03612 _dbus_verbose ("middle\n");
03613 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03614
03615 HAVE_LOCK_CHECK (connection);
03616 return status;
03617 }
03618
03624 void
03625 dbus_connection_flush (DBusConnection *connection)
03626 {
03627
03628
03629
03630
03631
03632 DBusDispatchStatus status;
03633
03634 _dbus_return_if_fail (connection != NULL);
03635
03636 CONNECTION_LOCK (connection);
03637
03638 status = _dbus_connection_flush_unlocked (connection);
03639
03640 HAVE_LOCK_CHECK (connection);
03641
03642 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03643
03644 _dbus_verbose ("end\n");
03645 }
03646
03657 static dbus_bool_t
03658 _dbus_connection_read_write_dispatch (DBusConnection *connection,
03659 int timeout_milliseconds,
03660 dbus_bool_t dispatch)
03661 {
03662 DBusDispatchStatus dstatus;
03663 dbus_bool_t progress_possible;
03664
03665
03666
03667
03668
03669 dbus_connection_ref (connection);
03670 dstatus = dbus_connection_get_dispatch_status (connection);
03671
03672 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
03673 {
03674 _dbus_verbose ("doing dispatch\n");
03675 dbus_connection_dispatch (connection);
03676 CONNECTION_LOCK (connection);
03677 }
03678 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
03679 {
03680 _dbus_verbose ("pausing for memory\n");
03681 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
03682 CONNECTION_LOCK (connection);
03683 }
03684 else
03685 {
03686 CONNECTION_LOCK (connection);
03687 if (_dbus_connection_get_is_connected_unlocked (connection))
03688 {
03689 _dbus_verbose ("doing iteration\n");
03690 _dbus_connection_do_iteration_unlocked (connection,
03691 NULL,
03692 DBUS_ITERATION_DO_READING |
03693 DBUS_ITERATION_DO_WRITING |
03694 DBUS_ITERATION_BLOCK,
03695 timeout_milliseconds);
03696 }
03697 }
03698
03699 HAVE_LOCK_CHECK (connection);
03700
03701
03702
03703
03704 if (dispatch)
03705 progress_possible = connection->n_incoming != 0 ||
03706 connection->disconnect_message_link != NULL;
03707 else
03708 progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
03709
03710 CONNECTION_UNLOCK (connection);
03711
03712 dbus_connection_unref (connection);
03713
03714 return progress_possible;
03715 }
03716
03717
03752 dbus_bool_t
03753 dbus_connection_read_write_dispatch (DBusConnection *connection,
03754 int timeout_milliseconds)
03755 {
03756 _dbus_return_val_if_fail (connection != NULL, FALSE);
03757 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03758 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
03759 }
03760
03784 dbus_bool_t
03785 dbus_connection_read_write (DBusConnection *connection,
03786 int timeout_milliseconds)
03787 {
03788 _dbus_return_val_if_fail (connection != NULL, FALSE);
03789 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
03790 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
03791 }
03792
03793
03794
03795
03796
03797
03798 static void
03799 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
03800 DBusMessage *head_of_queue)
03801 {
03802 HAVE_LOCK_CHECK (connection);
03803
03804
03805 if (connection->disconnect_message_link == NULL &&
03806 dbus_message_is_signal (head_of_queue,
03807 DBUS_INTERFACE_LOCAL,
03808 "Disconnected"))
03809 {
03810 connection->disconnected_message_arrived = TRUE;
03811 }
03812 }
03813
03833 DBusMessage*
03834 dbus_connection_borrow_message (DBusConnection *connection)
03835 {
03836 DBusDispatchStatus status;
03837 DBusMessage *message;
03838
03839 _dbus_return_val_if_fail (connection != NULL, NULL);
03840
03841 _dbus_verbose ("start\n");
03842
03843
03844
03845
03846 status = dbus_connection_get_dispatch_status (connection);
03847 if (status != DBUS_DISPATCH_DATA_REMAINS)
03848 return NULL;
03849
03850 CONNECTION_LOCK (connection);
03851
03852 _dbus_connection_acquire_dispatch (connection);
03853
03854
03855 _dbus_assert (connection->message_borrowed == NULL);
03856
03857 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
03858
03859 message = connection->message_borrowed;
03860
03861 check_disconnected_message_arrived_unlocked (connection, message);
03862
03863
03864 if (message == NULL)
03865 _dbus_connection_release_dispatch (connection);
03866
03867 CONNECTION_UNLOCK (connection);
03868
03869
03870
03871 return message;
03872 }
03873
03882 void
03883 dbus_connection_return_message (DBusConnection *connection,
03884 DBusMessage *message)
03885 {
03886 DBusDispatchStatus status;
03887
03888 _dbus_return_if_fail (connection != NULL);
03889 _dbus_return_if_fail (message != NULL);
03890 _dbus_return_if_fail (message == connection->message_borrowed);
03891 _dbus_return_if_fail (connection->dispatch_acquired);
03892
03893 CONNECTION_LOCK (connection);
03894
03895 _dbus_assert (message == connection->message_borrowed);
03896
03897 connection->message_borrowed = NULL;
03898
03899 _dbus_connection_release_dispatch (connection);
03900
03901 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03902 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03903 }
03904
03914 void
03915 dbus_connection_steal_borrowed_message (DBusConnection *connection,
03916 DBusMessage *message)
03917 {
03918 DBusMessage *pop_message;
03919 DBusDispatchStatus status;
03920
03921 _dbus_return_if_fail (connection != NULL);
03922 _dbus_return_if_fail (message != NULL);
03923 _dbus_return_if_fail (message == connection->message_borrowed);
03924 _dbus_return_if_fail (connection->dispatch_acquired);
03925
03926 CONNECTION_LOCK (connection);
03927
03928 _dbus_assert (message == connection->message_borrowed);
03929
03930 pop_message = _dbus_list_pop_first (&connection->incoming_messages);
03931 _dbus_assert (message == pop_message);
03932
03933 connection->n_incoming -= 1;
03934
03935 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
03936 message, connection->n_incoming);
03937
03938 connection->message_borrowed = NULL;
03939
03940 _dbus_connection_release_dispatch (connection);
03941
03942 status = _dbus_connection_get_dispatch_status_unlocked (connection);
03943 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
03944 }
03945
03946
03947
03948
03949 static DBusList*
03950 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
03951 {
03952 HAVE_LOCK_CHECK (connection);
03953
03954 _dbus_assert (connection->message_borrowed == NULL);
03955
03956 if (connection->n_incoming > 0)
03957 {
03958 DBusList *link;
03959
03960 link = _dbus_list_pop_first_link (&connection->incoming_messages);
03961 connection->n_incoming -= 1;
03962
03963 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
03964 link->data,
03965 dbus_message_type_to_string (dbus_message_get_type (link->data)),
03966 dbus_message_get_path (link->data) ?
03967 dbus_message_get_path (link->data) :
03968 "no path",
03969 dbus_message_get_interface (link->data) ?
03970 dbus_message_get_interface (link->data) :
03971 "no interface",
03972 dbus_message_get_member (link->data) ?
03973 dbus_message_get_member (link->data) :
03974 "no member",
03975 dbus_message_get_signature (link->data),
03976 connection, connection->n_incoming);
03977
03978 check_disconnected_message_arrived_unlocked (connection, link->data);
03979
03980 return link;
03981 }
03982 else
03983 return NULL;
03984 }
03985
03986
03987
03988
03989 static DBusMessage*
03990 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
03991 {
03992 DBusList *link;
03993
03994 HAVE_LOCK_CHECK (connection);
03995
03996 link = _dbus_connection_pop_message_link_unlocked (connection);
03997
03998 if (link != NULL)
03999 {
04000 DBusMessage *message;
04001
04002 message = link->data;
04003
04004 _dbus_list_free_link (link);
04005
04006 return message;
04007 }
04008 else
04009 return NULL;
04010 }
04011
04012 static void
04013 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
04014 DBusList *message_link)
04015 {
04016 HAVE_LOCK_CHECK (connection);
04017
04018 _dbus_assert (message_link != NULL);
04019
04020 _dbus_assert (connection->message_borrowed == NULL);
04021
04022 _dbus_assert (connection->dispatch_acquired);
04023
04024 _dbus_list_prepend_link (&connection->incoming_messages,
04025 message_link);
04026 connection->n_incoming += 1;
04027
04028 _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n",
04029 message_link->data,
04030 dbus_message_type_to_string (dbus_message_get_type (message_link->data)),
04031 dbus_message_get_interface (message_link->data) ?
04032 dbus_message_get_interface (message_link->data) :
04033 "no interface",
04034 dbus_message_get_member (message_link->data) ?
04035 dbus_message_get_member (message_link->data) :
04036 "no member",
04037 dbus_message_get_signature (message_link->data),
04038 connection, connection->n_incoming);
04039 }
04040
04060 DBusMessage*
04061 dbus_connection_pop_message (DBusConnection *connection)
04062 {
04063 DBusMessage *message;
04064 DBusDispatchStatus status;
04065
04066 _dbus_verbose ("start\n");
04067
04068
04069
04070
04071 status = dbus_connection_get_dispatch_status (connection);
04072 if (status != DBUS_DISPATCH_DATA_REMAINS)
04073 return NULL;
04074
04075 CONNECTION_LOCK (connection);
04076 _dbus_connection_acquire_dispatch (connection);
04077 HAVE_LOCK_CHECK (connection);
04078
04079 message = _dbus_connection_pop_message_unlocked (connection);
04080
04081 _dbus_verbose ("Returning popped message %p\n", message);
04082
04083 _dbus_connection_release_dispatch (connection);
04084
04085 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04086 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04087
04088 return message;
04089 }
04090
04098 static void
04099 _dbus_connection_acquire_dispatch (DBusConnection *connection)
04100 {
04101 HAVE_LOCK_CHECK (connection);
04102
04103 _dbus_connection_ref_unlocked (connection);
04104 CONNECTION_UNLOCK (connection);
04105
04106 _dbus_verbose ("locking dispatch_mutex\n");
04107 _dbus_mutex_lock (connection->dispatch_mutex);
04108
04109 while (connection->dispatch_acquired)
04110 {
04111 _dbus_verbose ("waiting for dispatch to be acquirable\n");
04112 _dbus_condvar_wait (connection->dispatch_cond,
04113 connection->dispatch_mutex);
04114 }
04115
04116 _dbus_assert (!connection->dispatch_acquired);
04117
04118 connection->dispatch_acquired = TRUE;
04119
04120 _dbus_verbose ("unlocking dispatch_mutex\n");
04121 _dbus_mutex_unlock (connection->dispatch_mutex);
04122
04123 CONNECTION_LOCK (connection);
04124 _dbus_connection_unref_unlocked (connection);
04125 }
04126
04134 static void
04135 _dbus_connection_release_dispatch (DBusConnection *connection)
04136 {
04137 HAVE_LOCK_CHECK (connection);
04138
04139 _dbus_verbose ("locking dispatch_mutex\n");
04140 _dbus_mutex_lock (connection->dispatch_mutex);
04141
04142 _dbus_assert (connection->dispatch_acquired);
04143
04144 connection->dispatch_acquired = FALSE;
04145 _dbus_condvar_wake_one (connection->dispatch_cond);
04146
04147 _dbus_verbose ("unlocking dispatch_mutex\n");
04148 _dbus_mutex_unlock (connection->dispatch_mutex);
04149 }
04150
04151 static void
04152 _dbus_connection_failed_pop (DBusConnection *connection,
04153 DBusList *message_link)
04154 {
04155 _dbus_list_prepend_link (&connection->incoming_messages,
04156 message_link);
04157 connection->n_incoming += 1;
04158 }
04159
04160
04161 static void
04162 notify_disconnected_unlocked (DBusConnection *connection)
04163 {
04164 HAVE_LOCK_CHECK (connection);
04165
04166
04167
04168
04169
04170
04171
04172 _dbus_bus_notify_shared_connection_disconnected_unlocked (connection);
04173
04174
04175
04176
04177
04178 if (connection->n_outgoing > 0)
04179 {
04180 DBusList *link;
04181
04182 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
04183 connection->n_outgoing);
04184
04185 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
04186 {
04187 _dbus_connection_message_sent (connection, link->data);
04188 }
04189 }
04190 }
04191
04192
04193 static DBusDispatchStatus
04194 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
04195 {
04196 HAVE_LOCK_CHECK (connection);
04197
04198 if (connection->disconnect_message_link != NULL)
04199 {
04200 _dbus_verbose ("Sending disconnect message\n");
04201
04202
04203
04204
04205 connection_timeout_and_complete_all_pending_calls_unlocked (connection);
04206
04207
04208
04209
04210 _dbus_connection_queue_synthesized_message_link (connection,
04211 connection->disconnect_message_link);
04212 connection->disconnect_message_link = NULL;
04213
04214 return DBUS_DISPATCH_DATA_REMAINS;
04215 }
04216
04217 return DBUS_DISPATCH_COMPLETE;
04218 }
04219
04220 static DBusDispatchStatus
04221 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
04222 {
04223 HAVE_LOCK_CHECK (connection);
04224
04225 if (connection->n_incoming > 0)
04226 return DBUS_DISPATCH_DATA_REMAINS;
04227 else if (!_dbus_transport_queue_messages (connection->transport))
04228 return DBUS_DISPATCH_NEED_MEMORY;
04229 else
04230 {
04231 DBusDispatchStatus status;
04232 dbus_bool_t is_connected;
04233
04234 status = _dbus_transport_get_dispatch_status (connection->transport);
04235 is_connected = _dbus_transport_get_is_connected (connection->transport);
04236
04237 _dbus_verbose ("dispatch status = %s is_connected = %d\n",
04238 DISPATCH_STATUS_NAME (status), is_connected);
04239
04240 if (!is_connected)
04241 {
04242
04243
04244
04245
04246
04247
04248 notify_disconnected_unlocked (connection);
04249
04250
04251
04252
04253
04254
04255 if (status == DBUS_DISPATCH_COMPLETE)
04256 status = notify_disconnected_and_dispatch_complete_unlocked (connection);
04257 }
04258
04259 if (status != DBUS_DISPATCH_COMPLETE)
04260 return status;
04261 else if (connection->n_incoming > 0)
04262 return DBUS_DISPATCH_DATA_REMAINS;
04263 else
04264 return DBUS_DISPATCH_COMPLETE;
04265 }
04266 }
04267
04268 static void
04269 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
04270 DBusDispatchStatus new_status)
04271 {
04272 dbus_bool_t changed;
04273 DBusDispatchStatusFunction function;
04274 void *data;
04275
04276 HAVE_LOCK_CHECK (connection);
04277
04278 _dbus_connection_ref_unlocked (connection);
04279
04280 changed = new_status != connection->last_dispatch_status;
04281
04282 connection->last_dispatch_status = new_status;
04283
04284 function = connection->dispatch_status_function;
04285 data = connection->dispatch_status_data;
04286
04287 if (connection->disconnected_message_arrived &&
04288 !connection->disconnected_message_processed)
04289 {
04290 connection->disconnected_message_processed = TRUE;
04291
04292
04293
04294
04295
04296 connection_forget_shared_unlocked (connection);
04297
04298 if (connection->exit_on_disconnect)
04299 {
04300 CONNECTION_UNLOCK (connection);
04301
04302 _dbus_verbose ("Exiting on Disconnected signal\n");
04303 _dbus_exit (1);
04304 _dbus_assert_not_reached ("Call to exit() returned");
04305 }
04306 }
04307
04308
04309 CONNECTION_UNLOCK (connection);
04310
04311 if (changed && function)
04312 {
04313 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
04314 connection, new_status,
04315 DISPATCH_STATUS_NAME (new_status));
04316 (* function) (connection, new_status, data);
04317 }
04318
04319 dbus_connection_unref (connection);
04320 }
04321
04347 DBusDispatchStatus
04348 dbus_connection_get_dispatch_status (DBusConnection *connection)
04349 {
04350 DBusDispatchStatus status;
04351
04352 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04353
04354 _dbus_verbose ("start\n");
04355
04356 CONNECTION_LOCK (connection);
04357
04358 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04359
04360 CONNECTION_UNLOCK (connection);
04361
04362 return status;
04363 }
04364
04368 static DBusHandlerResult
04369 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
04370 DBusMessage *message)
04371 {
04372 if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
04373 {
04374
04375 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04376 }
04377 else if (dbus_message_is_method_call (message,
04378 DBUS_INTERFACE_PEER,
04379 "Ping"))
04380 {
04381 DBusMessage *ret;
04382 dbus_bool_t sent;
04383
04384 ret = dbus_message_new_method_return (message);
04385 if (ret == NULL)
04386 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04387
04388 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04389
04390 dbus_message_unref (ret);
04391
04392 if (!sent)
04393 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04394
04395 return DBUS_HANDLER_RESULT_HANDLED;
04396 }
04397 else if (dbus_message_is_method_call (message,
04398 DBUS_INTERFACE_PEER,
04399 "GetMachineId"))
04400 {
04401 DBusMessage *ret;
04402 dbus_bool_t sent;
04403 DBusString uuid;
04404
04405 ret = dbus_message_new_method_return (message);
04406 if (ret == NULL)
04407 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04408
04409 sent = FALSE;
04410 _dbus_string_init (&uuid);
04411 if (_dbus_get_local_machine_uuid_encoded (&uuid))
04412 {
04413 const char *v_STRING = _dbus_string_get_const_data (&uuid);
04414 if (dbus_message_append_args (ret,
04415 DBUS_TYPE_STRING, &v_STRING,
04416 DBUS_TYPE_INVALID))
04417 {
04418 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04419 }
04420 }
04421 _dbus_string_free (&uuid);
04422
04423 dbus_message_unref (ret);
04424
04425 if (!sent)
04426 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04427
04428 return DBUS_HANDLER_RESULT_HANDLED;
04429 }
04430 else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
04431 {
04432
04433
04434
04435
04436
04437 DBusMessage *ret;
04438 dbus_bool_t sent;
04439
04440 ret = dbus_message_new_error (message,
04441 DBUS_ERROR_UNKNOWN_METHOD,
04442 "Unknown method invoked on org.freedesktop.DBus.Peer interface");
04443 if (ret == NULL)
04444 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04445
04446 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
04447
04448 dbus_message_unref (ret);
04449
04450 if (!sent)
04451 return DBUS_HANDLER_RESULT_NEED_MEMORY;
04452
04453 return DBUS_HANDLER_RESULT_HANDLED;
04454 }
04455 else
04456 {
04457 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04458 }
04459 }
04460
04467 static DBusHandlerResult
04468 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
04469 DBusMessage *message)
04470 {
04471
04472
04473
04474 return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
04475 }
04476
04519 DBusDispatchStatus
04520 dbus_connection_dispatch (DBusConnection *connection)
04521 {
04522 DBusMessage *message;
04523 DBusList *link, *filter_list_copy, *message_link;
04524 DBusHandlerResult result;
04525 DBusPendingCall *pending;
04526 dbus_int32_t reply_serial;
04527 DBusDispatchStatus status;
04528
04529 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
04530
04531 _dbus_verbose ("\n");
04532
04533 CONNECTION_LOCK (connection);
04534 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04535 if (status != DBUS_DISPATCH_DATA_REMAINS)
04536 {
04537
04538 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04539 return status;
04540 }
04541
04542
04543
04544
04545 _dbus_connection_ref_unlocked (connection);
04546
04547 _dbus_connection_acquire_dispatch (connection);
04548 HAVE_LOCK_CHECK (connection);
04549
04550 message_link = _dbus_connection_pop_message_link_unlocked (connection);
04551 if (message_link == NULL)
04552 {
04553
04554
04555 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
04556
04557 _dbus_connection_release_dispatch (connection);
04558
04559 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04560
04561 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04562
04563 dbus_connection_unref (connection);
04564
04565 return status;
04566 }
04567
04568 message = message_link->data;
04569
04570 _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n",
04571 message,
04572 dbus_message_type_to_string (dbus_message_get_type (message)),
04573 dbus_message_get_interface (message) ?
04574 dbus_message_get_interface (message) :
04575 "no interface",
04576 dbus_message_get_member (message) ?
04577 dbus_message_get_member (message) :
04578 "no member",
04579 dbus_message_get_signature (message));
04580
04581 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
04582
04583
04584
04585
04586
04587
04588
04589
04590 reply_serial = dbus_message_get_reply_serial (message);
04591 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
04592 reply_serial);
04593 if (pending)
04594 {
04595 _dbus_verbose ("Dispatching a pending reply\n");
04596 complete_pending_call_and_unlock (connection, pending, message);
04597 pending = NULL;
04598
04599 CONNECTION_LOCK (connection);
04600 _dbus_verbose ("pending call completed in dispatch\n");
04601 result = DBUS_HANDLER_RESULT_HANDLED;
04602 goto out;
04603 }
04604
04605 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
04606 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04607 goto out;
04608
04609 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
04610 {
04611 _dbus_connection_release_dispatch (connection);
04612 HAVE_LOCK_CHECK (connection);
04613
04614 _dbus_connection_failed_pop (connection, message_link);
04615
04616
04617 _dbus_connection_update_dispatch_status_and_unlock (connection,
04618 DBUS_DISPATCH_NEED_MEMORY);
04619
04620 if (pending)
04621 dbus_pending_call_unref (pending);
04622 dbus_connection_unref (connection);
04623
04624 return DBUS_DISPATCH_NEED_MEMORY;
04625 }
04626
04627 _dbus_list_foreach (&filter_list_copy,
04628 (DBusForeachFunction)_dbus_message_filter_ref,
04629 NULL);
04630
04631
04632
04633
04634 CONNECTION_UNLOCK (connection);
04635
04636 link = _dbus_list_get_first_link (&filter_list_copy);
04637 while (link != NULL)
04638 {
04639 DBusMessageFilter *filter = link->data;
04640 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
04641
04642 if (filter->function == NULL)
04643 {
04644 _dbus_verbose (" filter was removed in a callback function\n");
04645 link = next;
04646 continue;
04647 }
04648
04649 _dbus_verbose (" running filter on message %p\n", message);
04650 result = (* filter->function) (connection, message, filter->user_data);
04651
04652 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04653 break;
04654
04655 link = next;
04656 }
04657
04658 _dbus_list_foreach (&filter_list_copy,
04659 (DBusForeachFunction)_dbus_message_filter_unref,
04660 NULL);
04661 _dbus_list_clear (&filter_list_copy);
04662
04663 CONNECTION_LOCK (connection);
04664
04665 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04666 {
04667 _dbus_verbose ("No memory\n");
04668 goto out;
04669 }
04670 else if (result == DBUS_HANDLER_RESULT_HANDLED)
04671 {
04672 _dbus_verbose ("filter handled message in dispatch\n");
04673 goto out;
04674 }
04675
04676
04677
04678
04679 _dbus_verbose (" running object path dispatch on message %p (%s %s %s '%s')\n",
04680 message,
04681 dbus_message_type_to_string (dbus_message_get_type (message)),
04682 dbus_message_get_interface (message) ?
04683 dbus_message_get_interface (message) :
04684 "no interface",
04685 dbus_message_get_member (message) ?
04686 dbus_message_get_member (message) :
04687 "no member",
04688 dbus_message_get_signature (message));
04689
04690 HAVE_LOCK_CHECK (connection);
04691 result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
04692 message);
04693
04694 CONNECTION_LOCK (connection);
04695
04696 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
04697 {
04698 _dbus_verbose ("object tree handled message in dispatch\n");
04699 goto out;
04700 }
04701
04702 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
04703 {
04704 DBusMessage *reply;
04705 DBusString str;
04706 DBusPreallocatedSend *preallocated;
04707
04708 _dbus_verbose (" sending error %s\n",
04709 DBUS_ERROR_UNKNOWN_METHOD);
04710
04711 if (!_dbus_string_init (&str))
04712 {
04713 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04714 _dbus_verbose ("no memory for error string in dispatch\n");
04715 goto out;
04716 }
04717
04718 if (!_dbus_string_append_printf (&str,
04719 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
04720 dbus_message_get_member (message),
04721 dbus_message_get_signature (message),
04722 dbus_message_get_interface (message)))
04723 {
04724 _dbus_string_free (&str);
04725 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04726 _dbus_verbose ("no memory for error string in dispatch\n");
04727 goto out;
04728 }
04729
04730 reply = dbus_message_new_error (message,
04731 DBUS_ERROR_UNKNOWN_METHOD,
04732 _dbus_string_get_const_data (&str));
04733 _dbus_string_free (&str);
04734
04735 if (reply == NULL)
04736 {
04737 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04738 _dbus_verbose ("no memory for error reply in dispatch\n");
04739 goto out;
04740 }
04741
04742 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
04743
04744 if (preallocated == NULL)
04745 {
04746 dbus_message_unref (reply);
04747 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
04748 _dbus_verbose ("no memory for error send in dispatch\n");
04749 goto out;
04750 }
04751
04752 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
04753 reply, NULL);
04754
04755 dbus_message_unref (reply);
04756
04757 result = DBUS_HANDLER_RESULT_HANDLED;
04758 }
04759
04760 _dbus_verbose (" done dispatching %p (%s %s %s '%s') on connection %p\n", message,
04761 dbus_message_type_to_string (dbus_message_get_type (message)),
04762 dbus_message_get_interface (message) ?
04763 dbus_message_get_interface (message) :
04764 "no interface",
04765 dbus_message_get_member (message) ?
04766 dbus_message_get_member (message) :
04767 "no member",
04768 dbus_message_get_signature (message),
04769 connection);
04770
04771 out:
04772 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
04773 {
04774 _dbus_verbose ("out of memory\n");
04775
04776
04777
04778
04779
04780 _dbus_connection_putback_message_link_unlocked (connection,
04781 message_link);
04782 }
04783 else
04784 {
04785 _dbus_verbose (" ... done dispatching\n");
04786
04787 _dbus_list_free_link (message_link);
04788 dbus_message_unref (message);
04789
04790
04791 }
04792
04793 _dbus_connection_release_dispatch (connection);
04794 HAVE_LOCK_CHECK (connection);
04795
04796 _dbus_verbose ("before final status update\n");
04797 status = _dbus_connection_get_dispatch_status_unlocked (connection);
04798
04799
04800 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
04801
04802 dbus_connection_unref (connection);
04803
04804 return status;
04805 }
04806
04868 dbus_bool_t
04869 dbus_connection_set_watch_functions (DBusConnection *connection,
04870 DBusAddWatchFunction add_function,
04871 DBusRemoveWatchFunction remove_function,
04872 DBusWatchToggledFunction toggled_function,
04873 void *data,
04874 DBusFreeFunction free_data_function)
04875 {
04876 dbus_bool_t retval;
04877
04878 _dbus_return_val_if_fail (connection != NULL, FALSE);
04879
04880 CONNECTION_LOCK (connection);
04881
04882 retval = _dbus_watch_list_set_functions (connection->watches,
04883 add_function, remove_function,
04884 toggled_function,
04885 data, free_data_function);
04886
04887 CONNECTION_UNLOCK (connection);
04888
04889 return retval;
04890 }
04891
04931 dbus_bool_t
04932 dbus_connection_set_timeout_functions (DBusConnection *connection,
04933 DBusAddTimeoutFunction add_function,
04934 DBusRemoveTimeoutFunction remove_function,
04935 DBusTimeoutToggledFunction toggled_function,
04936 void *data,
04937 DBusFreeFunction free_data_function)
04938 {
04939 dbus_bool_t retval;
04940
04941 _dbus_return_val_if_fail (connection != NULL, FALSE);
04942
04943 CONNECTION_LOCK (connection);
04944
04945 retval = _dbus_timeout_list_set_functions (connection->timeouts,
04946 add_function, remove_function,
04947 toggled_function,
04948 data, free_data_function);
04949
04950 CONNECTION_UNLOCK (connection);
04951
04952 return retval;
04953 }
04954
04969 void
04970 dbus_connection_set_wakeup_main_function (DBusConnection *connection,
04971 DBusWakeupMainFunction wakeup_main_function,
04972 void *data,
04973 DBusFreeFunction free_data_function)
04974 {
04975 void *old_data;
04976 DBusFreeFunction old_free_data;
04977
04978 _dbus_return_if_fail (connection != NULL);
04979
04980 CONNECTION_LOCK (connection);
04981 old_data = connection->wakeup_main_data;
04982 old_free_data = connection->free_wakeup_main_data;
04983
04984 connection->wakeup_main_function = wakeup_main_function;
04985 connection->wakeup_main_data = data;
04986 connection->free_wakeup_main_data = free_data_function;
04987
04988 CONNECTION_UNLOCK (connection);
04989
04990
04991 if (old_free_data)
04992 (*old_free_data) (old_data);
04993 }
04994
05015 void
05016 dbus_connection_set_dispatch_status_function (DBusConnection *connection,
05017 DBusDispatchStatusFunction function,
05018 void *data,
05019 DBusFreeFunction free_data_function)
05020 {
05021 void *old_data;
05022 DBusFreeFunction old_free_data;
05023
05024 _dbus_return_if_fail (connection != NULL);
05025
05026 CONNECTION_LOCK (connection);
05027 old_data = connection->dispatch_status_data;
05028 old_free_data = connection->free_dispatch_status_data;
05029
05030 connection->dispatch_status_function = function;
05031 connection->dispatch_status_data = data;
05032 connection->free_dispatch_status_data = free_data_function;
05033
05034 CONNECTION_UNLOCK (connection);
05035
05036
05037 if (old_free_data)
05038 (*old_free_data) (old_data);
05039 }
05040
05060 dbus_bool_t
05061 dbus_connection_get_unix_fd (DBusConnection *connection,
05062 int *fd)
05063 {
05064 _dbus_return_val_if_fail (connection != NULL, FALSE);
05065 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
05066
05067 #ifdef DBUS_WIN
05068
05069 return FALSE;
05070 #endif
05071
05072 return dbus_connection_get_socket(connection, fd);
05073 }
05074
05090 dbus_bool_t
05091 dbus_connection_get_socket(DBusConnection *connection,
05092 int *fd)
05093 {
05094 dbus_bool_t retval;
05095
05096 _dbus_return_val_if_fail (connection != NULL, FALSE);
05097 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
05098
05099 CONNECTION_LOCK (connection);
05100
05101 retval = _dbus_transport_get_socket_fd (connection->transport,
05102 fd);
05103
05104 CONNECTION_UNLOCK (connection);
05105
05106 return retval;
05107 }
05108
05109
05132 dbus_bool_t
05133 dbus_connection_get_unix_user (DBusConnection *connection,
05134 unsigned long *uid)
05135 {
05136 dbus_bool_t result;
05137
05138 _dbus_return_val_if_fail (connection != NULL, FALSE);
05139 _dbus_return_val_if_fail (uid != NULL, FALSE);
05140
05141 CONNECTION_LOCK (connection);
05142
05143 if (!_dbus_transport_get_is_authenticated (connection->transport))
05144 result = FALSE;
05145 else
05146 result = _dbus_transport_get_unix_user (connection->transport,
05147 uid);
05148
05149 #ifdef DBUS_WIN
05150 _dbus_assert (!result);
05151 #endif
05152
05153 CONNECTION_UNLOCK (connection);
05154
05155 return result;
05156 }
05157
05168 dbus_bool_t
05169 dbus_connection_get_unix_process_id (DBusConnection *connection,
05170 unsigned long *pid)
05171 {
05172 dbus_bool_t result;
05173
05174 _dbus_return_val_if_fail (connection != NULL, FALSE);
05175 _dbus_return_val_if_fail (pid != NULL, FALSE);
05176
05177 CONNECTION_LOCK (connection);
05178
05179 if (!_dbus_transport_get_is_authenticated (connection->transport))
05180 result = FALSE;
05181 else
05182 result = _dbus_transport_get_unix_process_id (connection->transport,
05183 pid);
05184
05185 CONNECTION_UNLOCK (connection);
05186
05187 return result;
05188 }
05189
05200 dbus_bool_t
05201 dbus_connection_get_adt_audit_session_data (DBusConnection *connection,
05202 void **data,
05203 dbus_int32_t *data_size)
05204 {
05205 dbus_bool_t result;
05206
05207 _dbus_return_val_if_fail (connection != NULL, FALSE);
05208 _dbus_return_val_if_fail (data != NULL, FALSE);
05209 _dbus_return_val_if_fail (data_size != NULL, FALSE);
05210
05211 CONNECTION_LOCK (connection);
05212
05213 if (!_dbus_transport_get_is_authenticated (connection->transport))
05214 result = FALSE;
05215 else
05216 result = _dbus_transport_get_adt_audit_session_data (connection->transport,
05217 data,
05218 data_size);
05219 CONNECTION_UNLOCK (connection);
05220
05221 return result;
05222 }
05223
05246 void
05247 dbus_connection_set_unix_user_function (DBusConnection *connection,
05248 DBusAllowUnixUserFunction function,
05249 void *data,
05250 DBusFreeFunction free_data_function)
05251 {
05252 void *old_data = NULL;
05253 DBusFreeFunction old_free_function = NULL;
05254
05255 _dbus_return_if_fail (connection != NULL);
05256
05257 CONNECTION_LOCK (connection);
05258 _dbus_transport_set_unix_user_function (connection->transport,
05259 function, data, free_data_function,
05260 &old_data, &old_free_function);
05261 CONNECTION_UNLOCK (connection);
05262
05263 if (old_free_function != NULL)
05264 (* old_free_function) (old_data);
05265 }
05266
05298 dbus_bool_t
05299 dbus_connection_get_windows_user (DBusConnection *connection,
05300 char **windows_sid_p)
05301 {
05302 dbus_bool_t result;
05303
05304 _dbus_return_val_if_fail (connection != NULL, FALSE);
05305 _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
05306
05307 CONNECTION_LOCK (connection);
05308
05309 if (!_dbus_transport_get_is_authenticated (connection->transport))
05310 result = FALSE;
05311 else
05312 result = _dbus_transport_get_windows_user (connection->transport,
05313 windows_sid_p);
05314
05315 #ifdef DBUS_UNIX
05316 _dbus_assert (!result);
05317 #endif
05318
05319 CONNECTION_UNLOCK (connection);
05320
05321 return result;
05322 }
05323
05345 void
05346 dbus_connection_set_windows_user_function (DBusConnection *connection,
05347 DBusAllowWindowsUserFunction function,
05348 void *data,
05349 DBusFreeFunction free_data_function)
05350 {
05351 void *old_data = NULL;
05352 DBusFreeFunction old_free_function = NULL;
05353
05354 _dbus_return_if_fail (connection != NULL);
05355
05356 CONNECTION_LOCK (connection);
05357 _dbus_transport_set_windows_user_function (connection->transport,
05358 function, data, free_data_function,
05359 &old_data, &old_free_function);
05360 CONNECTION_UNLOCK (connection);
05361
05362 if (old_free_function != NULL)
05363 (* old_free_function) (old_data);
05364 }
05365
05392 void
05393 dbus_connection_set_allow_anonymous (DBusConnection *connection,
05394 dbus_bool_t value)
05395 {
05396 _dbus_return_if_fail (connection != NULL);
05397
05398 CONNECTION_LOCK (connection);
05399 _dbus_transport_set_allow_anonymous (connection->transport, value);
05400 CONNECTION_UNLOCK (connection);
05401 }
05402
05420 void
05421 dbus_connection_set_route_peer_messages (DBusConnection *connection,
05422 dbus_bool_t value)
05423 {
05424 _dbus_return_if_fail (connection != NULL);
05425
05426 CONNECTION_LOCK (connection);
05427 connection->route_peer_messages = TRUE;
05428 CONNECTION_UNLOCK (connection);
05429 }
05430
05452 dbus_bool_t
05453 dbus_connection_add_filter (DBusConnection *connection,
05454 DBusHandleMessageFunction function,
05455 void *user_data,
05456 DBusFreeFunction free_data_function)
05457 {
05458 DBusMessageFilter *filter;
05459
05460 _dbus_return_val_if_fail (connection != NULL, FALSE);
05461 _dbus_return_val_if_fail (function != NULL, FALSE);
05462
05463 filter = dbus_new0 (DBusMessageFilter, 1);
05464 if (filter == NULL)
05465 return FALSE;
05466
05467 filter->refcount.value = 1;
05468
05469 CONNECTION_LOCK (connection);
05470
05471 if (!_dbus_list_append (&connection->filter_list,
05472 filter))
05473 {
05474 _dbus_message_filter_unref (filter);
05475 CONNECTION_UNLOCK (connection);
05476 return FALSE;
05477 }
05478
05479
05480
05481
05482
05483
05484 filter->function = function;
05485 filter->user_data = user_data;
05486 filter->free_user_data_function = free_data_function;
05487
05488 CONNECTION_UNLOCK (connection);
05489 return TRUE;
05490 }
05491
05504 void
05505 dbus_connection_remove_filter (DBusConnection *connection,
05506 DBusHandleMessageFunction function,
05507 void *user_data)
05508 {
05509 DBusList *link;
05510 DBusMessageFilter *filter;
05511
05512 _dbus_return_if_fail (connection != NULL);
05513 _dbus_return_if_fail (function != NULL);
05514
05515 CONNECTION_LOCK (connection);
05516
05517 filter = NULL;
05518
05519 link = _dbus_list_get_last_link (&connection->filter_list);
05520 while (link != NULL)
05521 {
05522 filter = link->data;
05523
05524 if (filter->function == function &&
05525 filter->user_data == user_data)
05526 {
05527 _dbus_list_remove_link (&connection->filter_list, link);
05528 filter->function = NULL;
05529
05530 break;
05531 }
05532
05533 link = _dbus_list_get_prev_link (&connection->filter_list, link);
05534 filter = NULL;
05535 }
05536
05537 CONNECTION_UNLOCK (connection);
05538
05539 #ifndef DBUS_DISABLE_CHECKS
05540 if (filter == NULL)
05541 {
05542 _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
05543 function, user_data);
05544 return;
05545 }
05546 #endif
05547
05548
05549 if (filter->free_user_data_function)
05550 (* filter->free_user_data_function) (filter->user_data);
05551
05552 filter->free_user_data_function = NULL;
05553 filter->user_data = NULL;
05554
05555 _dbus_message_filter_unref (filter);
05556 }
05557
05570 dbus_bool_t
05571 dbus_connection_try_register_object_path (DBusConnection *connection,
05572 const char *path,
05573 const DBusObjectPathVTable *vtable,
05574 void *user_data,
05575 DBusError *error)
05576 {
05577 char **decomposed_path;
05578 dbus_bool_t retval;
05579
05580 _dbus_return_val_if_fail (connection != NULL, FALSE);
05581 _dbus_return_val_if_fail (path != NULL, FALSE);
05582 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05583 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05584
05585 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05586 return FALSE;
05587
05588 CONNECTION_LOCK (connection);
05589
05590 retval = _dbus_object_tree_register (connection->objects,
05591 FALSE,
05592 (const char **) decomposed_path, vtable,
05593 user_data, error);
05594
05595 CONNECTION_UNLOCK (connection);
05596
05597 dbus_free_string_array (decomposed_path);
05598
05599 return retval;
05600 }
05601
05616 dbus_bool_t
05617 dbus_connection_register_object_path (DBusConnection *connection,
05618 const char *path,
05619 const DBusObjectPathVTable *vtable,
05620 void *user_data)
05621 {
05622 char **decomposed_path;
05623 dbus_bool_t retval;
05624 DBusError error = DBUS_ERROR_INIT;
05625
05626 _dbus_return_val_if_fail (connection != NULL, FALSE);
05627 _dbus_return_val_if_fail (path != NULL, FALSE);
05628 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05629 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05630
05631 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05632 return FALSE;
05633
05634 CONNECTION_LOCK (connection);
05635
05636 retval = _dbus_object_tree_register (connection->objects,
05637 FALSE,
05638 (const char **) decomposed_path, vtable,
05639 user_data, &error);
05640
05641 CONNECTION_UNLOCK (connection);
05642
05643 dbus_free_string_array (decomposed_path);
05644
05645 if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
05646 {
05647 _dbus_warn ("%s\n", error.message);
05648 dbus_error_free (&error);
05649 return FALSE;
05650 }
05651
05652 return retval;
05653 }
05654
05669 dbus_bool_t
05670 dbus_connection_try_register_fallback (DBusConnection *connection,
05671 const char *path,
05672 const DBusObjectPathVTable *vtable,
05673 void *user_data,
05674 DBusError *error)
05675 {
05676 char **decomposed_path;
05677 dbus_bool_t retval;
05678
05679 _dbus_return_val_if_fail (connection != NULL, FALSE);
05680 _dbus_return_val_if_fail (path != NULL, FALSE);
05681 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05682 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05683
05684 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05685 return FALSE;
05686
05687 CONNECTION_LOCK (connection);
05688
05689 retval = _dbus_object_tree_register (connection->objects,
05690 TRUE,
05691 (const char **) decomposed_path, vtable,
05692 user_data, error);
05693
05694 CONNECTION_UNLOCK (connection);
05695
05696 dbus_free_string_array (decomposed_path);
05697
05698 return retval;
05699 }
05700
05717 dbus_bool_t
05718 dbus_connection_register_fallback (DBusConnection *connection,
05719 const char *path,
05720 const DBusObjectPathVTable *vtable,
05721 void *user_data)
05722 {
05723 char **decomposed_path;
05724 dbus_bool_t retval;
05725 DBusError error = DBUS_ERROR_INIT;
05726
05727 _dbus_return_val_if_fail (connection != NULL, FALSE);
05728 _dbus_return_val_if_fail (path != NULL, FALSE);
05729 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05730 _dbus_return_val_if_fail (vtable != NULL, FALSE);
05731
05732 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05733 return FALSE;
05734
05735 CONNECTION_LOCK (connection);
05736
05737 retval = _dbus_object_tree_register (connection->objects,
05738 TRUE,
05739 (const char **) decomposed_path, vtable,
05740 user_data, &error);
05741
05742 CONNECTION_UNLOCK (connection);
05743
05744 dbus_free_string_array (decomposed_path);
05745
05746 if (dbus_error_has_name (&error, DBUS_ERROR_ADDRESS_IN_USE))
05747 {
05748 _dbus_warn ("%s\n", error.message);
05749 dbus_error_free (&error);
05750 return FALSE;
05751 }
05752
05753 return retval;
05754 }
05755
05765 dbus_bool_t
05766 dbus_connection_unregister_object_path (DBusConnection *connection,
05767 const char *path)
05768 {
05769 char **decomposed_path;
05770
05771 _dbus_return_val_if_fail (connection != NULL, FALSE);
05772 _dbus_return_val_if_fail (path != NULL, FALSE);
05773 _dbus_return_val_if_fail (path[0] == '/', FALSE);
05774
05775 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05776 return FALSE;
05777
05778 CONNECTION_LOCK (connection);
05779
05780 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
05781
05782 dbus_free_string_array (decomposed_path);
05783
05784 return TRUE;
05785 }
05786
05797 dbus_bool_t
05798 dbus_connection_get_object_path_data (DBusConnection *connection,
05799 const char *path,
05800 void **data_p)
05801 {
05802 char **decomposed_path;
05803
05804 _dbus_return_val_if_fail (connection != NULL, FALSE);
05805 _dbus_return_val_if_fail (path != NULL, FALSE);
05806 _dbus_return_val_if_fail (data_p != NULL, FALSE);
05807
05808 *data_p = NULL;
05809
05810 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
05811 return FALSE;
05812
05813 CONNECTION_LOCK (connection);
05814
05815 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
05816
05817 CONNECTION_UNLOCK (connection);
05818
05819 dbus_free_string_array (decomposed_path);
05820
05821 return TRUE;
05822 }
05823
05834 dbus_bool_t
05835 dbus_connection_list_registered (DBusConnection *connection,
05836 const char *parent_path,
05837 char ***child_entries)
05838 {
05839 char **decomposed_path;
05840 dbus_bool_t retval;
05841 _dbus_return_val_if_fail (connection != NULL, FALSE);
05842 _dbus_return_val_if_fail (parent_path != NULL, FALSE);
05843 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
05844 _dbus_return_val_if_fail (child_entries != NULL, FALSE);
05845
05846 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
05847 return FALSE;
05848
05849 CONNECTION_LOCK (connection);
05850
05851 retval = _dbus_object_tree_list_registered_and_unlock (connection->objects,
05852 (const char **) decomposed_path,
05853 child_entries);
05854 dbus_free_string_array (decomposed_path);
05855
05856 return retval;
05857 }
05858
05859 static DBusDataSlotAllocator slot_allocator;
05860 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
05861
05876 dbus_bool_t
05877 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
05878 {
05879 return _dbus_data_slot_allocator_alloc (&slot_allocator,
05880 &_DBUS_LOCK_NAME (connection_slots),
05881 slot_p);
05882 }
05883
05895 void
05896 dbus_connection_free_data_slot (dbus_int32_t *slot_p)
05897 {
05898 _dbus_return_if_fail (*slot_p >= 0);
05899
05900 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
05901 }
05902
05925 dbus_bool_t
05926 dbus_connection_set_data (DBusConnection *connection,
05927 dbus_int32_t slot,
05928 void *data,
05929 DBusFreeFunction free_data_func)
05930 {
05931 DBusFreeFunction old_free_func;
05932 void *old_data;
05933 dbus_bool_t retval;
05934
05935 _dbus_return_val_if_fail (connection != NULL, FALSE);
05936 _dbus_return_val_if_fail (slot >= 0, FALSE);
05937
05938 SLOTS_LOCK (connection);
05939
05940 retval = _dbus_data_slot_list_set (&slot_allocator,
05941 &connection->slot_list,
05942 slot, data, free_data_func,
05943 &old_free_func, &old_data);
05944
05945 SLOTS_UNLOCK (connection);
05946
05947 if (retval)
05948 {
05949
05950 if (old_free_func)
05951 (* old_free_func) (old_data);
05952 }
05953
05954 return retval;
05955 }
05956
05974 void*
05975 dbus_connection_get_data (DBusConnection *connection,
05976 dbus_int32_t slot)
05977 {
05978 void *res;
05979
05980 _dbus_return_val_if_fail (connection != NULL, NULL);
05981
05982 SLOTS_LOCK (connection);
05983
05984 res = _dbus_data_slot_list_get (&slot_allocator,
05985 &connection->slot_list,
05986 slot);
05987
05988 SLOTS_UNLOCK (connection);
05989
05990 return res;
05991 }
05992
05999 void
06000 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
06001 {
06002 _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
06003 }
06004
06013 void
06014 dbus_connection_set_max_message_size (DBusConnection *connection,
06015 long size)
06016 {
06017 _dbus_return_if_fail (connection != NULL);
06018
06019 CONNECTION_LOCK (connection);
06020 _dbus_transport_set_max_message_size (connection->transport,
06021 size);
06022 CONNECTION_UNLOCK (connection);
06023 }
06024
06031 long
06032 dbus_connection_get_max_message_size (DBusConnection *connection)
06033 {
06034 long res;
06035
06036 _dbus_return_val_if_fail (connection != NULL, 0);
06037
06038 CONNECTION_LOCK (connection);
06039 res = _dbus_transport_get_max_message_size (connection->transport);
06040 CONNECTION_UNLOCK (connection);
06041 return res;
06042 }
06043
06052 void
06053 dbus_connection_set_max_message_unix_fds (DBusConnection *connection,
06054 long n)
06055 {
06056 _dbus_return_if_fail (connection != NULL);
06057
06058 CONNECTION_LOCK (connection);
06059 _dbus_transport_set_max_message_unix_fds (connection->transport,
06060 n);
06061 CONNECTION_UNLOCK (connection);
06062 }
06063
06070 long
06071 dbus_connection_get_max_message_unix_fds (DBusConnection *connection)
06072 {
06073 long res;
06074
06075 _dbus_return_val_if_fail (connection != NULL, 0);
06076
06077 CONNECTION_LOCK (connection);
06078 res = _dbus_transport_get_max_message_unix_fds (connection->transport);
06079 CONNECTION_UNLOCK (connection);
06080 return res;
06081 }
06082
06108 void
06109 dbus_connection_set_max_received_size (DBusConnection *connection,
06110 long size)
06111 {
06112 _dbus_return_if_fail (connection != NULL);
06113
06114 CONNECTION_LOCK (connection);
06115 _dbus_transport_set_max_received_size (connection->transport,
06116 size);
06117 CONNECTION_UNLOCK (connection);
06118 }
06119
06126 long
06127 dbus_connection_get_max_received_size (DBusConnection *connection)
06128 {
06129 long res;
06130
06131 _dbus_return_val_if_fail (connection != NULL, 0);
06132
06133 CONNECTION_LOCK (connection);
06134 res = _dbus_transport_get_max_received_size (connection->transport);
06135 CONNECTION_UNLOCK (connection);
06136 return res;
06137 }
06138
06150 void
06151 dbus_connection_set_max_received_unix_fds (DBusConnection *connection,
06152 long n)
06153 {
06154 _dbus_return_if_fail (connection != NULL);
06155
06156 CONNECTION_LOCK (connection);
06157 _dbus_transport_set_max_received_unix_fds (connection->transport,
06158 n);
06159 CONNECTION_UNLOCK (connection);
06160 }
06161
06168 long
06169 dbus_connection_get_max_received_unix_fds (DBusConnection *connection)
06170 {
06171 long res;
06172
06173 _dbus_return_val_if_fail (connection != NULL, 0);
06174
06175 CONNECTION_LOCK (connection);
06176 res = _dbus_transport_get_max_received_unix_fds (connection->transport);
06177 CONNECTION_UNLOCK (connection);
06178 return res;
06179 }
06180
06191 long
06192 dbus_connection_get_outgoing_size (DBusConnection *connection)
06193 {
06194 long res;
06195
06196 _dbus_return_val_if_fail (connection != NULL, 0);
06197
06198 CONNECTION_LOCK (connection);
06199 res = _dbus_counter_get_size_value (connection->outgoing_counter);
06200 CONNECTION_UNLOCK (connection);
06201 return res;
06202 }
06203
06211 long
06212 dbus_connection_get_outgoing_unix_fds (DBusConnection *connection)
06213 {
06214 long res;
06215
06216 _dbus_return_val_if_fail (connection != NULL, 0);
06217
06218 CONNECTION_LOCK (connection);
06219 res = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
06220 CONNECTION_UNLOCK (connection);
06221 return res;
06222 }
06223