D-Bus 1.15.8
dbus-connection.c
1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2/* dbus-connection.c DBusConnection object
3 *
4 * Copyright (C) 2002-2006 Red Hat Inc.
5 *
6 * SPDX-License-Identifier: AFL-2.1 OR GPL-2.0-or-later
7 *
8 * Licensed under the Academic Free License version 2.1
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 *
24 */
25
26#include <config.h>
27#include "dbus-shared.h"
28#include "dbus-connection.h"
29#include "dbus-list.h"
30#include "dbus-timeout.h"
31#include "dbus-transport.h"
32#include "dbus-watch.h"
33#include "dbus-connection-internal.h"
34#include "dbus-pending-call-internal.h"
35#include "dbus-list.h"
36#include "dbus-hash.h"
37#include "dbus-message-internal.h"
38#include "dbus-message-private.h"
39#include "dbus-threads.h"
40#include "dbus-protocol.h"
41#include "dbus-dataslot.h"
42#include "dbus-string.h"
43#include "dbus-signature.h"
44#include "dbus-pending-call.h"
45#include "dbus-object-tree.h"
46#include "dbus-threads-internal.h"
47#include "dbus-bus.h"
48#include "dbus-marshal-basic.h"
49
50#ifdef DBUS_DISABLE_CHECKS
51#define TOOK_LOCK_CHECK(connection)
52#define RELEASING_LOCK_CHECK(connection)
53#define HAVE_LOCK_CHECK(connection)
54#else
55#define TOOK_LOCK_CHECK(connection) do { \
56 _dbus_assert (!(connection)->have_connection_lock); \
57 (connection)->have_connection_lock = TRUE; \
58 } while (0)
59#define RELEASING_LOCK_CHECK(connection) do { \
60 _dbus_assert ((connection)->have_connection_lock); \
61 (connection)->have_connection_lock = FALSE; \
62 } while (0)
63#define HAVE_LOCK_CHECK(connection) _dbus_assert ((connection)->have_connection_lock)
64/* A "DO_NOT_HAVE_LOCK_CHECK" is impossible since we need the lock to check the flag */
65#endif
66
67#define TRACE_LOCKS 1
68
69#define CONNECTION_LOCK(connection) do { \
70 if (TRACE_LOCKS) { _dbus_verbose ("LOCK\n"); } \
71 _dbus_rmutex_lock ((connection)->mutex); \
72 TOOK_LOCK_CHECK (connection); \
73 } while (0)
74
75#define CONNECTION_UNLOCK(connection) _dbus_connection_unlock (connection)
76
77#define SLOTS_LOCK(connection) do { \
78 _dbus_rmutex_lock ((connection)->slot_mutex); \
79 } while (0)
80
81#define SLOTS_UNLOCK(connection) do { \
82 _dbus_rmutex_unlock ((connection)->slot_mutex); \
83 } while (0)
84
85#define DISPATCH_STATUS_NAME(s) \
86 ((s) == DBUS_DISPATCH_COMPLETE ? "complete" : \
87 (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
88 (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" : \
89 "???")
90
208static void
209_dbus_connection_trace_ref (DBusConnection *connection,
210 int old_refcount,
211 int new_refcount,
212 const char *why)
213{
214#ifdef DBUS_ENABLE_VERBOSE_MODE
215 static int enabled = -1;
216
217 _dbus_trace_ref ("DBusConnection", connection, old_refcount, new_refcount,
218 why, "DBUS_CONNECTION_TRACE", &enabled);
219#endif
220}
221
226
231{
234 void *user_data;
236};
237
238
243{
247};
248
249#if HAVE_DECL_MSG_NOSIGNAL
250static DBusAtomic _dbus_modify_sigpipe = { FALSE };
251#else
252static DBusAtomic _dbus_modify_sigpipe = { TRUE };
253#endif
254
259{
310 /* These two MUST be bools and not bitfields, because they are protected by a separate lock
311 * from connection->mutex and all bitfields in a word have to be read/written together.
312 * So you can't have a different lock for different bitfields in the same word.
313 */
317 unsigned int shareable : 1;
319 unsigned int exit_on_disconnect : 1;
321 unsigned int builtin_filters_enabled : 1;
323 unsigned int route_peer_messages : 1;
333#ifndef DBUS_DISABLE_CHECKS
334 unsigned int have_connection_lock : 1;
335#endif
336
337#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
338 int generation;
339#endif
340};
341
342static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection);
343static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
344 DBusDispatchStatus new_status);
345static void _dbus_connection_last_unref (DBusConnection *connection);
346static void _dbus_connection_acquire_dispatch (DBusConnection *connection);
347static void _dbus_connection_release_dispatch (DBusConnection *connection);
348static DBusDispatchStatus _dbus_connection_flush_unlocked (DBusConnection *connection);
349static void _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection);
350static dbus_bool_t _dbus_connection_get_is_connected_unlocked (DBusConnection *connection);
351static dbus_bool_t _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
352 dbus_uint32_t client_serial);
353
354static DBusMessageFilter *
355_dbus_message_filter_ref (DBusMessageFilter *filter)
356{
357#ifdef DBUS_DISABLE_ASSERT
358 _dbus_atomic_inc (&filter->refcount);
359#else
360 dbus_int32_t old_value;
361
362 old_value = _dbus_atomic_inc (&filter->refcount);
363 _dbus_assert (old_value > 0);
364#endif
365
366 return filter;
367}
368
369static void
370_dbus_message_filter_unref (DBusMessageFilter *filter)
371{
372 dbus_int32_t old_value;
373
374 old_value = _dbus_atomic_dec (&filter->refcount);
375 _dbus_assert (old_value > 0);
376
377 if (old_value == 1)
378 {
379 if (filter->free_user_data_function)
380 (* filter->free_user_data_function) (filter->user_data);
381
382 dbus_free (filter);
383 }
384}
385
391void
393{
394 CONNECTION_LOCK (connection);
395}
396
402void
404{
405 DBusList *expired_messages;
406 DBusList *iter;
407
408 if (TRACE_LOCKS)
409 {
410 _dbus_verbose ("UNLOCK\n");
411 }
412
413 /* If we had messages that expired (fell off the incoming or outgoing
414 * queues) while we were locked, actually release them now */
415 expired_messages = connection->expired_messages;
416 connection->expired_messages = NULL;
417
418 RELEASING_LOCK_CHECK (connection);
419 _dbus_rmutex_unlock (connection->mutex);
420
421 for (iter = _dbus_list_pop_first_link (&expired_messages);
422 iter != NULL;
423 iter = _dbus_list_pop_first_link (&expired_messages))
424 {
425 DBusMessage *message = iter->data;
426
427 dbus_message_unref (message);
429 }
430}
431
439static void
440_dbus_connection_wakeup_mainloop (DBusConnection *connection)
441{
442 if (connection->wakeup_main_function)
443 (*connection->wakeup_main_function) (connection->wakeup_main_data);
444}
445
446#ifdef DBUS_ENABLE_EMBEDDED_TESTS
459void
460_dbus_connection_test_get_locks (DBusConnection *connection,
461 DBusMutex **mutex_loc,
462 DBusMutex **dispatch_mutex_loc,
463 DBusMutex **io_path_mutex_loc,
464 DBusCondVar **dispatch_cond_loc,
465 DBusCondVar **io_path_cond_loc)
466{
467 *mutex_loc = (DBusMutex *) connection->mutex;
468 *dispatch_mutex_loc = (DBusMutex *) connection->dispatch_mutex;
469 *io_path_mutex_loc = (DBusMutex *) connection->io_path_mutex;
470 *dispatch_cond_loc = connection->dispatch_cond;
471 *io_path_cond_loc = connection->io_path_cond;
472}
473#endif
474
483void
485 DBusList *link)
486{
487 DBusPendingCall *pending;
488 dbus_uint32_t reply_serial;
489 DBusMessage *message;
490
492
494 link);
495 message = link->data;
496
497 /* If this is a reply we're waiting on, remove timeout for it */
498 reply_serial = dbus_message_get_reply_serial (message);
499 if (reply_serial != 0)
500 {
501 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
502 reply_serial);
503 if (pending != NULL)
504 {
508
510 }
511 }
512
513
514
515 connection->n_incoming += 1;
516
517 _dbus_connection_wakeup_mainloop (connection);
518
519 _dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
520 message,
522 dbus_message_get_path (message) ?
523 dbus_message_get_path (message) :
524 "no path",
527 "no interface",
528 dbus_message_get_member (message) ?
529 dbus_message_get_member (message) :
530 "no member",
533 connection,
534 connection->n_incoming);
535
536 _dbus_message_trace_ref (message, -1, -1,
537 "_dbus_conection_queue_received_message_link");
538}
539
548void
550 DBusList *link)
551{
552 HAVE_LOCK_CHECK (connection);
553
554 _dbus_list_append_link (&connection->incoming_messages, link);
555
556 connection->n_incoming += 1;
557
558 _dbus_connection_wakeup_mainloop (connection);
559
560 _dbus_message_trace_ref (link->data, -1, -1,
561 "_dbus_connection_queue_synthesized_message_link");
562
563 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
564 link->data, connection, connection->n_incoming);
565}
566
567
577{
578 HAVE_LOCK_CHECK (connection);
579 return connection->outgoing_messages != NULL;
580}
581
593{
594 dbus_bool_t v;
595
596 _dbus_return_val_if_fail (connection != NULL, FALSE);
597
598 CONNECTION_LOCK (connection);
600 CONNECTION_UNLOCK (connection);
601
602 return v;
603}
604
614{
615 HAVE_LOCK_CHECK (connection);
616
617 return _dbus_list_get_last (&connection->outgoing_messages);
618}
619
628void
630 DBusMessage *message)
631{
632 DBusList *link;
633
634 HAVE_LOCK_CHECK (connection);
635
636 /* This can be called before we even complete authentication, since
637 * it's called on disconnect to clean up the outgoing queue.
638 * It's also called as we successfully send each message.
639 */
640
641 link = _dbus_list_get_last_link (&connection->outgoing_messages);
642 _dbus_assert (link != NULL);
643 _dbus_assert (link->data == message);
644
646 link);
647 _dbus_list_prepend_link (&connection->expired_messages, link);
648
649 connection->n_outgoing -= 1;
650
651 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
652 message,
654 dbus_message_get_path (message) ?
655 dbus_message_get_path (message) :
656 "no path",
659 "no interface",
660 dbus_message_get_member (message) ?
661 dbus_message_get_member (message) :
662 "no member",
664 connection, connection->n_outgoing);
665
666 /* It's OK that in principle we call the notify function, because for the
667 * outgoing limit, there isn't one */
668 _dbus_message_remove_counter (message, connection->outgoing_counter);
669
670 /* The message will actually be unreffed when we unlock */
671}
672
675 DBusWatch *watch);
678 DBusWatch *watch);
681 DBusWatch *watch,
682 dbus_bool_t enabled);
683
684static dbus_bool_t
685protected_change_watch (DBusConnection *connection,
686 DBusWatch *watch,
687 DBusWatchAddFunction add_function,
688 DBusWatchRemoveFunction remove_function,
689 DBusWatchToggleFunction toggle_function,
690 dbus_bool_t enabled)
691{
692 dbus_bool_t retval;
693
694 HAVE_LOCK_CHECK (connection);
695
696 /* The original purpose of protected_change_watch() was to hold a
697 * ref on the connection while dropping the connection lock, then
698 * calling out to the app. This was a broken hack that did not
699 * work, since the connection was in a hosed state (no WatchList
700 * field) while calling out.
701 *
702 * So for now we'll just keep the lock while calling out. This means
703 * apps are not allowed to call DBusConnection methods inside a
704 * watch function or they will deadlock.
705 *
706 * The "real fix" is to use the _and_unlock() pattern found
707 * elsewhere in the code, to defer calling out to the app until
708 * we're about to drop locks and return flow of control to the app
709 * anyway.
710 *
711 * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
712 */
713
714 if (connection->watches)
715 {
716 if (add_function)
717 retval = (* add_function) (connection->watches, watch);
718 else if (remove_function)
719 {
720 retval = TRUE;
721 (* remove_function) (connection->watches, watch);
722 }
723 else
724 {
725 retval = TRUE;
726 (* toggle_function) (connection->watches, watch, enabled);
727 }
728 return retval;
729 }
730 else
731 return FALSE;
732}
733
734
748 DBusWatch *watch)
749{
750 return protected_change_watch (connection, watch,
752 NULL, NULL, FALSE);
753}
754
764void
766 DBusWatch *watch)
767{
768 protected_change_watch (connection, watch,
769 NULL,
771 NULL, FALSE);
772}
773
784void
786 DBusWatch *watch,
787 dbus_bool_t enabled)
788{
789 _dbus_assert (watch != NULL);
790
791 protected_change_watch (connection, watch,
792 NULL, NULL,
794 enabled);
795}
796
799 DBusTimeout *timeout);
802 DBusTimeout *timeout);
805 DBusTimeout *timeout,
806 dbus_bool_t enabled);
807
808static dbus_bool_t
809protected_change_timeout (DBusConnection *connection,
810 DBusTimeout *timeout,
811 DBusTimeoutAddFunction add_function,
812 DBusTimeoutRemoveFunction remove_function,
813 DBusTimeoutToggleFunction toggle_function,
814 dbus_bool_t enabled)
815{
816 dbus_bool_t retval;
817
818 HAVE_LOCK_CHECK (connection);
819
820 /* The original purpose of protected_change_timeout() was to hold a
821 * ref on the connection while dropping the connection lock, then
822 * calling out to the app. This was a broken hack that did not
823 * work, since the connection was in a hosed state (no TimeoutList
824 * field) while calling out.
825 *
826 * So for now we'll just keep the lock while calling out. This means
827 * apps are not allowed to call DBusConnection methods inside a
828 * timeout function or they will deadlock.
829 *
830 * The "real fix" is to use the _and_unlock() pattern found
831 * elsewhere in the code, to defer calling out to the app until
832 * we're about to drop locks and return flow of control to the app
833 * anyway.
834 *
835 * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
836 */
837
838 if (connection->timeouts)
839 {
840 if (add_function)
841 retval = (* add_function) (connection->timeouts, timeout);
842 else if (remove_function)
843 {
844 retval = TRUE;
845 (* remove_function) (connection->timeouts, timeout);
846 }
847 else
848 {
849 retval = TRUE;
850 (* toggle_function) (connection->timeouts, timeout, enabled);
851 }
852 return retval;
853 }
854 else
855 return FALSE;
856}
857
872 DBusTimeout *timeout)
873{
874 return protected_change_timeout (connection, timeout,
876 NULL, NULL, FALSE);
877}
878
888void
890 DBusTimeout *timeout)
891{
892 protected_change_timeout (connection, timeout,
893 NULL,
895 NULL, FALSE);
896}
897
908void
910 DBusTimeout *timeout,
911 dbus_bool_t enabled)
912{
913 protected_change_timeout (connection, timeout,
914 NULL, NULL,
916 enabled);
917}
918
919static dbus_bool_t
920_dbus_connection_attach_pending_call_unlocked (DBusConnection *connection,
921 DBusPendingCall *pending)
922{
923 dbus_uint32_t reply_serial;
924 DBusTimeout *timeout;
925
926 HAVE_LOCK_CHECK (connection);
927
928 reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
929
930 _dbus_assert (reply_serial != 0);
931
932 timeout = _dbus_pending_call_get_timeout_unlocked (pending);
933
934 if (timeout)
935 {
936 if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
937 return FALSE;
938
940 reply_serial,
941 pending))
942 {
943 _dbus_connection_remove_timeout_unlocked (connection, timeout);
944
946 HAVE_LOCK_CHECK (connection);
947 return FALSE;
948 }
949
951 }
952 else
953 {
955 reply_serial,
956 pending))
957 {
958 HAVE_LOCK_CHECK (connection);
959 return FALSE;
960 }
961 }
962
964
965 HAVE_LOCK_CHECK (connection);
966
967 return TRUE;
968}
969
970static void
971free_pending_call_on_hash_removal (void *data)
972{
973 DBusPendingCall *pending;
974 DBusConnection *connection;
975
976 if (data == NULL)
977 return;
978
979 pending = data;
980
981 connection = _dbus_pending_call_get_connection_unlocked (pending);
982
983 HAVE_LOCK_CHECK (connection);
984
986 {
989
991 }
992
993 /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock
994 * here, but the pending call finalizer could in principle call out to
995 * application code so we pretty much have to... some larger code reorg
996 * might be needed.
997 */
1000 CONNECTION_LOCK (connection);
1002}
1003
1004static void
1005_dbus_connection_detach_pending_call_unlocked (DBusConnection *connection,
1006 DBusPendingCall *pending)
1007{
1008 /* This ends up unlocking to call the pending call finalizer, which is unexpected to
1009 * say the least.
1010 */
1013}
1014
1015static void
1016_dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection,
1017 DBusPendingCall *pending)
1018{
1019 /* The idea here is to avoid finalizing the pending call
1020 * with the lock held, since there's a destroy notifier
1021 * in pending call that goes out to application code.
1022 *
1023 * There's an extra unlock inside the hash table
1024 * "free pending call" function FIXME...
1025 */
1029
1033
1035
1037}
1038
1047void
1049 DBusPendingCall *pending)
1050{
1051 CONNECTION_LOCK (connection);
1052 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
1053}
1054
1064static dbus_bool_t
1065_dbus_connection_acquire_io_path (DBusConnection *connection,
1066 int timeout_milliseconds)
1067{
1068 dbus_bool_t we_acquired;
1069
1070 HAVE_LOCK_CHECK (connection);
1071
1072 /* We don't want the connection to vanish */
1073 _dbus_connection_ref_unlocked (connection);
1074
1075 /* We will only touch io_path_acquired which is protected by our mutex */
1076 CONNECTION_UNLOCK (connection);
1077
1078 _dbus_verbose ("locking io_path_mutex\n");
1079 _dbus_cmutex_lock (connection->io_path_mutex);
1080
1081 _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n",
1082 connection->io_path_acquired, timeout_milliseconds);
1083
1084 we_acquired = FALSE;
1085
1086 if (connection->io_path_acquired)
1087 {
1088 if (timeout_milliseconds != -1)
1089 {
1090 _dbus_verbose ("waiting %d for IO path to be acquirable\n",
1091 timeout_milliseconds);
1092
1093 if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
1094 connection->io_path_mutex,
1095 timeout_milliseconds))
1096 {
1097 /* We timed out before anyone signaled. */
1098 /* (writing the loop to handle the !timedout case by
1099 * waiting longer if needed is a pain since dbus
1100 * wraps pthread_cond_timedwait to take a relative
1101 * time instead of absolute, something kind of stupid
1102 * on our part. for now it doesn't matter, we will just
1103 * end up back here eventually.)
1104 */
1105 }
1106 }
1107 else
1108 {
1109 while (connection->io_path_acquired)
1110 {
1111 _dbus_verbose ("waiting for IO path to be acquirable\n");
1112 _dbus_condvar_wait (connection->io_path_cond,
1113 connection->io_path_mutex);
1114 }
1115 }
1116 }
1117
1118 if (!connection->io_path_acquired)
1119 {
1120 we_acquired = TRUE;
1121 connection->io_path_acquired = TRUE;
1122 }
1123
1124 _dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n",
1125 connection->io_path_acquired, we_acquired);
1126
1127 _dbus_verbose ("unlocking io_path_mutex\n");
1128 _dbus_cmutex_unlock (connection->io_path_mutex);
1129
1130 CONNECTION_LOCK (connection);
1131
1132 HAVE_LOCK_CHECK (connection);
1133
1135
1136 return we_acquired;
1137}
1138
1146static void
1147_dbus_connection_release_io_path (DBusConnection *connection)
1148{
1149 HAVE_LOCK_CHECK (connection);
1150
1151 _dbus_verbose ("locking io_path_mutex\n");
1152 _dbus_cmutex_lock (connection->io_path_mutex);
1153
1154 _dbus_assert (connection->io_path_acquired);
1155
1156 _dbus_verbose ("start connection->io_path_acquired = %d\n",
1157 connection->io_path_acquired);
1158
1159 connection->io_path_acquired = FALSE;
1161
1162 _dbus_verbose ("unlocking io_path_mutex\n");
1163 _dbus_cmutex_unlock (connection->io_path_mutex);
1164}
1165
1201void
1203 DBusPendingCall *pending,
1204 unsigned int flags,
1205 int timeout_milliseconds)
1206{
1207 _dbus_verbose ("start\n");
1208
1209 HAVE_LOCK_CHECK (connection);
1210
1211 if (connection->n_outgoing == 0)
1212 flags &= ~DBUS_ITERATION_DO_WRITING;
1213
1214 if (_dbus_connection_acquire_io_path (connection,
1215 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
1216 {
1217 HAVE_LOCK_CHECK (connection);
1218
1219 if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending))
1220 {
1221 _dbus_verbose ("pending call completed while acquiring I/O path");
1222 }
1223 else if ( (pending != NULL) &&
1224 _dbus_connection_peek_for_reply_unlocked (connection,
1226 {
1227 _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)");
1228 }
1229 else
1230 {
1232 flags, timeout_milliseconds);
1233 }
1234
1235 _dbus_connection_release_io_path (connection);
1236 }
1237
1238 HAVE_LOCK_CHECK (connection);
1239
1240 _dbus_verbose ("end\n");
1241}
1242
1254{
1255 DBusConnection *connection;
1256 DBusWatchList *watch_list;
1257 DBusTimeoutList *timeout_list;
1258 DBusHashTable *pending_replies;
1259 DBusList *disconnect_link;
1260 DBusMessage *disconnect_message;
1261 DBusCounter *outgoing_counter;
1262 DBusObjectTree *objects;
1263
1264 watch_list = NULL;
1265 connection = NULL;
1266 pending_replies = NULL;
1267 timeout_list = NULL;
1268 disconnect_link = NULL;
1269 disconnect_message = NULL;
1270 outgoing_counter = NULL;
1271 objects = NULL;
1272
1273 watch_list = _dbus_watch_list_new ();
1274 if (watch_list == NULL)
1275 goto error;
1276
1277 timeout_list = _dbus_timeout_list_new ();
1278 if (timeout_list == NULL)
1279 goto error;
1280
1281 pending_replies =
1283 NULL,
1284 (DBusFreeFunction)free_pending_call_on_hash_removal);
1285 if (pending_replies == NULL)
1286 goto error;
1287
1288 connection = dbus_new0 (DBusConnection, 1);
1289 if (connection == NULL)
1290 goto error;
1291
1292 _dbus_rmutex_new_at_location (&connection->mutex);
1293 if (connection->mutex == NULL)
1294 goto error;
1295
1297 if (connection->io_path_mutex == NULL)
1298 goto error;
1299
1301 if (connection->dispatch_mutex == NULL)
1302 goto error;
1303
1305 if (connection->dispatch_cond == NULL)
1306 goto error;
1307
1309 if (connection->io_path_cond == NULL)
1310 goto error;
1311
1313 if (connection->slot_mutex == NULL)
1314 goto error;
1315
1316 disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
1318 "Disconnected");
1319
1320 if (disconnect_message == NULL)
1321 goto error;
1322
1323 disconnect_link = _dbus_list_alloc_link (disconnect_message);
1324 if (disconnect_link == NULL)
1325 goto error;
1326
1327 outgoing_counter = _dbus_counter_new ();
1328 if (outgoing_counter == NULL)
1329 goto error;
1330
1331 objects = _dbus_object_tree_new (connection);
1332 if (objects == NULL)
1333 goto error;
1334
1335 if (_dbus_atomic_get (&_dbus_modify_sigpipe) != 0)
1337
1338 /* initialized to 0: use atomic op to avoid mixing atomic and non-atomic */
1339 _dbus_atomic_inc (&connection->refcount);
1340 connection->transport = transport;
1341 connection->watches = watch_list;
1342 connection->timeouts = timeout_list;
1343 connection->pending_replies = pending_replies;
1344 connection->outgoing_counter = outgoing_counter;
1345 connection->filter_list = NULL;
1346 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
1347 connection->objects = objects;
1348 connection->exit_on_disconnect = FALSE;
1349 connection->shareable = FALSE;
1350 connection->builtin_filters_enabled = TRUE;
1351 connection->route_peer_messages = FALSE;
1352 connection->disconnected_message_arrived = FALSE;
1354
1355#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
1356 connection->generation = _dbus_current_generation;
1357#endif
1358
1359 _dbus_data_slot_list_init (&connection->slot_list);
1360
1361 connection->client_serial = 1;
1362
1363 connection->disconnect_message_link = disconnect_link;
1364
1365 CONNECTION_LOCK (connection);
1366
1367 if (!_dbus_transport_set_connection (transport, connection))
1368 {
1369 CONNECTION_UNLOCK (connection);
1370
1371 goto error;
1372 }
1373
1374 _dbus_transport_ref (transport);
1375
1376 CONNECTION_UNLOCK (connection);
1377
1378 _dbus_connection_trace_ref (connection, 0, 1, "new_for_transport");
1379 return connection;
1380
1381 error:
1382 if (disconnect_message != NULL)
1383 dbus_message_unref (disconnect_message);
1384
1385 if (disconnect_link != NULL)
1386 _dbus_list_free_link (disconnect_link);
1387
1388 if (connection != NULL)
1389 {
1392 _dbus_rmutex_free_at_location (&connection->mutex);
1396 dbus_free (connection);
1397 }
1398 if (pending_replies)
1399 _dbus_hash_table_unref (pending_replies);
1400
1401 if (watch_list)
1402 _dbus_watch_list_free (watch_list);
1403
1404 if (timeout_list)
1405 _dbus_timeout_list_free (timeout_list);
1406
1407 if (outgoing_counter)
1408 _dbus_counter_unref (outgoing_counter);
1409
1410 if (objects)
1411 _dbus_object_tree_unref (objects);
1412
1413 return NULL;
1414}
1415
1425{
1426 dbus_int32_t old_refcount;
1427
1428 _dbus_assert (connection != NULL);
1429 _dbus_assert (connection->generation == _dbus_current_generation);
1430
1431 HAVE_LOCK_CHECK (connection);
1432
1433 old_refcount = _dbus_atomic_inc (&connection->refcount);
1434 _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1,
1435 "ref_unlocked");
1436
1437 return connection;
1438}
1439
1446void
1448{
1449 dbus_int32_t old_refcount;
1450
1451 HAVE_LOCK_CHECK (connection);
1452
1453 _dbus_assert (connection != NULL);
1454
1455 old_refcount = _dbus_atomic_dec (&connection->refcount);
1456
1457 _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1,
1458 "unref_unlocked");
1459
1460 if (old_refcount == 1)
1461 _dbus_connection_last_unref (connection);
1462}
1463
1475{
1476 dbus_uint32_t serial;
1477
1478 serial = connection->client_serial++;
1479
1480 if (connection->client_serial == 0)
1481 connection->client_serial = 1;
1482
1483 return serial;
1484}
1485
1501 unsigned int condition,
1502 void *data)
1503{
1504 DBusConnection *connection;
1505 dbus_bool_t retval;
1506 DBusDispatchStatus status;
1507
1508 connection = data;
1509
1510 _dbus_verbose ("start\n");
1511
1512 CONNECTION_LOCK (connection);
1513
1514 if (!_dbus_connection_acquire_io_path (connection, 1))
1515 {
1516 /* another thread is handling the message */
1517 CONNECTION_UNLOCK (connection);
1518 return TRUE;
1519 }
1520
1521 HAVE_LOCK_CHECK (connection);
1522 retval = _dbus_transport_handle_watch (connection->transport,
1523 watch, condition);
1524
1525 _dbus_connection_release_io_path (connection);
1526
1527 HAVE_LOCK_CHECK (connection);
1528
1529 _dbus_verbose ("middle\n");
1530
1531 status = _dbus_connection_get_dispatch_status_unlocked (connection);
1532
1533 /* this calls out to user code */
1534 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
1535
1536 _dbus_verbose ("end\n");
1537
1538 return retval;
1539}
1540
1541/* Protected by _DBUS_LOCK (shared_connections) */
1542static DBusHashTable *shared_connections = NULL;
1543static DBusList *shared_connections_no_guid = NULL;
1544
1545static void
1546close_connection_on_shutdown (DBusConnection *connection)
1547{
1548 DBusMessage *message;
1549
1550 dbus_connection_ref (connection);
1552
1553 /* Churn through to the Disconnected message */
1554 while ((message = dbus_connection_pop_message (connection)))
1555 {
1556 dbus_message_unref (message);
1557 }
1558 dbus_connection_unref (connection);
1559}
1560
1561static void
1562shared_connections_shutdown (void *data)
1563{
1564 int n_entries;
1565
1566 if (!_DBUS_LOCK (shared_connections))
1567 {
1568 /* We'd have initialized locks before adding anything, so there
1569 * can't be anything there. */
1570 return;
1571 }
1572
1573 /* This is a little bit unpleasant... better ideas? */
1574 while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
1575 {
1576 DBusConnection *connection;
1577 DBusHashIter iter;
1578
1579 _dbus_hash_iter_init (shared_connections, &iter);
1580 _dbus_hash_iter_next (&iter);
1581
1582 connection = _dbus_hash_iter_get_value (&iter);
1583
1584 _DBUS_UNLOCK (shared_connections);
1585 close_connection_on_shutdown (connection);
1586 if (!_DBUS_LOCK (shared_connections))
1587 _dbus_assert_not_reached ("global locks were already initialized");
1588
1589 /* The connection should now be dead and not in our hash ... */
1590 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
1591 }
1592
1593 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
1594
1595 _dbus_hash_table_unref (shared_connections);
1596 shared_connections = NULL;
1597
1598 if (shared_connections_no_guid != NULL)
1599 {
1600 DBusConnection *connection;
1601 connection = _dbus_list_pop_first (&shared_connections_no_guid);
1602 while (connection != NULL)
1603 {
1604 _DBUS_UNLOCK (shared_connections);
1605 close_connection_on_shutdown (connection);
1606 if (!_DBUS_LOCK (shared_connections))
1607 _dbus_assert_not_reached ("global locks were already initialized");
1608 connection = _dbus_list_pop_first (&shared_connections_no_guid);
1609 }
1610 }
1611
1612 shared_connections_no_guid = NULL;
1613
1614 _DBUS_UNLOCK (shared_connections);
1615}
1616
1617static dbus_bool_t
1618connection_lookup_shared (DBusAddressEntry *entry,
1619 DBusConnection **result)
1620{
1621 _dbus_verbose ("checking for existing connection\n");
1622
1623 *result = NULL;
1624
1625 if (!_DBUS_LOCK (shared_connections))
1626 {
1627 /* If it was shared, we'd have initialized global locks when we put
1628 * it in shared_connections. */
1629 return FALSE;
1630 }
1631
1632 if (shared_connections == NULL)
1633 {
1634 _dbus_verbose ("creating shared_connections hash table\n");
1635
1636 shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
1637 dbus_free,
1638 NULL);
1639 if (shared_connections == NULL)
1640 {
1641 _DBUS_UNLOCK (shared_connections);
1642 return FALSE;
1643 }
1644
1645 if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
1646 {
1647 _dbus_hash_table_unref (shared_connections);
1648 shared_connections = NULL;
1649 _DBUS_UNLOCK (shared_connections);
1650 return FALSE;
1651 }
1652
1653 _dbus_verbose (" successfully created shared_connections\n");
1654
1655 _DBUS_UNLOCK (shared_connections);
1656 return TRUE; /* no point looking up in the hash we just made */
1657 }
1658 else
1659 {
1660 const char *guid;
1661
1662 guid = dbus_address_entry_get_value (entry, "guid");
1663
1664 if (guid != NULL)
1665 {
1666 DBusConnection *connection;
1667
1668 connection = _dbus_hash_table_lookup_string (shared_connections,
1669 guid);
1670
1671 if (connection)
1672 {
1673 /* The DBusConnection can't be finalized without taking
1674 * the shared_connections lock to remove it from the
1675 * hash. So it's safe to ref the connection here.
1676 * However, it may be disconnected if the Disconnected
1677 * message hasn't been processed yet, in which case we
1678 * want to pretend it isn't in the hash and avoid
1679 * returning it.
1680 *
1681 * The idea is to avoid ever returning a disconnected connection
1682 * from dbus_connection_open(). We could just synchronously
1683 * drop our shared ref to the connection on connection disconnect,
1684 * and then assert here that the connection is connected, but
1685 * that causes reentrancy headaches.
1686 */
1687 CONNECTION_LOCK (connection);
1688 if (_dbus_connection_get_is_connected_unlocked (connection))
1689 {
1690 _dbus_connection_ref_unlocked (connection);
1691 *result = connection;
1692 _dbus_verbose ("looked up existing connection to server guid %s\n",
1693 guid);
1694 }
1695 else
1696 {
1697 _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
1698 guid);
1699 }
1700 CONNECTION_UNLOCK (connection);
1701 }
1702 }
1703
1704 _DBUS_UNLOCK (shared_connections);
1705 return TRUE;
1706 }
1707}
1708
1709static dbus_bool_t
1710connection_record_shared_unlocked (DBusConnection *connection,
1711 const char *guid)
1712{
1713 char *guid_key;
1714 char *guid_in_connection;
1715
1716 HAVE_LOCK_CHECK (connection);
1717 _dbus_assert (connection->server_guid == NULL);
1718 _dbus_assert (connection->shareable);
1719
1720 /* get a hard ref on this connection, even if
1721 * we won't in fact store it in the hash, we still
1722 * need to hold a ref on it until it's disconnected.
1723 */
1724 _dbus_connection_ref_unlocked (connection);
1725
1726 if (guid == NULL)
1727 {
1728 if (!_DBUS_LOCK (shared_connections))
1729 return FALSE;
1730
1731 if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
1732 {
1733 _DBUS_UNLOCK (shared_connections);
1734 return FALSE;
1735 }
1736
1737 _DBUS_UNLOCK (shared_connections);
1738 return TRUE; /* don't store in the hash */
1739 }
1740
1741 /* A separate copy of the key is required in the hash table, because
1742 * we don't have a lock on the connection when we are doing a hash
1743 * lookup.
1744 */
1745
1746 guid_key = _dbus_strdup (guid);
1747 if (guid_key == NULL)
1748 return FALSE;
1749
1750 guid_in_connection = _dbus_strdup (guid);
1751 if (guid_in_connection == NULL)
1752 {
1753 dbus_free (guid_key);
1754 return FALSE;
1755 }
1756
1757 if (!_DBUS_LOCK (shared_connections))
1758 {
1759 dbus_free (guid_in_connection);
1760 dbus_free (guid_key);
1761 return FALSE;
1762 }
1763
1764 _dbus_assert (shared_connections != NULL);
1765
1766 if (!_dbus_hash_table_insert_string (shared_connections,
1767 guid_key, connection))
1768 {
1769 dbus_free (guid_key);
1770 dbus_free (guid_in_connection);
1771 _DBUS_UNLOCK (shared_connections);
1772 return FALSE;
1773 }
1774
1775 connection->server_guid = guid_in_connection;
1776
1777 _dbus_verbose ("stored connection to %s to be shared\n",
1778 connection->server_guid);
1779
1780 _DBUS_UNLOCK (shared_connections);
1781
1782 _dbus_assert (connection->server_guid != NULL);
1783
1784 return TRUE;
1785}
1786
1787static void
1788connection_forget_shared_unlocked (DBusConnection *connection)
1789{
1790 HAVE_LOCK_CHECK (connection);
1791
1792 if (!connection->shareable)
1793 return;
1794
1795 if (!_DBUS_LOCK (shared_connections))
1796 {
1797 /* If it was shared, we'd have initialized global locks when we put
1798 * it in the table; so it can't be there. */
1799 return;
1800 }
1801
1802 if (connection->server_guid != NULL)
1803 {
1804 _dbus_verbose ("dropping connection to %s out of the shared table\n",
1805 connection->server_guid);
1806
1807 if (!_dbus_hash_table_remove_string (shared_connections,
1808 connection->server_guid))
1809 _dbus_assert_not_reached ("connection was not in the shared table");
1810
1811 dbus_free (connection->server_guid);
1812 connection->server_guid = NULL;
1813 }
1814 else
1815 {
1816 _dbus_list_remove (&shared_connections_no_guid, connection);
1817 }
1818
1819 _DBUS_UNLOCK (shared_connections);
1820
1821 /* remove our reference held on all shareable connections */
1823}
1824
1825static DBusConnection*
1826connection_try_from_address_entry (DBusAddressEntry *entry,
1827 DBusError *error)
1828{
1829 DBusTransport *transport;
1830 DBusConnection *connection;
1831
1832 transport = _dbus_transport_open (entry, error);
1833
1834 if (transport == NULL)
1835 {
1836 _DBUS_ASSERT_ERROR_IS_SET (error);
1837 return NULL;
1838 }
1839
1840 connection = _dbus_connection_new_for_transport (transport);
1841
1842 _dbus_transport_unref (transport);
1843
1844 if (connection == NULL)
1845 {
1846 _DBUS_SET_OOM (error);
1847 return NULL;
1848 }
1849
1850#ifndef DBUS_DISABLE_CHECKS
1851 _dbus_assert (!connection->have_connection_lock);
1852#endif
1853 return connection;
1854}
1855
1856/*
1857 * If the shared parameter is true, then any existing connection will
1858 * be used (and if a new connection is created, it will be available
1859 * for use by others). If the shared parameter is false, a new
1860 * connection will always be created, and the new connection will
1861 * never be returned to other callers.
1862 *
1863 * @param address the address
1864 * @param shared whether the connection is shared or private
1865 * @param error error return
1866 * @returns the connection or #NULL on error
1867 */
1868static DBusConnection*
1869_dbus_connection_open_internal (const char *address,
1870 dbus_bool_t shared,
1871 DBusError *error)
1872{
1873 DBusConnection *connection;
1874 DBusAddressEntry **entries;
1875 DBusError tmp_error = DBUS_ERROR_INIT;
1876 DBusError first_error = DBUS_ERROR_INIT;
1877 int len, i;
1878
1879 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1880
1881 _dbus_verbose ("opening %s connection to: %s\n",
1882 shared ? "shared" : "private", address);
1883
1884 if (!dbus_parse_address (address, &entries, &len, error))
1885 return NULL;
1886
1887 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1888
1889 connection = NULL;
1890
1891 for (i = 0; i < len; i++)
1892 {
1893 if (shared)
1894 {
1895 if (!connection_lookup_shared (entries[i], &connection))
1896 _DBUS_SET_OOM (&tmp_error);
1897 }
1898
1899 if (connection == NULL)
1900 {
1901 connection = connection_try_from_address_entry (entries[i],
1902 &tmp_error);
1903
1904 if (connection != NULL && shared)
1905 {
1906 const char *guid;
1907
1908 connection->shareable = TRUE;
1909
1910 /* guid may be NULL */
1911 guid = dbus_address_entry_get_value (entries[i], "guid");
1912
1913 CONNECTION_LOCK (connection);
1914
1915 if (!connection_record_shared_unlocked (connection, guid))
1916 {
1917 _DBUS_SET_OOM (&tmp_error);
1918 _dbus_connection_close_possibly_shared_and_unlock (connection);
1919 dbus_connection_unref (connection);
1920 connection = NULL;
1921 }
1922 else
1923 CONNECTION_UNLOCK (connection);
1924 }
1925 }
1926
1927 if (connection)
1928 break;
1929
1930 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
1931
1932 if (i == 0)
1933 dbus_move_error (&tmp_error, &first_error);
1934 else
1935 dbus_error_free (&tmp_error);
1936 }
1937
1938 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1939 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
1940
1941 if (connection == NULL)
1942 {
1943 _DBUS_ASSERT_ERROR_IS_SET (&first_error);
1944 dbus_move_error (&first_error, error);
1945 }
1946 else
1947 dbus_error_free (&first_error);
1948
1949 dbus_address_entries_free (entries);
1950 return connection;
1951}
1952
1961void
1963{
1964 _dbus_assert (connection != NULL);
1965 _dbus_assert (connection->generation == _dbus_current_generation);
1966
1967 CONNECTION_LOCK (connection);
1968 _dbus_connection_close_possibly_shared_and_unlock (connection);
1969}
1970
1972_dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
1973{
1974 DBusPreallocatedSend *preallocated;
1975
1976 HAVE_LOCK_CHECK (connection);
1977
1978 _dbus_assert (connection != NULL);
1979
1980 preallocated = dbus_new (DBusPreallocatedSend, 1);
1981 if (preallocated == NULL)
1982 return NULL;
1983
1984 preallocated->queue_link = _dbus_list_alloc_link (NULL);
1985 if (preallocated->queue_link == NULL)
1986 goto failed_0;
1987
1988 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
1989 if (preallocated->counter_link == NULL)
1990 goto failed_1;
1991
1992 _dbus_counter_ref (preallocated->counter_link->data);
1993
1994 preallocated->connection = connection;
1995
1996 return preallocated;
1997
1998 failed_1:
1999 _dbus_list_free_link (preallocated->queue_link);
2000 failed_0:
2001 dbus_free (preallocated);
2002
2003 return NULL;
2004}
2005
2006/* Called with lock held, does not update dispatch status */
2007static void
2008_dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection,
2009 DBusPreallocatedSend *preallocated,
2010 DBusMessage *message,
2011 dbus_uint32_t *client_serial)
2012{
2013 dbus_uint32_t serial;
2014
2015 preallocated->queue_link->data = message;
2017 preallocated->queue_link);
2018
2019 /* It's OK that we'll never call the notify function, because for the
2020 * outgoing limit, there isn't one */
2022 preallocated->counter_link);
2023
2024 dbus_free (preallocated);
2025 preallocated = NULL;
2026
2027 dbus_message_ref (message);
2028
2029 connection->n_outgoing += 1;
2030
2031 _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
2032 message,
2034 dbus_message_get_path (message) ?
2035 dbus_message_get_path (message) :
2036 "no path",
2037 dbus_message_get_interface (message) ?
2038 dbus_message_get_interface (message) :
2039 "no interface",
2040 dbus_message_get_member (message) ?
2041 dbus_message_get_member (message) :
2042 "no member",
2046 "null",
2047 connection,
2048 connection->n_outgoing);
2049
2050 if (dbus_message_get_serial (message) == 0)
2051 {
2052 serial = _dbus_connection_get_next_client_serial (connection);
2053 dbus_message_set_serial (message, serial);
2054 if (client_serial)
2055 *client_serial = serial;
2056 }
2057 else
2058 {
2059 if (client_serial)
2060 *client_serial = dbus_message_get_serial (message);
2061 }
2062
2063 _dbus_verbose ("Message %p serial is %u\n",
2064 message, dbus_message_get_serial (message));
2065
2066 dbus_message_lock (message);
2067
2068 /* Now we need to run an iteration to hopefully just write the messages
2069 * out immediately, and otherwise get them queued up
2070 */
2072 NULL,
2073 DBUS_ITERATION_DO_WRITING,
2074 -1);
2075
2076 /* If stuff is still queued up, be sure we wake up the main loop */
2077 if (connection->n_outgoing > 0)
2078 _dbus_connection_wakeup_mainloop (connection);
2079}
2080
2081static void
2082_dbus_connection_send_preallocated_and_unlock (DBusConnection *connection,
2083 DBusPreallocatedSend *preallocated,
2084 DBusMessage *message,
2085 dbus_uint32_t *client_serial)
2086{
2087 DBusDispatchStatus status;
2088
2089 HAVE_LOCK_CHECK (connection);
2090
2091 _dbus_connection_send_preallocated_unlocked_no_update (connection,
2092 preallocated,
2093 message, client_serial);
2094
2095 _dbus_verbose ("middle\n");
2096 status = _dbus_connection_get_dispatch_status_unlocked (connection);
2097
2098 /* this calls out to user code */
2099 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2100}
2101
2113 DBusMessage *message,
2114 dbus_uint32_t *client_serial)
2115{
2116 DBusPreallocatedSend *preallocated;
2117
2118 _dbus_assert (connection != NULL);
2119 _dbus_assert (message != NULL);
2120
2121 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
2122 if (preallocated == NULL)
2123 {
2124 CONNECTION_UNLOCK (connection);
2125 return FALSE;
2126 }
2127
2128 _dbus_connection_send_preallocated_and_unlock (connection,
2129 preallocated,
2130 message,
2131 client_serial);
2132 return TRUE;
2133}
2134
2159void
2161{
2162 dbus_int32_t refcount;
2163
2164 CONNECTION_LOCK (connection);
2165
2166 refcount = _dbus_atomic_get (&connection->refcount);
2167 /* The caller should have at least one ref */
2168 _dbus_assert (refcount >= 1);
2169
2170 if (refcount == 1)
2171 _dbus_connection_close_possibly_shared_and_unlock (connection);
2172 else
2173 CONNECTION_UNLOCK (connection);
2174}
2175
2176
2186static void
2187_dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
2188{
2189 if (timeout_milliseconds == -1)
2191 else if (timeout_milliseconds < 100)
2192 ; /* just busy loop */
2193 else if (timeout_milliseconds <= 1000)
2194 _dbus_sleep_milliseconds (timeout_milliseconds / 3);
2195 else
2197}
2198
2199static DBusMessage *
2200generate_local_error_message (dbus_uint32_t serial,
2201 const char *error_name,
2202 const char *error_msg)
2203{
2204 DBusMessage *message;
2206 if (!message)
2207 goto out;
2208
2209 if (!dbus_message_set_error_name (message, error_name))
2210 {
2211 dbus_message_unref (message);
2212 message = NULL;
2213 goto out;
2214 }
2215
2216 dbus_message_set_no_reply (message, TRUE);
2217
2218 if (!dbus_message_set_reply_serial (message,
2219 serial))
2220 {
2221 dbus_message_unref (message);
2222 message = NULL;
2223 goto out;
2224 }
2225
2226 if (error_msg != NULL)
2227 {
2228 DBusMessageIter iter;
2229
2230 dbus_message_iter_init_append (message, &iter);
2233 &error_msg))
2234 {
2235 dbus_message_unref (message);
2236 message = NULL;
2237 goto out;
2238 }
2239 }
2240
2241 out:
2242 return message;
2243}
2244
2245/*
2246 * Peek the incoming queue to see if we got reply for a specific serial
2247 */
2248static dbus_bool_t
2249_dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
2250 dbus_uint32_t client_serial)
2251{
2252 DBusList *link;
2253 HAVE_LOCK_CHECK (connection);
2254
2255 link = _dbus_list_get_first_link (&connection->incoming_messages);
2256
2257 while (link != NULL)
2258 {
2259 DBusMessage *reply = link->data;
2260
2261 if (dbus_message_get_reply_serial (reply) == client_serial)
2262 {
2263 _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial);
2264 return TRUE;
2265 }
2266 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
2267 }
2268
2269 return FALSE;
2270}
2271
2272/* This is slightly strange since we can pop a message here without
2273 * the dispatch lock.
2274 */
2275static DBusMessage*
2276check_for_reply_unlocked (DBusConnection *connection,
2277 dbus_uint32_t client_serial)
2278{
2279 DBusList *link;
2280
2281 HAVE_LOCK_CHECK (connection);
2282
2283 link = _dbus_list_get_first_link (&connection->incoming_messages);
2284
2285 while (link != NULL)
2286 {
2287 DBusMessage *reply = link->data;
2288
2289 if (dbus_message_get_reply_serial (reply) == client_serial)
2290 {
2291 _dbus_list_remove_link (&connection->incoming_messages, link);
2292 connection->n_incoming -= 1;
2293 return reply;
2294 }
2295 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
2296 }
2297
2298 return NULL;
2299}
2300
2301static void
2302connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
2303{
2304 /* We can't iterate over the hash in the normal way since we'll be
2305 * dropping the lock for each item. So we restart the
2306 * iter each time as we drain the hash table.
2307 */
2308
2309 while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
2310 {
2311 DBusPendingCall *pending;
2312 DBusHashIter iter;
2313
2314 _dbus_hash_iter_init (connection->pending_replies, &iter);
2315 _dbus_hash_iter_next (&iter);
2316
2317 pending = _dbus_hash_iter_get_value (&iter);
2319
2321 connection);
2322
2328
2330 CONNECTION_LOCK (connection);
2331 }
2332 HAVE_LOCK_CHECK (connection);
2333}
2334
2335static void
2336complete_pending_call_and_unlock (DBusConnection *connection,
2337 DBusPendingCall *pending,
2338 DBusMessage *message)
2339{
2340 _dbus_pending_call_set_reply_unlocked (pending, message);
2341 _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */
2343 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
2344
2345 /* Must be called unlocked since it invokes app callback */
2347 dbus_pending_call_unref (pending);
2348}
2349
2350static dbus_bool_t
2351check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection,
2352 DBusPendingCall *pending)
2353{
2354 DBusMessage *reply;
2355 DBusDispatchStatus status;
2356
2357 reply = check_for_reply_unlocked (connection,
2359 if (reply != NULL)
2360 {
2361 _dbus_verbose ("checked for reply\n");
2362
2363 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
2364
2365 complete_pending_call_and_unlock (connection, pending, reply);
2366 dbus_message_unref (reply);
2367
2368 CONNECTION_LOCK (connection);
2369 status = _dbus_connection_get_dispatch_status_unlocked (connection);
2370 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2371 dbus_pending_call_unref (pending);
2372
2373 return TRUE;
2374 }
2375
2376 return FALSE;
2377}
2378
2393void
2395{
2396 long start_tv_sec, start_tv_usec;
2397 long tv_sec, tv_usec;
2398 DBusDispatchStatus status;
2399 DBusConnection *connection;
2400 dbus_uint32_t client_serial;
2401 DBusTimeout *timeout;
2402 int timeout_milliseconds, elapsed_milliseconds;
2403
2404 _dbus_assert (pending != NULL);
2405
2406 if (dbus_pending_call_get_completed (pending))
2407 return;
2408
2409 dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
2410
2411 connection = _dbus_pending_call_get_connection_and_lock (pending);
2412
2413 /* Flush message queue - note, can affect dispatch status */
2414 _dbus_connection_flush_unlocked (connection);
2415
2416 client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
2417
2418 /* note that timeout_milliseconds is limited to a smallish value
2419 * in _dbus_pending_call_new() so overflows aren't possible
2420 * below
2421 */
2422 timeout = _dbus_pending_call_get_timeout_unlocked (pending);
2423 _dbus_get_monotonic_time (&start_tv_sec, &start_tv_usec);
2424 if (timeout)
2425 {
2426 timeout_milliseconds = dbus_timeout_get_interval (timeout);
2427
2428 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n",
2429 timeout_milliseconds,
2430 client_serial,
2431 start_tv_sec, start_tv_usec);
2432 }
2433 else
2434 {
2435 timeout_milliseconds = -1;
2436
2437 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial);
2438 }
2439
2440 /* check to see if we already got the data off the socket */
2441 /* from another blocked pending call */
2442 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
2443 return;
2444
2445 /* Now we wait... */
2446 /* always block at least once as we know we don't have the reply yet */
2448 pending,
2449 DBUS_ITERATION_DO_READING |
2450 DBUS_ITERATION_BLOCK,
2451 timeout_milliseconds);
2452
2453 recheck_status:
2454
2455 _dbus_verbose ("top of recheck\n");
2456
2457 HAVE_LOCK_CHECK (connection);
2458
2459 /* queue messages and get status */
2460
2461 status = _dbus_connection_get_dispatch_status_unlocked (connection);
2462
2463 /* the get_completed() is in case a dispatch() while we were blocking
2464 * got the reply instead of us.
2465 */
2467 {
2468 _dbus_verbose ("Pending call completed by dispatch\n");
2469 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2470 dbus_pending_call_unref (pending);
2471 return;
2472 }
2473
2474 if (status == DBUS_DISPATCH_DATA_REMAINS)
2475 {
2476 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
2477 return;
2478 }
2479
2480 _dbus_get_monotonic_time (&tv_sec, &tv_usec);
2481 elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
2482 (tv_usec - start_tv_usec) / 1000;
2483
2484 if (!_dbus_connection_get_is_connected_unlocked (connection))
2485 {
2486 DBusMessage *error_msg;
2487
2488 error_msg = generate_local_error_message (client_serial,
2490 "Connection was disconnected before a reply was received");
2491
2492 /* on OOM error_msg is set to NULL */
2493 complete_pending_call_and_unlock (connection, pending, error_msg);
2494 if (error_msg != NULL)
2495 dbus_message_unref (error_msg);
2496 dbus_pending_call_unref (pending);
2497 return;
2498 }
2499 else if (connection->disconnect_message_link == NULL)
2500 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
2501 else if (timeout == NULL)
2502 {
2503 if (status == DBUS_DISPATCH_NEED_MEMORY)
2504 {
2505 /* Try sleeping a bit, as we aren't sure we need to block for reading,
2506 * we may already have a reply in the buffer and just can't process
2507 * it.
2508 */
2509 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
2510
2511 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
2512 }
2513 else
2514 {
2515 /* block again, we don't have the reply buffered yet. */
2517 pending,
2518 DBUS_ITERATION_DO_READING |
2519 DBUS_ITERATION_BLOCK,
2520 timeout_milliseconds - elapsed_milliseconds);
2521 }
2522
2523 goto recheck_status;
2524 }
2525 else if (tv_sec < start_tv_sec)
2526 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
2527 else if (elapsed_milliseconds < timeout_milliseconds)
2528 {
2529 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds);
2530
2531 if (status == DBUS_DISPATCH_NEED_MEMORY)
2532 {
2533 /* Try sleeping a bit, as we aren't sure we need to block for reading,
2534 * we may already have a reply in the buffer and just can't process
2535 * it.
2536 */
2537 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
2538
2539 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
2540 }
2541 else
2542 {
2543 /* block again, we don't have the reply buffered yet. */
2545 pending,
2546 DBUS_ITERATION_DO_READING |
2547 DBUS_ITERATION_BLOCK,
2548 timeout_milliseconds - elapsed_milliseconds);
2549 }
2550
2551 goto recheck_status;
2552 }
2553
2554 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n",
2555 elapsed_milliseconds);
2556
2558
2559 /* unlock and call user code */
2560 complete_pending_call_and_unlock (connection, pending, NULL);
2561
2562 /* update user code on dispatch status */
2563 CONNECTION_LOCK (connection);
2564 status = _dbus_connection_get_dispatch_status_unlocked (connection);
2565 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2566 dbus_pending_call_unref (pending);
2567}
2568
2574int
2576{
2578}
2579
2587void
2589 DBusPendingFdsChangeFunction callback,
2590 void *data)
2591{
2593 callback, data);
2594}
2595
2633dbus_connection_open (const char *address,
2634 DBusError *error)
2635{
2636 DBusConnection *connection;
2637
2638 _dbus_return_val_if_fail (address != NULL, NULL);
2639 _dbus_return_val_if_error_is_set (error, NULL);
2640
2641 connection = _dbus_connection_open_internal (address,
2642 TRUE,
2643 error);
2644
2645 return connection;
2646}
2647
2676dbus_connection_open_private (const char *address,
2677 DBusError *error)
2678{
2679 DBusConnection *connection;
2680
2681 _dbus_return_val_if_fail (address != NULL, NULL);
2682 _dbus_return_val_if_error_is_set (error, NULL);
2683
2684 connection = _dbus_connection_open_internal (address,
2685 FALSE,
2686 error);
2687
2688 return connection;
2689}
2690
2699{
2700 dbus_int32_t old_refcount;
2701
2702 _dbus_return_val_if_fail (connection != NULL, NULL);
2703 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
2704 old_refcount = _dbus_atomic_inc (&connection->refcount);
2705 _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1,
2706 "ref");
2707
2708 return connection;
2709}
2710
2711static void
2712free_outgoing_message (void *element,
2713 void *data)
2714{
2715 DBusMessage *message = element;
2716 DBusConnection *connection = data;
2717
2718 _dbus_message_remove_counter (message, connection->outgoing_counter);
2719 dbus_message_unref (message);
2720}
2721
2722/* This is run without the mutex held, but after the last reference
2723 * to the connection has been dropped we should have no thread-related
2724 * problems
2725 */
2726static void
2727_dbus_connection_last_unref (DBusConnection *connection)
2728{
2729 DBusList *link;
2730
2731 _dbus_verbose ("Finalizing connection %p\n", connection);
2732
2733 _dbus_assert (_dbus_atomic_get (&connection->refcount) == 0);
2734
2735 /* You have to disconnect the connection before unref:ing it. Otherwise
2736 * you won't get the disconnected message.
2737 */
2739 _dbus_assert (connection->server_guid == NULL);
2740
2741 /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
2743
2748
2749 _dbus_watch_list_free (connection->watches);
2750 connection->watches = NULL;
2751
2752 _dbus_timeout_list_free (connection->timeouts);
2753 connection->timeouts = NULL;
2754
2755 _dbus_data_slot_list_free (&connection->slot_list);
2756
2757 link = _dbus_list_get_first_link (&connection->filter_list);
2758 while (link != NULL)
2759 {
2760 DBusMessageFilter *filter = link->data;
2761 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
2762
2763 filter->function = NULL;
2764 _dbus_message_filter_unref (filter); /* calls app callback */
2765 link->data = NULL;
2766
2767 link = next;
2768 }
2769 _dbus_list_clear (&connection->filter_list);
2770
2771 /* ---- Done with stuff that invokes application callbacks */
2772
2773 _dbus_object_tree_unref (connection->objects);
2774
2776 connection->pending_replies = NULL;
2777
2779 free_outgoing_message,
2780 connection);
2781 _dbus_list_clear (&connection->outgoing_messages);
2782
2785
2787
2788 _dbus_transport_unref (connection->transport);
2789
2790 if (connection->disconnect_message_link)
2791 {
2792 DBusMessage *message = connection->disconnect_message_link->data;
2793 dbus_message_unref (message);
2795 }
2796
2799
2802
2804
2805 _dbus_rmutex_free_at_location (&connection->mutex);
2806
2807 dbus_free (connection);
2808}
2809
2829void
2831{
2832 dbus_int32_t old_refcount;
2833
2834 _dbus_return_if_fail (connection != NULL);
2835 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
2836
2837 old_refcount = _dbus_atomic_dec (&connection->refcount);
2838
2839 _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1,
2840 "unref");
2841
2842 if (old_refcount == 1)
2843 {
2844#ifndef DBUS_DISABLE_CHECKS
2846 {
2847 _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",
2848 connection->shareable ?
2849 "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection." :
2850 "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.");
2851 return;
2852 }
2853#endif
2854 _dbus_connection_last_unref (connection);
2855 }
2856}
2857
2858/*
2859 * Note that the transport can disconnect itself (other end drops us)
2860 * and in that case this function never runs. So this function must
2861 * not do anything more than disconnect the transport and update the
2862 * dispatch status.
2863 *
2864 * If the transport self-disconnects, then we assume someone will
2865 * dispatch the connection to cause the dispatch status update.
2866 */
2867static void
2868_dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
2869{
2870 DBusDispatchStatus status;
2871
2872 HAVE_LOCK_CHECK (connection);
2873
2874 _dbus_verbose ("Disconnecting %p\n", connection);
2875
2876 /* We need to ref because update_dispatch_status_and_unlock will unref
2877 * the connection if it was shared and libdbus was the only remaining
2878 * refcount holder.
2879 */
2880 _dbus_connection_ref_unlocked (connection);
2881
2883
2884 /* This has the side effect of queuing the disconnect message link
2885 * (unless we don't have enough memory, possibly, so don't assert it).
2886 * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open
2887 * should never again return the newly-disconnected connection.
2888 *
2889 * However, we only unref the shared connection and exit_on_disconnect when
2890 * the disconnect message reaches the head of the message queue,
2891 * NOT when it's first queued.
2892 */
2893 status = _dbus_connection_get_dispatch_status_unlocked (connection);
2894
2895 /* This calls out to user code */
2896 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2897
2898 /* Could also call out to user code */
2899 dbus_connection_unref (connection);
2900}
2901
2944void
2946{
2947 _dbus_return_if_fail (connection != NULL);
2948 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
2949
2950 CONNECTION_LOCK (connection);
2951
2952#ifndef DBUS_DISABLE_CHECKS
2953 if (connection->shareable)
2954 {
2955 CONNECTION_UNLOCK (connection);
2956
2957 _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.");
2958 return;
2959 }
2960#endif
2961
2962 _dbus_connection_close_possibly_shared_and_unlock (connection);
2963}
2964
2965static dbus_bool_t
2966_dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
2967{
2968 HAVE_LOCK_CHECK (connection);
2969 return _dbus_transport_get_is_connected (connection->transport);
2970}
2971
2987{
2988 dbus_bool_t res;
2989
2990 _dbus_return_val_if_fail (connection != NULL, FALSE);
2991
2992 CONNECTION_LOCK (connection);
2993 res = _dbus_connection_get_is_connected_unlocked (connection);
2994 CONNECTION_UNLOCK (connection);
2995
2996 return res;
2997}
2998
3009{
3010 dbus_bool_t res;
3011
3012 _dbus_return_val_if_fail (connection != NULL, FALSE);
3013
3014 CONNECTION_LOCK (connection);
3016 CONNECTION_UNLOCK (connection);
3017
3018 return res;
3019}
3020
3043{
3044 dbus_bool_t res;
3045
3046 _dbus_return_val_if_fail (connection != NULL, FALSE);
3047
3048 CONNECTION_LOCK (connection);
3049 res = _dbus_transport_get_is_anonymous (connection->transport);
3050 CONNECTION_UNLOCK (connection);
3051
3052 return res;
3053}
3054
3086char*
3088{
3089 char *id;
3090
3091 _dbus_return_val_if_fail (connection != NULL, NULL);
3092
3093 CONNECTION_LOCK (connection);
3095 CONNECTION_UNLOCK (connection);
3096
3097 return id;
3098}
3099
3119 int type)
3120{
3121 _dbus_return_val_if_fail (connection != NULL, FALSE);
3122
3123 if (!dbus_type_is_valid (type))
3124 return FALSE;
3125
3126 if (type != DBUS_TYPE_UNIX_FD)
3127 return TRUE;
3128
3129#ifdef HAVE_UNIX_FD_PASSING
3130 {
3131 dbus_bool_t b;
3132
3133 CONNECTION_LOCK(connection);
3135 CONNECTION_UNLOCK(connection);
3136
3137 return b;
3138 }
3139#endif
3140
3141 return FALSE;
3142}
3143
3157void
3159 dbus_bool_t exit_on_disconnect)
3160{
3161 _dbus_return_if_fail (connection != NULL);
3162
3163 CONNECTION_LOCK (connection);
3164 connection->exit_on_disconnect = exit_on_disconnect != FALSE;
3165 CONNECTION_UNLOCK (connection);
3166}
3167
3179{
3180 DBusPreallocatedSend *preallocated;
3181
3182 _dbus_return_val_if_fail (connection != NULL, NULL);
3183
3184 CONNECTION_LOCK (connection);
3185
3186 preallocated =
3187 _dbus_connection_preallocate_send_unlocked (connection);
3188
3189 CONNECTION_UNLOCK (connection);
3190
3191 return preallocated;
3192}
3193
3203void
3205 DBusPreallocatedSend *preallocated)
3206{
3207 _dbus_return_if_fail (connection != NULL);
3208 _dbus_return_if_fail (preallocated != NULL);
3209 _dbus_return_if_fail (connection == preallocated->connection);
3210
3211 _dbus_list_free_link (preallocated->queue_link);
3212 _dbus_counter_unref (preallocated->counter_link->data);
3213 _dbus_list_free_link (preallocated->counter_link);
3214 dbus_free (preallocated);
3215}
3216
3229void
3231 DBusPreallocatedSend *preallocated,
3232 DBusMessage *message,
3233 dbus_uint32_t *client_serial)
3234{
3235 _dbus_return_if_fail (connection != NULL);
3236 _dbus_return_if_fail (preallocated != NULL);
3237 _dbus_return_if_fail (message != NULL);
3238 _dbus_return_if_fail (preallocated->connection == connection);
3239 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
3240 dbus_message_get_member (message) != NULL);
3241 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
3242 (dbus_message_get_interface (message) != NULL &&
3243 dbus_message_get_member (message) != NULL));
3244
3245 CONNECTION_LOCK (connection);
3246
3247#ifdef HAVE_UNIX_FD_PASSING
3248
3249 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
3250 message->n_unix_fds > 0)
3251 {
3252 /* Refuse to send fds on a connection that cannot handle
3253 them. Unfortunately we cannot return a proper error here, so
3254 the best we can is just return. */
3255 CONNECTION_UNLOCK (connection);
3256 return;
3257 }
3258
3259#endif
3260
3261 _dbus_connection_send_preallocated_and_unlock (connection,
3262 preallocated,
3263 message, client_serial);
3264}
3265
3266static dbus_bool_t
3267_dbus_connection_send_unlocked_no_update (DBusConnection *connection,
3268 DBusMessage *message,
3269 dbus_uint32_t *client_serial)
3270{
3271 DBusPreallocatedSend *preallocated;
3272
3273 _dbus_assert (connection != NULL);
3274 _dbus_assert (message != NULL);
3275
3276 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
3277 if (preallocated == NULL)
3278 return FALSE;
3279
3280 _dbus_connection_send_preallocated_unlocked_no_update (connection,
3281 preallocated,
3282 message,
3283 client_serial);
3284 return TRUE;
3285}
3286
3316 DBusMessage *message,
3317 dbus_uint32_t *serial)
3318{
3319 _dbus_return_val_if_fail (connection != NULL, FALSE);
3320 _dbus_return_val_if_fail (message != NULL, FALSE);
3321
3322 CONNECTION_LOCK (connection);
3323
3324#ifdef HAVE_UNIX_FD_PASSING
3325
3326 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
3327 message->n_unix_fds > 0)
3328 {
3329 /* Refuse to send fds on a connection that cannot handle
3330 them. Unfortunately we cannot return a proper error here, so
3331 the best we can is just return. */
3332 CONNECTION_UNLOCK (connection);
3333 return FALSE;
3334 }
3335
3336#endif
3337
3338 return _dbus_connection_send_and_unlock (connection,
3339 message,
3340 serial);
3341}
3342
3343static dbus_bool_t
3344reply_handler_timeout (void *data)
3345{
3346 DBusConnection *connection;
3347 DBusDispatchStatus status;
3348 DBusPendingCall *pending = data;
3349
3350 connection = _dbus_pending_call_get_connection_and_lock (pending);
3351 _dbus_connection_ref_unlocked (connection);
3352
3354 connection);
3358
3359 _dbus_verbose ("middle\n");
3360 status = _dbus_connection_get_dispatch_status_unlocked (connection);
3361
3362 /* Unlocks, and calls out to user code */
3363 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3364 dbus_connection_unref (connection);
3365
3366 return TRUE;
3367}
3368
3413 DBusMessage *message,
3414 DBusPendingCall **pending_return,
3415 int timeout_milliseconds)
3416{
3417 DBusPendingCall *pending;
3418 dbus_int32_t serial = -1;
3419 DBusDispatchStatus status;
3420
3421 _dbus_return_val_if_fail (connection != NULL, FALSE);
3422 _dbus_return_val_if_fail (message != NULL, FALSE);
3423 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
3424
3425 if (pending_return)
3426 *pending_return = NULL;
3427
3428 CONNECTION_LOCK (connection);
3429
3430#ifdef HAVE_UNIX_FD_PASSING
3431
3432 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
3433 message->n_unix_fds > 0)
3434 {
3435 /* Refuse to send fds on a connection that cannot handle
3436 them. Unfortunately we cannot return a proper error here, so
3437 the best we can do is return TRUE but leave *pending_return
3438 as NULL. */
3439 CONNECTION_UNLOCK (connection);
3440 return TRUE;
3441 }
3442
3443#endif
3444
3445 if (!_dbus_connection_get_is_connected_unlocked (connection))
3446 {
3447 CONNECTION_UNLOCK (connection);
3448
3449 return TRUE;
3450 }
3451
3452 pending = _dbus_pending_call_new_unlocked (connection,
3453 timeout_milliseconds,
3454 reply_handler_timeout);
3455
3456 if (pending == NULL)
3457 {
3458 CONNECTION_UNLOCK (connection);
3459 return FALSE;
3460 }
3461
3462 /* Assign a serial to the message */
3463 serial = dbus_message_get_serial (message);
3464 if (serial == 0)
3465 {
3466 serial = _dbus_connection_get_next_client_serial (connection);
3467 dbus_message_set_serial (message, serial);
3468 }
3469
3470 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
3471 goto error;
3472
3473 /* Insert the serial in the pending replies hash;
3474 * hash takes a refcount on DBusPendingCall.
3475 * Also, add the timeout.
3476 */
3477 if (!_dbus_connection_attach_pending_call_unlocked (connection,
3478 pending))
3479 goto error;
3480
3481 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
3482 {
3483 _dbus_connection_detach_pending_call_and_unlock (connection,
3484 pending);
3485 goto error_unlocked;
3486 }
3487
3488 if (pending_return)
3489 *pending_return = pending; /* hand off refcount */
3490 else
3491 {
3492 _dbus_connection_detach_pending_call_unlocked (connection, pending);
3493 /* we still have a ref to the pending call in this case, we unref
3494 * after unlocking, below
3495 */
3496 }
3497
3498 status = _dbus_connection_get_dispatch_status_unlocked (connection);
3499
3500 /* this calls out to user code */
3501 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3502
3503 if (pending_return == NULL)
3504 dbus_pending_call_unref (pending);
3505
3506 return TRUE;
3507
3508 error:
3509 CONNECTION_UNLOCK (connection);
3510 error_unlocked:
3511 dbus_pending_call_unref (pending);
3512 return FALSE;
3513}
3514
3549 DBusMessage *message,
3550 int timeout_milliseconds,
3551 DBusError *error)
3552{
3553 DBusMessage *reply;
3554 DBusPendingCall *pending;
3555
3556 _dbus_return_val_if_fail (connection != NULL, NULL);
3557 _dbus_return_val_if_fail (message != NULL, NULL);
3558 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
3559 _dbus_return_val_if_error_is_set (error, NULL);
3560
3561#ifdef HAVE_UNIX_FD_PASSING
3562
3563 CONNECTION_LOCK (connection);
3564 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
3565 message->n_unix_fds > 0)
3566 {
3567 CONNECTION_UNLOCK (connection);
3568 dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection.");
3569 return NULL;
3570 }
3571 CONNECTION_UNLOCK (connection);
3572
3573#endif
3574
3575 if (!dbus_connection_send_with_reply (connection, message,
3576 &pending, timeout_milliseconds))
3577 {
3578 _DBUS_SET_OOM (error);
3579 return NULL;
3580 }
3581
3582 if (pending == NULL)
3583 {
3584 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
3585 return NULL;
3586 }
3587
3588 dbus_pending_call_block (pending);
3589
3590 reply = dbus_pending_call_steal_reply (pending);
3591 dbus_pending_call_unref (pending);
3592
3593 /* call_complete_and_unlock() called from pending_call_block() should
3594 * always fill this in.
3595 */
3596 _dbus_assert (reply != NULL);
3597
3598 if (dbus_set_error_from_message (error, reply))
3599 {
3600 dbus_message_unref (reply);
3601 return NULL;
3602 }
3603 else
3604 return reply;
3605}
3606
3615static DBusDispatchStatus
3616_dbus_connection_flush_unlocked (DBusConnection *connection)
3617{
3618 /* We have to specify DBUS_ITERATION_DO_READING here because
3619 * otherwise we could have two apps deadlock if they are both doing
3620 * a flush(), and the kernel buffers fill up. This could change the
3621 * dispatch status.
3622 */
3623 DBusDispatchStatus status;
3624
3625 HAVE_LOCK_CHECK (connection);
3626
3627 while (connection->n_outgoing > 0 &&
3628 _dbus_connection_get_is_connected_unlocked (connection))
3629 {
3630 _dbus_verbose ("doing iteration in\n");
3631 HAVE_LOCK_CHECK (connection);
3633 NULL,
3634 DBUS_ITERATION_DO_READING |
3635 DBUS_ITERATION_DO_WRITING |
3636 DBUS_ITERATION_BLOCK,
3637 -1);
3638 }
3639
3640 HAVE_LOCK_CHECK (connection);
3641 _dbus_verbose ("middle\n");
3642 status = _dbus_connection_get_dispatch_status_unlocked (connection);
3643
3644 HAVE_LOCK_CHECK (connection);
3645 return status;
3646}
3647
3653void
3655{
3656 /* We have to specify DBUS_ITERATION_DO_READING here because
3657 * otherwise we could have two apps deadlock if they are both doing
3658 * a flush(), and the kernel buffers fill up. This could change the
3659 * dispatch status.
3660 */
3661 DBusDispatchStatus status;
3662
3663 _dbus_return_if_fail (connection != NULL);
3664
3665 CONNECTION_LOCK (connection);
3666
3667 status = _dbus_connection_flush_unlocked (connection);
3668
3669 HAVE_LOCK_CHECK (connection);
3670 /* Unlocks and calls out to user code */
3671 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3672
3673 _dbus_verbose ("end\n");
3674}
3675
3686static dbus_bool_t
3687_dbus_connection_read_write_dispatch (DBusConnection *connection,
3688 int timeout_milliseconds,
3689 dbus_bool_t dispatch)
3690{
3691 DBusDispatchStatus dstatus;
3692 dbus_bool_t progress_possible;
3693
3694 /* Need to grab a ref here in case we're a private connection and
3695 * the user drops the last ref in a handler we call; see bug
3696 * https://bugs.freedesktop.org/show_bug.cgi?id=15635
3697 */
3698 dbus_connection_ref (connection);
3699 dstatus = dbus_connection_get_dispatch_status (connection);
3700
3701 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
3702 {
3703 _dbus_verbose ("doing dispatch\n");
3704 dbus_connection_dispatch (connection);
3705 CONNECTION_LOCK (connection);
3706 }
3707 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
3708 {
3709 _dbus_verbose ("pausing for memory\n");
3710 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
3711 CONNECTION_LOCK (connection);
3712 }
3713 else
3714 {
3715 CONNECTION_LOCK (connection);
3716 if (_dbus_connection_get_is_connected_unlocked (connection))
3717 {
3718 _dbus_verbose ("doing iteration\n");
3720 NULL,
3721 DBUS_ITERATION_DO_READING |
3722 DBUS_ITERATION_DO_WRITING |
3723 DBUS_ITERATION_BLOCK,
3724 timeout_milliseconds);
3725 }
3726 }
3727
3728 HAVE_LOCK_CHECK (connection);
3729 /* If we can dispatch, we can make progress until the Disconnected message
3730 * has been processed; if we can only read/write, we can make progress
3731 * as long as the transport is open.
3732 */
3733 if (dispatch)
3734 progress_possible = connection->n_incoming != 0 ||
3735 connection->disconnect_message_link != NULL;
3736 else
3737 progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
3738
3739 CONNECTION_UNLOCK (connection);
3740
3741 dbus_connection_unref (connection);
3742
3743 return progress_possible; /* TRUE if we can make more progress */
3744}
3745
3746
3783 int timeout_milliseconds)
3784{
3785 _dbus_return_val_if_fail (connection != NULL, FALSE);
3786 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
3787 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
3788}
3789
3815 int timeout_milliseconds)
3816{
3817 _dbus_return_val_if_fail (connection != NULL, FALSE);
3818 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
3819 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
3820}
3821
3822/* We need to call this anytime we pop the head of the queue, and then
3823 * update_dispatch_status_and_unlock needs to be called afterward
3824 * which will "process" the disconnected message and set
3825 * disconnected_message_processed.
3826 */
3827static void
3828check_disconnected_message_arrived_unlocked (DBusConnection *connection,
3829 DBusMessage *head_of_queue)
3830{
3831 HAVE_LOCK_CHECK (connection);
3832
3833 /* checking that the link is NULL is an optimization to avoid the is_signal call */
3834 if (connection->disconnect_message_link == NULL &&
3835 dbus_message_is_signal (head_of_queue,
3837 "Disconnected"))
3838 {
3839 connection->disconnected_message_arrived = TRUE;
3840 }
3841}
3842
3864{
3865 DBusDispatchStatus status;
3866 DBusMessage *message;
3867
3868 _dbus_return_val_if_fail (connection != NULL, NULL);
3869
3870 _dbus_verbose ("start\n");
3871
3872 /* this is called for the side effect that it queues
3873 * up any messages from the transport
3874 */
3875 status = dbus_connection_get_dispatch_status (connection);
3876 if (status != DBUS_DISPATCH_DATA_REMAINS)
3877 return NULL;
3878
3879 CONNECTION_LOCK (connection);
3880
3881 _dbus_connection_acquire_dispatch (connection);
3882
3883 /* While a message is outstanding, the dispatch lock is held */
3884 _dbus_assert (connection->message_borrowed == NULL);
3885
3886 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
3887
3888 message = connection->message_borrowed;
3889
3890 check_disconnected_message_arrived_unlocked (connection, message);
3891
3892 /* Note that we KEEP the dispatch lock until the message is returned */
3893 if (message == NULL)
3894 _dbus_connection_release_dispatch (connection);
3895
3896 CONNECTION_UNLOCK (connection);
3897
3898 _dbus_message_trace_ref (message, -1, -1, "dbus_connection_borrow_message");
3899
3900 /* We don't update dispatch status until it's returned or stolen */
3901
3902 return message;
3903}
3904
3913void
3915 DBusMessage *message)
3916{
3917 DBusDispatchStatus status;
3918
3919 _dbus_return_if_fail (connection != NULL);
3920 _dbus_return_if_fail (message != NULL);
3921 _dbus_return_if_fail (message == connection->message_borrowed);
3922 _dbus_return_if_fail (connection->dispatch_acquired);
3923
3924 CONNECTION_LOCK (connection);
3925
3926 _dbus_assert (message == connection->message_borrowed);
3927
3928 connection->message_borrowed = NULL;
3929
3930 _dbus_connection_release_dispatch (connection);
3931
3932 status = _dbus_connection_get_dispatch_status_unlocked (connection);
3933 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3934
3935 _dbus_message_trace_ref (message, -1, -1, "dbus_connection_return_message");
3936}
3937
3947void
3949 DBusMessage *message)
3950{
3951 DBusMessage *pop_message;
3952 DBusDispatchStatus status;
3953
3954 _dbus_return_if_fail (connection != NULL);
3955 _dbus_return_if_fail (message != NULL);
3956 _dbus_return_if_fail (message == connection->message_borrowed);
3957 _dbus_return_if_fail (connection->dispatch_acquired);
3958
3959 CONNECTION_LOCK (connection);
3960
3961 _dbus_assert (message == connection->message_borrowed);
3962
3963 pop_message = _dbus_list_pop_first (&connection->incoming_messages);
3964 _dbus_assert (message == pop_message);
3965 (void) pop_message; /* unused unless asserting */
3966
3967 connection->n_incoming -= 1;
3968
3969 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
3970 message, connection->n_incoming);
3971
3972 connection->message_borrowed = NULL;
3973
3974 _dbus_connection_release_dispatch (connection);
3975
3976 status = _dbus_connection_get_dispatch_status_unlocked (connection);
3977 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3978 _dbus_message_trace_ref (message, -1, -1,
3979 "dbus_connection_steal_borrowed_message");
3980}
3981
3982/* See dbus_connection_pop_message, but requires the caller to own
3983 * the lock before calling. May drop the lock while running.
3984 */
3985static DBusList*
3986_dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
3987{
3988 HAVE_LOCK_CHECK (connection);
3989
3990 _dbus_assert (connection->message_borrowed == NULL);
3991
3992 if (connection->n_incoming > 0)
3993 {
3994 DBusList *link;
3995
3996 link = _dbus_list_pop_first_link (&connection->incoming_messages);
3997 connection->n_incoming -= 1;
3998
3999 _dbus_verbose ("Message %p (%s %s %s %s sig:'%s' serial:%u) removed from incoming queue %p, %d incoming\n",
4000 link->data,
4002 dbus_message_get_path (link->data) ?
4003 dbus_message_get_path (link->data) :
4004 "no path",
4007 "no interface",
4010 "no member",
4013 connection, connection->n_incoming);
4014
4015 _dbus_message_trace_ref (link->data, -1, -1,
4016 "_dbus_connection_pop_message_link_unlocked");
4017
4018 check_disconnected_message_arrived_unlocked (connection, link->data);
4019
4020 return link;
4021 }
4022 else
4023 return NULL;
4024}
4025
4026/* See dbus_connection_pop_message, but requires the caller to own
4027 * the lock before calling. May drop the lock while running.
4028 */
4029static DBusMessage*
4030_dbus_connection_pop_message_unlocked (DBusConnection *connection)
4031{
4032 DBusList *link;
4033
4034 HAVE_LOCK_CHECK (connection);
4035
4036 link = _dbus_connection_pop_message_link_unlocked (connection);
4037
4038 if (link != NULL)
4039 {
4040 DBusMessage *message;
4041
4042 message = link->data;
4043
4044 _dbus_list_free_link (link);
4045
4046 return message;
4047 }
4048 else
4049 return NULL;
4050}
4051
4052static void
4053_dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
4054 DBusList *message_link)
4055{
4056 HAVE_LOCK_CHECK (connection);
4057
4058 _dbus_assert (message_link != NULL);
4059 /* You can't borrow a message while a link is outstanding */
4060 _dbus_assert (connection->message_borrowed == NULL);
4061 /* We had to have the dispatch lock across the pop/putback */
4062 _dbus_assert (connection->dispatch_acquired);
4063
4065 message_link);
4066 connection->n_incoming += 1;
4067
4068 _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n",
4069 message_link->data,
4071 dbus_message_get_interface (message_link->data) ?
4072 dbus_message_get_interface (message_link->data) :
4073 "no interface",
4074 dbus_message_get_member (message_link->data) ?
4075 dbus_message_get_member (message_link->data) :
4076 "no member",
4077 dbus_message_get_signature (message_link->data),
4078 connection, connection->n_incoming);
4079
4080 _dbus_message_trace_ref (message_link->data, -1, -1,
4081 "_dbus_connection_putback_message_link_unlocked");
4082}
4083
4105{
4106 DBusMessage *message;
4107 DBusDispatchStatus status;
4108
4109 _dbus_verbose ("start\n");
4110
4111 /* this is called for the side effect that it queues
4112 * up any messages from the transport
4113 */
4114 status = dbus_connection_get_dispatch_status (connection);
4115 if (status != DBUS_DISPATCH_DATA_REMAINS)
4116 return NULL;
4117
4118 CONNECTION_LOCK (connection);
4119 _dbus_connection_acquire_dispatch (connection);
4120 HAVE_LOCK_CHECK (connection);
4121
4122 message = _dbus_connection_pop_message_unlocked (connection);
4123
4124 _dbus_verbose ("Returning popped message %p\n", message);
4125
4126 _dbus_connection_release_dispatch (connection);
4127
4128 status = _dbus_connection_get_dispatch_status_unlocked (connection);
4129 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
4130
4131 return message;
4132}
4133
4141static void
4142_dbus_connection_acquire_dispatch (DBusConnection *connection)
4143{
4144 HAVE_LOCK_CHECK (connection);
4145
4146 _dbus_connection_ref_unlocked (connection);
4147 CONNECTION_UNLOCK (connection);
4148
4149 _dbus_verbose ("locking dispatch_mutex\n");
4150 _dbus_cmutex_lock (connection->dispatch_mutex);
4151
4152 while (connection->dispatch_acquired)
4153 {
4154 _dbus_verbose ("waiting for dispatch to be acquirable\n");
4155 _dbus_condvar_wait (connection->dispatch_cond,
4156 connection->dispatch_mutex);
4157 }
4158
4159 _dbus_assert (!connection->dispatch_acquired);
4160
4161 connection->dispatch_acquired = TRUE;
4162
4163 _dbus_verbose ("unlocking dispatch_mutex\n");
4164 _dbus_cmutex_unlock (connection->dispatch_mutex);
4165
4166 CONNECTION_LOCK (connection);
4168}
4169
4177static void
4178_dbus_connection_release_dispatch (DBusConnection *connection)
4179{
4180 HAVE_LOCK_CHECK (connection);
4181
4182 _dbus_verbose ("locking dispatch_mutex\n");
4183 _dbus_cmutex_lock (connection->dispatch_mutex);
4184
4185 _dbus_assert (connection->dispatch_acquired);
4186
4187 connection->dispatch_acquired = FALSE;
4189
4190 _dbus_verbose ("unlocking dispatch_mutex\n");
4191 _dbus_cmutex_unlock (connection->dispatch_mutex);
4192}
4193
4194static void
4195_dbus_connection_failed_pop (DBusConnection *connection,
4196 DBusList *message_link)
4197{
4199 message_link);
4200 connection->n_incoming += 1;
4201}
4202
4203/* Note this may be called multiple times since we don't track whether we already did it */
4204static void
4205notify_disconnected_unlocked (DBusConnection *connection)
4206{
4207 HAVE_LOCK_CHECK (connection);
4208
4209 /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected
4210 * connection from dbus_bus_get(). We make the same guarantee for
4211 * dbus_connection_open() but in a different way since we don't want to
4212 * unref right here; we instead check for connectedness before returning
4213 * the connection from the hash.
4214 */
4216
4217 /* Dump the outgoing queue, we aren't going to be able to
4218 * send it now, and we'd like accessors like
4219 * dbus_connection_get_outgoing_size() to be accurate.
4220 */
4221 if (connection->n_outgoing > 0)
4222 {
4223 DBusList *link;
4224
4225 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
4226 connection->n_outgoing);
4227
4228 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
4229 {
4230 _dbus_connection_message_sent_unlocked (connection, link->data);
4231 }
4232 }
4233}
4234
4235/* Note this may be called multiple times since we don't track whether we already did it */
4236static DBusDispatchStatus
4237notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
4238{
4239 HAVE_LOCK_CHECK (connection);
4240
4241 if (connection->disconnect_message_link != NULL)
4242 {
4243 _dbus_verbose ("Sending disconnect message\n");
4244
4245 /* If we have pending calls, queue their timeouts - we want the Disconnected
4246 * to be the last message, after these timeouts.
4247 */
4248 connection_timeout_and_complete_all_pending_calls_unlocked (connection);
4249
4250 /* We haven't sent the disconnect message already,
4251 * and all real messages have been queued up.
4252 */
4254 connection->disconnect_message_link);
4255 connection->disconnect_message_link = NULL;
4256
4258 }
4259
4261}
4262
4263static DBusDispatchStatus
4264_dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
4265{
4266 HAVE_LOCK_CHECK (connection);
4267
4268 if (connection->n_incoming > 0)
4270 else if (!_dbus_transport_queue_messages (connection->transport))
4272 else
4273 {
4274 DBusDispatchStatus status;
4275 dbus_bool_t is_connected;
4276
4277 status = _dbus_transport_get_dispatch_status (connection->transport);
4278 is_connected = _dbus_transport_get_is_connected (connection->transport);
4279
4280 _dbus_verbose ("dispatch status = %s is_connected = %d\n",
4281 DISPATCH_STATUS_NAME (status), is_connected);
4282
4283 if (!is_connected)
4284 {
4285 /* It's possible this would be better done by having an explicit
4286 * notification from _dbus_transport_disconnect() that would
4287 * synchronously do this, instead of waiting for the next dispatch
4288 * status check. However, probably not good to change until it causes
4289 * a problem.
4290 */
4291 notify_disconnected_unlocked (connection);
4292
4293 /* I'm not sure this is needed; the idea is that we want to
4294 * queue the Disconnected only after we've read all the
4295 * messages, but if we're disconnected maybe we are guaranteed
4296 * to have read them all ?
4297 */
4298 if (status == DBUS_DISPATCH_COMPLETE)
4299 status = notify_disconnected_and_dispatch_complete_unlocked (connection);
4300 }
4301
4302 if (status != DBUS_DISPATCH_COMPLETE)
4303 return status;
4304 else if (connection->n_incoming > 0)
4306 else
4308 }
4309}
4310
4311static void
4312_dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
4313 DBusDispatchStatus new_status)
4314{
4315 dbus_bool_t changed;
4317 void *data;
4318
4319 HAVE_LOCK_CHECK (connection);
4320
4321 _dbus_connection_ref_unlocked (connection);
4322
4323 changed = new_status != connection->last_dispatch_status;
4324
4325 connection->last_dispatch_status = new_status;
4326
4327 function = connection->dispatch_status_function;
4328 data = connection->dispatch_status_data;
4329
4330 if (connection->disconnected_message_arrived &&
4331 !connection->disconnected_message_processed)
4332 {
4334
4335 /* this does an unref, but we have a ref
4336 * so we should not run the finalizer here
4337 * inside the lock.
4338 */
4339 connection_forget_shared_unlocked (connection);
4340
4341 if (connection->exit_on_disconnect)
4342 {
4343 CONNECTION_UNLOCK (connection);
4344
4345 _dbus_verbose ("Exiting on Disconnected signal\n");
4346 _dbus_exit (1);
4347 _dbus_assert_not_reached ("Call to exit() returned");
4348 }
4349 }
4350
4351 /* We drop the lock */
4352 CONNECTION_UNLOCK (connection);
4353
4354 if (changed && function)
4355 {
4356 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
4357 connection, new_status,
4358 DISPATCH_STATUS_NAME (new_status));
4359 (* function) (connection, new_status, data);
4360 }
4361
4362 dbus_connection_unref (connection);
4363}
4364
4392{
4393 DBusDispatchStatus status;
4394
4395 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
4396
4397 _dbus_verbose ("start\n");
4398
4399 CONNECTION_LOCK (connection);
4400
4401 status = _dbus_connection_get_dispatch_status_unlocked (connection);
4402
4403 CONNECTION_UNLOCK (connection);
4404
4405 return status;
4406}
4407
4411static DBusHandlerResult
4412_dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
4413 DBusMessage *message)
4414{
4415 dbus_bool_t sent = FALSE;
4416 DBusMessage *ret = NULL;
4417 DBusList *expire_link;
4418
4419 if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
4420 {
4421 /* This means we're letting the bus route this message */
4423 }
4424
4426 {
4428 }
4429
4430 /* Preallocate a linked-list link, so that if we need to dispose of a
4431 * message, we can attach it to the expired list */
4432 expire_link = _dbus_list_alloc_link (NULL);
4433
4434 if (!expire_link)
4436
4437 if (dbus_message_is_method_call (message,
4439 "Ping"))
4440 {
4441 ret = dbus_message_new_method_return (message);
4442 if (ret == NULL)
4443 goto out;
4444
4445 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
4446 }
4447 else if (dbus_message_is_method_call (message,
4449 "GetMachineId"))
4450 {
4451 DBusString uuid;
4452 DBusError error = DBUS_ERROR_INIT;
4453
4454 if (!_dbus_string_init (&uuid))
4455 goto out;
4456
4457 if (_dbus_get_local_machine_uuid_encoded (&uuid, &error))
4458 {
4459 const char *v_STRING;
4460
4461 ret = dbus_message_new_method_return (message);
4462
4463 if (ret == NULL)
4464 {
4465 _dbus_string_free (&uuid);
4466 goto out;
4467 }
4468
4469 v_STRING = _dbus_string_get_const_data (&uuid);
4470 if (dbus_message_append_args (ret,
4471 DBUS_TYPE_STRING, &v_STRING,
4473 {
4474 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
4475 }
4476 }
4477 else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
4478 {
4479 dbus_error_free (&error);
4480 goto out;
4481 }
4482 else
4483 {
4484 ret = dbus_message_new_error (message, error.name, error.message);
4485 dbus_error_free (&error);
4486
4487 if (ret == NULL)
4488 goto out;
4489
4490 sent = _dbus_connection_send_unlocked_no_update (connection, ret,
4491 NULL);
4492 }
4493
4494 _dbus_string_free (&uuid);
4495 }
4496 else
4497 {
4498 /* We need to bounce anything else with this interface, otherwise apps
4499 * could start extending the interface and when we added extensions
4500 * here to DBusConnection we'd break those apps.
4501 */
4502 ret = dbus_message_new_error (message,
4504 "Unknown method invoked on org.freedesktop.DBus.Peer interface");
4505 if (ret == NULL)
4506 goto out;
4507
4508 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
4509 }
4510
4511out:
4512 if (ret == NULL)
4513 {
4514 _dbus_list_free_link (expire_link);
4515 }
4516 else
4517 {
4518 /* It'll be safe to unref the reply when we unlock */
4519 expire_link->data = ret;
4520 _dbus_list_prepend_link (&connection->expired_messages, expire_link);
4521 }
4522
4523 if (!sent)
4525
4527}
4528
4535static DBusHandlerResult
4536_dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
4537 DBusMessage *message)
4538{
4539 /* We just run one filter for now but have the option to run more
4540 if the spec calls for it in the future */
4541
4542 return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
4543}
4544
4589{
4590 DBusMessage *message;
4591 DBusList *link, *filter_list_copy, *message_link;
4592 DBusHandlerResult result;
4593 DBusPendingCall *pending;
4594 dbus_int32_t reply_serial;
4595 DBusDispatchStatus status;
4596 dbus_bool_t found_object;
4597
4598 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
4599
4600 _dbus_verbose ("\n");
4601
4602 CONNECTION_LOCK (connection);
4603 status = _dbus_connection_get_dispatch_status_unlocked (connection);
4604 if (status != DBUS_DISPATCH_DATA_REMAINS)
4605 {
4606 /* unlocks and calls out to user code */
4607 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
4608 return status;
4609 }
4610
4611 /* We need to ref the connection since the callback could potentially
4612 * drop the last ref to it
4613 */
4614 _dbus_connection_ref_unlocked (connection);
4615
4616 _dbus_connection_acquire_dispatch (connection);
4617 HAVE_LOCK_CHECK (connection);
4618
4619 message_link = _dbus_connection_pop_message_link_unlocked (connection);
4620 if (message_link == NULL)
4621 {
4622 /* another thread dispatched our stuff */
4623
4624 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
4625
4626 _dbus_connection_release_dispatch (connection);
4627
4628 status = _dbus_connection_get_dispatch_status_unlocked (connection);
4629
4630 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
4631
4632 dbus_connection_unref (connection);
4633
4634 return status;
4635 }
4636
4637 message = message_link->data;
4638
4639 _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n",
4640 message,
4642 dbus_message_get_interface (message) ?
4643 dbus_message_get_interface (message) :
4644 "no interface",
4645 dbus_message_get_member (message) ?
4646 dbus_message_get_member (message) :
4647 "no member",
4648 dbus_message_get_signature (message));
4649
4651
4652 /* Pending call handling must be first, because if you do
4653 * dbus_connection_send_with_reply_and_block() or
4654 * dbus_pending_call_block() then no handlers/filters will be run on
4655 * the reply. We want consistent semantics in the case where we
4656 * dbus_connection_dispatch() the reply.
4657 */
4658
4659 reply_serial = dbus_message_get_reply_serial (message);
4660 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
4661 reply_serial);
4662 if (pending)
4663 {
4664 _dbus_verbose ("Dispatching a pending reply\n");
4665 complete_pending_call_and_unlock (connection, pending, message);
4666 pending = NULL; /* it's probably unref'd */
4667
4668 CONNECTION_LOCK (connection);
4669 _dbus_verbose ("pending call completed in dispatch\n");
4671 goto out;
4672 }
4673
4674 /* If skipping builtin filters, we are probably a monitor. */
4675 if (connection->builtin_filters_enabled)
4676 {
4677 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
4679 goto out;
4680 }
4681
4682 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
4683 {
4684 _dbus_connection_release_dispatch (connection);
4685 HAVE_LOCK_CHECK (connection);
4686
4687 _dbus_connection_failed_pop (connection, message_link);
4688
4689 /* unlocks and calls user code */
4690 _dbus_connection_update_dispatch_status_and_unlock (connection,
4692 dbus_connection_unref (connection);
4693
4695 }
4696
4697 for (link = _dbus_list_get_first_link (&filter_list_copy);
4698 link != NULL;
4699 link = _dbus_list_get_next_link (&filter_list_copy, link))
4700 _dbus_message_filter_ref (link->data);
4701
4702 /* We're still protected from dispatch() reentrancy here
4703 * since we acquired the dispatcher
4704 */
4705 CONNECTION_UNLOCK (connection);
4706
4707 link = _dbus_list_get_first_link (&filter_list_copy);
4708 while (link != NULL)
4709 {
4710 DBusMessageFilter *filter = link->data;
4711 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
4712
4713 if (filter->function == NULL)
4714 {
4715 _dbus_verbose (" filter was removed in a callback function\n");
4716 link = next;
4717 continue;
4718 }
4719
4720 _dbus_verbose (" running filter on message %p\n", message);
4721 result = (* filter->function) (connection, message, filter->user_data);
4722
4724 break;
4725
4726 link = next;
4727 }
4728
4729 _dbus_list_clear_full (&filter_list_copy,
4730 (DBusFreeFunction) _dbus_message_filter_unref);
4731
4732 CONNECTION_LOCK (connection);
4733
4734 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
4735 {
4736 _dbus_verbose ("No memory\n");
4737 goto out;
4738 }
4739 else if (result == DBUS_HANDLER_RESULT_HANDLED)
4740 {
4741 _dbus_verbose ("filter handled message in dispatch\n");
4742 goto out;
4743 }
4744
4745 /* We're still protected from dispatch() reentrancy here
4746 * since we acquired the dispatcher
4747 */
4748 _dbus_verbose (" running object path dispatch on message %p (%s %s %s '%s')\n",
4749 message,
4751 dbus_message_get_interface (message) ?
4752 dbus_message_get_interface (message) :
4753 "no interface",
4754 dbus_message_get_member (message) ?
4755 dbus_message_get_member (message) :
4756 "no member",
4757 dbus_message_get_signature (message));
4758
4759 HAVE_LOCK_CHECK (connection);
4760 result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
4761 message,
4762 &found_object);
4763
4764 CONNECTION_LOCK (connection);
4765
4767 {
4768 _dbus_verbose ("object tree handled message in dispatch\n");
4769 goto out;
4770 }
4771
4773 {
4774 DBusMessage *reply;
4775 DBusString str;
4776 DBusPreallocatedSend *preallocated;
4777 DBusList *expire_link;
4778
4779 _dbus_verbose (" sending error %s\n",
4781
4782 if (!_dbus_string_init (&str))
4783 {
4785 _dbus_verbose ("no memory for error string in dispatch\n");
4786 goto out;
4787 }
4788
4789 if (!_dbus_string_append_printf (&str,
4790 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
4791 dbus_message_get_member (message),
4793 dbus_message_get_interface (message)))
4794 {
4795 _dbus_string_free (&str);
4797 _dbus_verbose ("no memory for error string in dispatch\n");
4798 goto out;
4799 }
4800
4801 reply = dbus_message_new_error (message,
4804 _dbus_string_free (&str);
4805
4806 if (reply == NULL)
4807 {
4809 _dbus_verbose ("no memory for error reply in dispatch\n");
4810 goto out;
4811 }
4812
4813 expire_link = _dbus_list_alloc_link (reply);
4814
4815 if (expire_link == NULL)
4816 {
4817 dbus_message_unref (reply);
4819 _dbus_verbose ("no memory for error send in dispatch\n");
4820 goto out;
4821 }
4822
4823 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
4824
4825 if (preallocated == NULL)
4826 {
4827 _dbus_list_free_link (expire_link);
4828 /* It's OK that this is finalized, because it hasn't been seen by
4829 * anything that could attach user callbacks */
4830 dbus_message_unref (reply);
4832 _dbus_verbose ("no memory for error send in dispatch\n");
4833 goto out;
4834 }
4835
4836 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
4837 reply, NULL);
4838 /* reply will be freed when we release the lock */
4839 _dbus_list_prepend_link (&connection->expired_messages, expire_link);
4840
4842 }
4843
4844 _dbus_verbose (" done dispatching %p (%s %s %s '%s') on connection %p\n", message,
4846 dbus_message_get_interface (message) ?
4847 dbus_message_get_interface (message) :
4848 "no interface",
4849 dbus_message_get_member (message) ?
4850 dbus_message_get_member (message) :
4851 "no member",
4853 connection);
4854
4855 out:
4856 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
4857 {
4858 _dbus_verbose ("out of memory\n");
4859
4860 /* Put message back, and we'll start over.
4861 * Yes this means handlers must be idempotent if they
4862 * don't return HANDLED; c'est la vie.
4863 */
4864 _dbus_connection_putback_message_link_unlocked (connection,
4865 message_link);
4866 /* now we don't want to free them */
4867 message_link = NULL;
4868 message = NULL;
4869 }
4870 else
4871 {
4872 _dbus_verbose (" ... done dispatching\n");
4873 }
4874
4875 _dbus_connection_release_dispatch (connection);
4876 HAVE_LOCK_CHECK (connection);
4877
4878 if (message != NULL)
4879 {
4880 /* We don't want this message to count in maximum message limits when
4881 * computing the dispatch status, below. We have to drop the lock
4882 * temporarily, because finalizing a message can trigger callbacks.
4883 *
4884 * We have a reference to the connection, and we don't use any cached
4885 * pointers to the connection's internals below this point, so it should
4886 * be safe to drop the lock and take it back. */
4887 CONNECTION_UNLOCK (connection);
4888 dbus_message_unref (message);
4889 CONNECTION_LOCK (connection);
4890 }
4891
4892 if (message_link != NULL)
4893 _dbus_list_free_link (message_link);
4894
4895 _dbus_verbose ("before final status update\n");
4896 status = _dbus_connection_get_dispatch_status_unlocked (connection);
4897
4898 /* unlocks and calls user code */
4899 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
4900
4901 dbus_connection_unref (connection);
4902
4903 return status;
4904}
4905
4969 DBusAddWatchFunction add_function,
4970 DBusRemoveWatchFunction remove_function,
4971 DBusWatchToggledFunction toggled_function,
4972 void *data,
4973 DBusFreeFunction free_data_function)
4974{
4975 dbus_bool_t retval;
4976
4977 _dbus_return_val_if_fail (connection != NULL, FALSE);
4978
4979 CONNECTION_LOCK (connection);
4980
4981 retval = _dbus_watch_list_set_functions (connection->watches,
4982 add_function, remove_function,
4983 toggled_function,
4984 data, free_data_function);
4985
4986 CONNECTION_UNLOCK (connection);
4987
4988 return retval;
4989}
4990
5032 DBusAddTimeoutFunction add_function,
5033 DBusRemoveTimeoutFunction remove_function,
5034 DBusTimeoutToggledFunction toggled_function,
5035 void *data,
5036 DBusFreeFunction free_data_function)
5037{
5038 dbus_bool_t retval;
5039
5040 _dbus_return_val_if_fail (connection != NULL, FALSE);
5041
5042 CONNECTION_LOCK (connection);
5043
5044 retval = _dbus_timeout_list_set_functions (connection->timeouts,
5045 add_function, remove_function,
5046 toggled_function,
5047 data, free_data_function);
5048
5049 CONNECTION_UNLOCK (connection);
5050
5051 return retval;
5052}
5053
5068void
5070 DBusWakeupMainFunction wakeup_main_function,
5071 void *data,
5072 DBusFreeFunction free_data_function)
5073{
5074 void *old_data;
5075 DBusFreeFunction old_free_data;
5076
5077 _dbus_return_if_fail (connection != NULL);
5078
5079 CONNECTION_LOCK (connection);
5080 old_data = connection->wakeup_main_data;
5081 old_free_data = connection->free_wakeup_main_data;
5082
5083 connection->wakeup_main_function = wakeup_main_function;
5084 connection->wakeup_main_data = data;
5085 connection->free_wakeup_main_data = free_data_function;
5086
5087 CONNECTION_UNLOCK (connection);
5088
5089 /* Callback outside the lock */
5090 if (old_free_data)
5091 (*old_free_data) (old_data);
5092}
5093
5114void
5117 void *data,
5118 DBusFreeFunction free_data_function)
5119{
5120 void *old_data;
5121 DBusFreeFunction old_free_data;
5122
5123 _dbus_return_if_fail (connection != NULL);
5124
5125 CONNECTION_LOCK (connection);
5126 old_data = connection->dispatch_status_data;
5127 old_free_data = connection->free_dispatch_status_data;
5128
5129 connection->dispatch_status_function = function;
5130 connection->dispatch_status_data = data;
5131 connection->free_dispatch_status_data = free_data_function;
5132
5133 CONNECTION_UNLOCK (connection);
5134
5135 /* Callback outside the lock */
5136 if (old_free_data)
5137 (*old_free_data) (old_data);
5138}
5139
5161 int *fd)
5162{
5163 _dbus_return_val_if_fail (connection != NULL, FALSE);
5164 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
5165
5166#ifdef DBUS_WIN
5167 /* FIXME do this on a lower level */
5168 return FALSE;
5169#endif
5170
5171 return dbus_connection_get_socket(connection, fd);
5172}
5173
5191 int *fd)
5192{
5193 dbus_bool_t retval;
5194 DBusSocket s = DBUS_SOCKET_INIT;
5195
5196 _dbus_return_val_if_fail (connection != NULL, FALSE);
5197 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
5198
5199 CONNECTION_LOCK (connection);
5200
5201 retval = _dbus_transport_get_socket_fd (connection->transport, &s);
5202
5203 if (retval)
5204 {
5205 *fd = _dbus_socket_get_int (s);
5206 }
5207
5208 CONNECTION_UNLOCK (connection);
5209
5210 return retval;
5211}
5212
5213
5238 unsigned long *uid)
5239{
5240 dbus_bool_t result;
5241
5242 _dbus_return_val_if_fail (connection != NULL, FALSE);
5243 _dbus_return_val_if_fail (uid != NULL, FALSE);
5244
5245 CONNECTION_LOCK (connection);
5246
5248 result = FALSE;
5249 else
5250 result = _dbus_transport_get_unix_user (connection->transport,
5251 uid);
5252
5253#ifdef DBUS_WIN
5254 _dbus_assert (!result);
5255#endif
5256
5257 CONNECTION_UNLOCK (connection);
5258
5259 return result;
5260}
5261
5274 unsigned long *pid)
5275{
5276 dbus_bool_t result;
5277
5278 _dbus_return_val_if_fail (connection != NULL, FALSE);
5279 _dbus_return_val_if_fail (pid != NULL, FALSE);
5280
5281 CONNECTION_LOCK (connection);
5282
5284 result = FALSE;
5285 else
5286 result = _dbus_transport_get_unix_process_id (connection->transport,
5287 pid);
5288
5289 CONNECTION_UNLOCK (connection);
5290
5291 return result;
5292}
5293
5307 void **data,
5308 dbus_int32_t *data_size)
5309{
5310 dbus_bool_t result;
5311
5312 _dbus_return_val_if_fail (connection != NULL, FALSE);
5313 _dbus_return_val_if_fail (data != NULL, FALSE);
5314 _dbus_return_val_if_fail (data_size != NULL, FALSE);
5315
5316 CONNECTION_LOCK (connection);
5317
5319 result = FALSE;
5320 else
5322 data,
5323 data_size);
5324 CONNECTION_UNLOCK (connection);
5325
5326 return result;
5327}
5328
5351void
5354 void *data,
5355 DBusFreeFunction free_data_function)
5356{
5357 void *old_data = NULL;
5358 DBusFreeFunction old_free_function = NULL;
5359
5360 _dbus_return_if_fail (connection != NULL);
5361
5362 CONNECTION_LOCK (connection);
5364 function, data, free_data_function,
5365 &old_data, &old_free_function);
5366 CONNECTION_UNLOCK (connection);
5367
5368 if (old_free_function != NULL)
5369 (* old_free_function) (old_data);
5370}
5371
5372/* Same calling convention as dbus_connection_get_windows_user */
5374_dbus_connection_get_linux_security_label (DBusConnection *connection,
5375 char **label_p)
5376{
5377 dbus_bool_t result;
5378
5379 _dbus_assert (connection != NULL);
5380 _dbus_assert (label_p != NULL);
5381
5382 CONNECTION_LOCK (connection);
5383
5385 result = FALSE;
5386 else
5387 result = _dbus_transport_get_linux_security_label (connection->transport,
5388 label_p);
5389#ifndef __linux__
5390 _dbus_assert (!result);
5391#endif
5392
5393 CONNECTION_UNLOCK (connection);
5394
5395 return result;
5396}
5397
5399_dbus_connection_get_credentials (DBusConnection *connection)
5400{
5401 DBusCredentials *result;
5402
5403 _dbus_assert (connection != NULL);
5404
5405 CONNECTION_LOCK (connection);
5406
5408 result = NULL;
5409 else
5410 result = _dbus_transport_get_credentials (connection->transport);
5411
5412 CONNECTION_UNLOCK (connection);
5413
5414 return result;
5415}
5416
5450 char **windows_sid_p)
5451{
5452 dbus_bool_t result;
5453
5454 _dbus_return_val_if_fail (connection != NULL, FALSE);
5455 _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
5456
5457 CONNECTION_LOCK (connection);
5458
5460 result = FALSE;
5461 else
5462 result = _dbus_transport_get_windows_user (connection->transport,
5463 windows_sid_p);
5464
5465#ifdef DBUS_UNIX
5466 _dbus_assert (!result);
5467#endif
5468
5469 CONNECTION_UNLOCK (connection);
5470
5471 return result;
5472}
5473
5495void
5498 void *data,
5499 DBusFreeFunction free_data_function)
5500{
5501 void *old_data = NULL;
5502 DBusFreeFunction old_free_function = NULL;
5503
5504 _dbus_return_if_fail (connection != NULL);
5505
5506 CONNECTION_LOCK (connection);
5508 function, data, free_data_function,
5509 &old_data, &old_free_function);
5510 CONNECTION_UNLOCK (connection);
5511
5512 if (old_free_function != NULL)
5513 (* old_free_function) (old_data);
5514}
5515
5542void
5544 dbus_bool_t value)
5545{
5546 _dbus_return_if_fail (connection != NULL);
5547
5548 CONNECTION_LOCK (connection);
5550 CONNECTION_UNLOCK (connection);
5551}
5552
5574void
5576 dbus_bool_t value)
5577{
5578 _dbus_return_if_fail (connection != NULL);
5579
5580 CONNECTION_LOCK (connection);
5581 connection->builtin_filters_enabled = value;
5582 CONNECTION_UNLOCK (connection);
5583}
5584
5602void
5604 dbus_bool_t value)
5605{
5606 _dbus_return_if_fail (connection != NULL);
5607
5608 CONNECTION_LOCK (connection);
5609 connection->route_peer_messages = value;
5610 CONNECTION_UNLOCK (connection);
5611}
5612
5637 void *user_data,
5638 DBusFreeFunction free_data_function)
5639{
5640 DBusMessageFilter *filter;
5641
5642 _dbus_return_val_if_fail (connection != NULL, FALSE);
5643 _dbus_return_val_if_fail (function != NULL, FALSE);
5644
5645 filter = dbus_new0 (DBusMessageFilter, 1);
5646 if (filter == NULL)
5647 return FALSE;
5648
5649 _dbus_atomic_inc (&filter->refcount);
5650
5651 CONNECTION_LOCK (connection);
5652
5653 if (!_dbus_list_append (&connection->filter_list,
5654 filter))
5655 {
5656 _dbus_message_filter_unref (filter);
5657 CONNECTION_UNLOCK (connection);
5658 return FALSE;
5659 }
5660
5661 /* Fill in filter after all memory allocated,
5662 * so we don't run the free_user_data_function
5663 * if the add_filter() fails
5664 */
5665
5666 filter->function = function;
5667 filter->user_data = user_data;
5668 filter->free_user_data_function = free_data_function;
5669
5670 CONNECTION_UNLOCK (connection);
5671 return TRUE;
5672}
5673
5686void
5689 void *user_data)
5690{
5691 DBusList *link;
5692 DBusMessageFilter *filter;
5693
5694 _dbus_return_if_fail (connection != NULL);
5695 _dbus_return_if_fail (function != NULL);
5696
5697 CONNECTION_LOCK (connection);
5698
5699 filter = NULL;
5700
5701 link = _dbus_list_get_last_link (&connection->filter_list);
5702 while (link != NULL)
5703 {
5704 filter = link->data;
5705
5706 if (filter->function == function &&
5707 filter->user_data == user_data)
5708 {
5709 _dbus_list_remove_link (&connection->filter_list, link);
5710 filter->function = NULL;
5711
5712 break;
5713 }
5714
5715 link = _dbus_list_get_prev_link (&connection->filter_list, link);
5716 filter = NULL;
5717 }
5718
5719 CONNECTION_UNLOCK (connection);
5720
5721#ifndef DBUS_DISABLE_CHECKS
5722 if (filter == NULL)
5723 {
5724 _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added",
5725 function, user_data);
5726 return;
5727 }
5728#endif
5729
5730 /* Call application code */
5731 if (filter->free_user_data_function)
5732 (* filter->free_user_data_function) (filter->user_data);
5733
5734 filter->free_user_data_function = NULL;
5735 filter->user_data = NULL;
5736
5737 _dbus_message_filter_unref (filter);
5738}
5739
5755static dbus_bool_t
5756_dbus_connection_register_object_path (DBusConnection *connection,
5757 dbus_bool_t fallback,
5758 const char *path,
5759 const DBusObjectPathVTable *vtable,
5760 void *user_data,
5761 DBusError *error)
5762{
5763 char **decomposed_path;
5764 dbus_bool_t retval;
5765
5766 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
5767 return FALSE;
5768
5769 CONNECTION_LOCK (connection);
5770
5771 retval = _dbus_object_tree_register (connection->objects,
5772 fallback,
5773 (const char **) decomposed_path, vtable,
5774 user_data, error);
5775
5776 CONNECTION_UNLOCK (connection);
5777
5778 dbus_free_string_array (decomposed_path);
5779
5780 return retval;
5781}
5782
5797 const char *path,
5798 const DBusObjectPathVTable *vtable,
5799 void *user_data,
5800 DBusError *error)
5801{
5802 _dbus_return_val_if_fail (connection != NULL, FALSE);
5803 _dbus_return_val_if_fail (path != NULL, FALSE);
5804 _dbus_return_val_if_fail (path[0] == '/', FALSE);
5805 _dbus_return_val_if_fail (vtable != NULL, FALSE);
5806
5807 return _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, error);
5808}
5809
5827 const char *path,
5828 const DBusObjectPathVTable *vtable,
5829 void *user_data)
5830{
5831 dbus_bool_t retval;
5832 DBusError error = DBUS_ERROR_INIT;
5833
5834 _dbus_return_val_if_fail (connection != NULL, FALSE);
5835 _dbus_return_val_if_fail (path != NULL, FALSE);
5836 _dbus_return_val_if_fail (path[0] == '/', FALSE);
5837 _dbus_return_val_if_fail (vtable != NULL, FALSE);
5838
5839 retval = _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, &error);
5840
5842 {
5843 _dbus_warn ("%s", error.message);
5844 dbus_error_free (&error);
5845 return FALSE;
5846 }
5847
5848 return retval;
5849}
5850
5867 const char *path,
5868 const DBusObjectPathVTable *vtable,
5869 void *user_data,
5870 DBusError *error)
5871{
5872 _dbus_return_val_if_fail (connection != NULL, FALSE);
5873 _dbus_return_val_if_fail (path != NULL, FALSE);
5874 _dbus_return_val_if_fail (path[0] == '/', FALSE);
5875 _dbus_return_val_if_fail (vtable != NULL, FALSE);
5876
5877 return _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, error);
5878}
5879
5899 const char *path,
5900 const DBusObjectPathVTable *vtable,
5901 void *user_data)
5902{
5903 dbus_bool_t retval;
5904 DBusError error = DBUS_ERROR_INIT;
5905
5906 _dbus_return_val_if_fail (connection != NULL, FALSE);
5907 _dbus_return_val_if_fail (path != NULL, FALSE);
5908 _dbus_return_val_if_fail (path[0] == '/', FALSE);
5909 _dbus_return_val_if_fail (vtable != NULL, FALSE);
5910
5911 retval = _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, &error);
5912
5914 {
5915 _dbus_warn ("%s", error.message);
5916 dbus_error_free (&error);
5917 return FALSE;
5918 }
5919
5920 return retval;
5921}
5922
5934 const char *path)
5935{
5936 char **decomposed_path;
5937
5938 _dbus_return_val_if_fail (connection != NULL, FALSE);
5939 _dbus_return_val_if_fail (path != NULL, FALSE);
5940 _dbus_return_val_if_fail (path[0] == '/', FALSE);
5941
5942 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
5943 return FALSE;
5944
5945 CONNECTION_LOCK (connection);
5946
5947 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
5948
5949 dbus_free_string_array (decomposed_path);
5950
5951 return TRUE;
5952}
5953
5966 const char *path,
5967 void **data_p)
5968{
5969 char **decomposed_path;
5970
5971 _dbus_return_val_if_fail (connection != NULL, FALSE);
5972 _dbus_return_val_if_fail (path != NULL, FALSE);
5973 _dbus_return_val_if_fail (data_p != NULL, FALSE);
5974
5975 *data_p = NULL;
5976
5977 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
5978 return FALSE;
5979
5980 CONNECTION_LOCK (connection);
5981
5982 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
5983
5984 CONNECTION_UNLOCK (connection);
5985
5986 dbus_free_string_array (decomposed_path);
5987
5988 return TRUE;
5989}
5990
6003 const char *parent_path,
6004 char ***child_entries)
6005{
6006 char **decomposed_path;
6007 dbus_bool_t retval;
6008 _dbus_return_val_if_fail (connection != NULL, FALSE);
6009 _dbus_return_val_if_fail (parent_path != NULL, FALSE);
6010 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
6011 _dbus_return_val_if_fail (child_entries != NULL, FALSE);
6012
6013 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
6014 return FALSE;
6015
6016 CONNECTION_LOCK (connection);
6017
6019 (const char **) decomposed_path,
6020 child_entries);
6021 dbus_free_string_array (decomposed_path);
6022
6023 return retval;
6024}
6025
6026static DBusDataSlotAllocator slot_allocator =
6027 _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (connection_slots));
6028
6045{
6046 return _dbus_data_slot_allocator_alloc (&slot_allocator,
6047 slot_p);
6048}
6049
6061void
6063{
6064 _dbus_return_if_fail (*slot_p >= 0);
6065
6066 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
6067}
6068
6093 dbus_int32_t slot,
6094 void *data,
6095 DBusFreeFunction free_data_func)
6096{
6097 DBusFreeFunction old_free_func;
6098 void *old_data;
6099 dbus_bool_t retval;
6100
6101 _dbus_return_val_if_fail (connection != NULL, FALSE);
6102 _dbus_return_val_if_fail (slot >= 0, FALSE);
6103
6104 SLOTS_LOCK (connection);
6105
6106 retval = _dbus_data_slot_list_set (&slot_allocator,
6107 &connection->slot_list,
6108 slot, data, free_data_func,
6109 &old_free_func, &old_data);
6110
6111 SLOTS_UNLOCK (connection);
6112
6113 if (retval)
6114 {
6115 /* Do the actual free outside the connection lock */
6116 if (old_free_func)
6117 (* old_free_func) (old_data);
6118 }
6119
6120 return retval;
6121}
6122
6140void*
6142 dbus_int32_t slot)
6143{
6144 void *res;
6145
6146 _dbus_return_val_if_fail (connection != NULL, NULL);
6147 _dbus_return_val_if_fail (slot >= 0, NULL);
6148
6149 SLOTS_LOCK (connection);
6150
6151 res = _dbus_data_slot_list_get (&slot_allocator,
6152 &connection->slot_list,
6153 slot);
6154
6155 SLOTS_UNLOCK (connection);
6156
6157 return res;
6158}
6159
6166void
6168{
6169 if (will_modify_sigpipe)
6170 _dbus_atomic_set_nonzero (&_dbus_modify_sigpipe);
6171 else
6172 _dbus_atomic_set_zero (&_dbus_modify_sigpipe);
6173}
6174
6183void
6185 long size)
6186{
6187 _dbus_return_if_fail (connection != NULL);
6188
6189 CONNECTION_LOCK (connection);
6191 size);
6192 CONNECTION_UNLOCK (connection);
6193}
6194
6201long
6203{
6204 long res;
6205
6206 _dbus_return_val_if_fail (connection != NULL, 0);
6207
6208 CONNECTION_LOCK (connection);
6210 CONNECTION_UNLOCK (connection);
6211 return res;
6212}
6213
6222void
6224 long n)
6225{
6226 _dbus_return_if_fail (connection != NULL);
6227
6228 CONNECTION_LOCK (connection);
6230 n);
6231 CONNECTION_UNLOCK (connection);
6232}
6233
6240long
6242{
6243 long res;
6244
6245 _dbus_return_val_if_fail (connection != NULL, 0);
6246
6247 CONNECTION_LOCK (connection);
6249 CONNECTION_UNLOCK (connection);
6250 return res;
6251}
6252
6278void
6280 long size)
6281{
6282 _dbus_return_if_fail (connection != NULL);
6283
6284 CONNECTION_LOCK (connection);
6286 size);
6287 CONNECTION_UNLOCK (connection);
6288}
6289
6296long
6298{
6299 long res;
6300
6301 _dbus_return_val_if_fail (connection != NULL, 0);
6302
6303 CONNECTION_LOCK (connection);
6305 CONNECTION_UNLOCK (connection);
6306 return res;
6307}
6308
6320void
6322 long n)
6323{
6324 _dbus_return_if_fail (connection != NULL);
6325
6326 CONNECTION_LOCK (connection);
6328 n);
6329 CONNECTION_UNLOCK (connection);
6330}
6331
6338long
6340{
6341 long res;
6342
6343 _dbus_return_val_if_fail (connection != NULL, 0);
6344
6345 CONNECTION_LOCK (connection);
6347 CONNECTION_UNLOCK (connection);
6348 return res;
6349}
6350
6361long
6363{
6364 long res;
6365
6366 _dbus_return_val_if_fail (connection != NULL, 0);
6367
6368 CONNECTION_LOCK (connection);
6370 CONNECTION_UNLOCK (connection);
6371 return res;
6372}
6373
6374#ifdef DBUS_ENABLE_STATS
6375void
6376_dbus_connection_get_stats (DBusConnection *connection,
6377 dbus_uint32_t *in_messages,
6378 dbus_uint32_t *in_bytes,
6379 dbus_uint32_t *in_fds,
6380 dbus_uint32_t *in_peak_bytes,
6381 dbus_uint32_t *in_peak_fds,
6382 dbus_uint32_t *out_messages,
6383 dbus_uint32_t *out_bytes,
6384 dbus_uint32_t *out_fds,
6385 dbus_uint32_t *out_peak_bytes,
6386 dbus_uint32_t *out_peak_fds)
6387{
6388 CONNECTION_LOCK (connection);
6389
6390 if (in_messages != NULL)
6391 *in_messages = connection->n_incoming;
6392
6393 _dbus_transport_get_stats (connection->transport,
6394 in_bytes, in_fds, in_peak_bytes, in_peak_fds);
6395
6396 if (out_messages != NULL)
6397 *out_messages = connection->n_outgoing;
6398
6399 if (out_bytes != NULL)
6400 *out_bytes = _dbus_counter_get_size_value (connection->outgoing_counter);
6401
6402 if (out_fds != NULL)
6403 *out_fds = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
6404
6405 if (out_peak_bytes != NULL)
6406 *out_peak_bytes = _dbus_counter_get_peak_size_value (connection->outgoing_counter);
6407
6408 if (out_peak_fds != NULL)
6409 *out_peak_fds = _dbus_counter_get_peak_unix_fd_value (connection->outgoing_counter);
6410
6411 CONNECTION_UNLOCK (connection);
6412}
6413#endif /* DBUS_ENABLE_STATS */
6414
6422long
6424{
6425 long res;
6426
6427 _dbus_return_val_if_fail (connection != NULL, 0);
6428
6429 CONNECTION_LOCK (connection);
6431 CONNECTION_UNLOCK (connection);
6432 return res;
6433}
6434
6435#ifdef DBUS_ENABLE_EMBEDDED_TESTS
6442const char*
6443_dbus_connection_get_address (DBusConnection *connection)
6444{
6445 return _dbus_transport_get_address (connection->transport);
6446}
6447#endif
6448
void dbus_address_entries_free(DBusAddressEntry **entries)
Frees a NULL-terminated array of address entries.
Definition: dbus-address.c:194
dbus_bool_t dbus_parse_address(const char *address, DBusAddressEntry ***entry_result, int *array_len, DBusError *error)
Parses an address string of the form:
Definition: dbus-address.c:368
const char * dbus_address_entry_get_value(DBusAddressEntry *entry, const char *key)
Returns a value from a key of an entry.
Definition: dbus-address.c:249
void _dbus_bus_notify_shared_connection_disconnected_unlocked(DBusConnection *connection)
Internal function that checks to see if this is a shared connection owned by the bus and if it is unr...
Definition: dbus-bus.c:390
dbus_bool_t _dbus_connection_handle_watch(DBusWatch *watch, unsigned int condition, void *data)
A callback for use with dbus_watch_new() to create a DBusWatch.
void _dbus_connection_toggle_timeout_unlocked(DBusConnection *connection, DBusTimeout *timeout, dbus_bool_t enabled)
Toggles a timeout and notifies app via connection's DBusTimeoutToggledFunction if available.
dbus_bool_t dbus_connection_has_messages_to_send(DBusConnection *connection)
Checks whether there are messages in the outgoing message queue.
void _dbus_connection_do_iteration_unlocked(DBusConnection *connection, DBusPendingCall *pending, unsigned int flags, int timeout_milliseconds)
Queues incoming messages and sends outgoing messages for this connection, optionally blocking in the ...
dbus_bool_t _dbus_connection_send_and_unlock(DBusConnection *connection, DBusMessage *message, dbus_uint32_t *client_serial)
Like dbus_connection_send(), but assumes the connection is already locked on function entry,...
DBusConnection * _dbus_connection_new_for_transport(DBusTransport *transport)
Creates a new connection for the given transport.
dbus_bool_t _dbus_connection_has_messages_to_send_unlocked(DBusConnection *connection)
Checks whether there are messages in the outgoing message queue.
void(* DBusWatchRemoveFunction)(DBusWatchList *list, DBusWatch *watch)
Function to be called in protected_change_watch() with refcount held.
void _dbus_connection_unlock(DBusConnection *connection)
Releases the connection lock.
void _dbus_connection_lock(DBusConnection *connection)
Acquires the connection lock.
void _dbus_connection_remove_watch_unlocked(DBusConnection *connection, DBusWatch *watch)
Removes a watch using the connection's DBusRemoveWatchFunction if available.
dbus_bool_t _dbus_connection_add_timeout_unlocked(DBusConnection *connection, DBusTimeout *timeout)
Adds a timeout using the connection's DBusAddTimeoutFunction if available.
void _dbus_connection_toggle_watch_unlocked(DBusConnection *connection, DBusWatch *watch, dbus_bool_t enabled)
Toggles a watch and notifies app via connection's DBusWatchToggledFunction if available.
void(* DBusTimeoutToggleFunction)(DBusTimeoutList *list, DBusTimeout *timeout, dbus_bool_t enabled)
Function to be called in protected_change_timeout() with refcount held.
void(* DBusTimeoutRemoveFunction)(DBusTimeoutList *list, DBusTimeout *timeout)
Function to be called in protected_change_timeout() with refcount held.
dbus_bool_t _dbus_connection_add_watch_unlocked(DBusConnection *connection, DBusWatch *watch)
Adds a watch using the connection's DBusAddWatchFunction if available.
void _dbus_connection_remove_pending_call(DBusConnection *connection, DBusPendingCall *pending)
Removes a pending call from the connection, such that the pending reply will be ignored.
void _dbus_connection_close_if_only_one_ref(DBusConnection *connection)
Used internally to handle the semantics of dbus_server_set_new_connection_function().
void _dbus_connection_unref_unlocked(DBusConnection *connection)
Decrements the reference count of a DBusConnection.
DBusMessage * _dbus_connection_get_message_to_send(DBusConnection *connection)
Gets the next outgoing message.
dbus_bool_t(* DBusTimeoutAddFunction)(DBusTimeoutList *list, DBusTimeout *timeout)
Function to be called in protected_change_timeout() with refcount held.
void _dbus_connection_message_sent_unlocked(DBusConnection *connection, DBusMessage *message)
Notifies the connection that a message has been sent, so the message can be removed from the outgoing...
void _dbus_connection_remove_timeout_unlocked(DBusConnection *connection, DBusTimeout *timeout)
Removes a timeout using the connection's DBusRemoveTimeoutFunction if available.
dbus_uint32_t _dbus_connection_get_next_client_serial(DBusConnection *connection)
Allocate and return the next non-zero serial number for outgoing messages.
void(* DBusWatchToggleFunction)(DBusWatchList *list, DBusWatch *watch, dbus_bool_t enabled)
Function to be called in protected_change_watch() with refcount held.
void _dbus_connection_queue_received_message_link(DBusConnection *connection, DBusList *link)
Adds a message-containing list link to the incoming message queue, taking ownership of the link and t...
int _dbus_connection_get_pending_fds_count(DBusConnection *connection)
Return how many file descriptors are pending in the loader.
void _dbus_connection_set_pending_fds_function(DBusConnection *connection, DBusPendingFdsChangeFunction callback, void *data)
Register a function to be called whenever the number of pending file descriptors in the loader change...
dbus_bool_t(* DBusWatchAddFunction)(DBusWatchList *list, DBusWatch *watch)
Function to be called in protected_change_watch() with refcount held.
void _dbus_connection_block_pending_call(DBusPendingCall *pending)
Blocks until a pending call times out or gets a reply.
void _dbus_connection_queue_synthesized_message_link(DBusConnection *connection, DBusList *link)
Adds a link + message to the incoming message queue.
void _dbus_connection_close_possibly_shared(DBusConnection *connection)
Closes a shared OR private connection, while dbus_connection_close() can only be used on private conn...
DBusConnection * _dbus_connection_ref_unlocked(DBusConnection *connection)
Increments the reference count of a DBusConnection.
void dbus_connection_return_message(DBusConnection *connection, DBusMessage *message)
Used to return a message after peeking at it using dbus_connection_borrow_message().
void(* DBusWatchToggledFunction)(DBusWatch *watch, void *data)
Called when dbus_watch_get_enabled() may return a different value than it did before.
dbus_bool_t dbus_connection_get_object_path_data(DBusConnection *connection, const char *path, void **data_p)
Gets the user data passed to dbus_connection_register_object_path() or dbus_connection_register_fallb...
void dbus_connection_set_max_message_size(DBusConnection *connection, long size)
Specifies the maximum size message this connection is allowed to receive.
void dbus_connection_flush(DBusConnection *connection)
Blocks until the outgoing message queue is empty.
long dbus_connection_get_max_message_unix_fds(DBusConnection *connection)
Gets the value set by dbus_connection_set_max_message_unix_fds().
void dbus_connection_set_exit_on_disconnect(DBusConnection *connection, dbus_bool_t exit_on_disconnect)
Set whether _exit() should be called when the connection receives a disconnect signal.
dbus_bool_t dbus_connection_get_socket(DBusConnection *connection, int *fd)
Gets the underlying Windows or UNIX socket file descriptor of the connection, if any.
DBusMessage * dbus_connection_pop_message(DBusConnection *connection)
Returns the first-received message from the incoming message queue, removing it from the queue.
long dbus_connection_get_max_received_unix_fds(DBusConnection *connection)
Gets the value set by dbus_connection_set_max_received_unix_fds().
dbus_bool_t dbus_connection_register_object_path(DBusConnection *connection, const char *path, const DBusObjectPathVTable *vtable, void *user_data)
Registers a handler for a given path in the object hierarchy.
void dbus_connection_close(DBusConnection *connection)
Closes a private connection, so no further data can be sent or received.
void dbus_connection_set_max_message_unix_fds(DBusConnection *connection, long n)
Specifies the maximum number of unix fds a message on this connection is allowed to receive.
void dbus_connection_set_wakeup_main_function(DBusConnection *connection, DBusWakeupMainFunction wakeup_main_function, void *data, DBusFreeFunction free_data_function)
Sets the mainloop wakeup function for the connection.
dbus_bool_t dbus_connection_get_windows_user(DBusConnection *connection, char **windows_sid_p)
Gets the Windows user SID of the connection if known.
dbus_bool_t dbus_connection_get_is_authenticated(DBusConnection *connection)
Gets whether the connection was authenticated.
void dbus_connection_send_preallocated(DBusConnection *connection, DBusPreallocatedSend *preallocated, DBusMessage *message, dbus_uint32_t *client_serial)
Sends a message using preallocated resources.
dbus_bool_t dbus_connection_read_write(DBusConnection *connection, int timeout_milliseconds)
This function is intended for use with applications that don't want to write a main loop and deal wit...
long dbus_connection_get_max_received_size(DBusConnection *connection)
Gets the value set by dbus_connection_set_max_received_size().
dbus_bool_t dbus_connection_get_unix_fd(DBusConnection *connection, int *fd)
Get the UNIX file descriptor of the connection, if any.
void(* DBusDispatchStatusFunction)(DBusConnection *connection, DBusDispatchStatus new_status, void *data)
Called when the return value of dbus_connection_get_dispatch_status() may have changed.
dbus_bool_t dbus_connection_can_send_type(DBusConnection *connection, int type)
Tests whether a certain type can be send via the connection.
dbus_bool_t dbus_connection_list_registered(DBusConnection *connection, const char *parent_path, char ***child_entries)
Lists the registered fallback handlers and object path handlers at the given parent_path.
void * dbus_connection_get_data(DBusConnection *connection, dbus_int32_t slot)
Retrieves data previously set with dbus_connection_set_data().
DBusConnection * dbus_connection_open_private(const char *address, DBusError *error)
Opens a new, dedicated connection to a remote address.
long dbus_connection_get_outgoing_size(DBusConnection *connection)
Gets the approximate size in bytes of all messages in the outgoing message queue.
void dbus_connection_set_dispatch_status_function(DBusConnection *connection, DBusDispatchStatusFunction function, void *data, DBusFreeFunction free_data_function)
Set a function to be invoked when the dispatch status changes.
dbus_bool_t dbus_connection_read_write_dispatch(DBusConnection *connection, int timeout_milliseconds)
This function is intended for use with applications that don't want to write a main loop and deal wit...
DBusHandlerResult(* DBusHandleMessageFunction)(DBusConnection *connection, DBusMessage *message, void *user_data)
Called when a message needs to be handled.
void dbus_connection_remove_filter(DBusConnection *connection, DBusHandleMessageFunction function, void *user_data)
Removes a previously-added message filter.
dbus_bool_t dbus_connection_get_is_connected(DBusConnection *connection)
Gets whether the connection is currently open.
DBusPreallocatedSend * dbus_connection_preallocate_send(DBusConnection *connection)
Preallocates resources needed to send a message, allowing the message to be sent without the possibil...
dbus_bool_t(* DBusAddWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus needs a new watch to be monitored by the main loop.
void dbus_connection_unref(DBusConnection *connection)
Decrements the reference count of a DBusConnection, and finalizes it if the count reaches zero.
void dbus_connection_set_max_received_size(DBusConnection *connection, long size)
Sets the maximum total number of bytes that can be used for all messages received on this connection.
void(* DBusTimeoutToggledFunction)(DBusTimeout *timeout, void *data)
Called when dbus_timeout_get_enabled() may return a different value than it did before.
DBusDispatchStatus dbus_connection_dispatch(DBusConnection *connection)
Processes any incoming data.
dbus_bool_t dbus_connection_unregister_object_path(DBusConnection *connection, const char *path)
Unregisters the handler registered with exactly the given path.
void dbus_connection_set_unix_user_function(DBusConnection *connection, DBusAllowUnixUserFunction function, void *data, DBusFreeFunction free_data_function)
Sets a predicate function used to determine whether a given user ID is allowed to connect.
dbus_bool_t dbus_connection_try_register_object_path(DBusConnection *connection, const char *path, const DBusObjectPathVTable *vtable, void *user_data, DBusError *error)
Registers a handler for a given path in the object hierarchy.
void dbus_connection_steal_borrowed_message(DBusConnection *connection, DBusMessage *message)
Used to keep a message after peeking at it using dbus_connection_borrow_message().
dbus_bool_t dbus_connection_allocate_data_slot(dbus_int32_t *slot_p)
Allocates an integer ID to be used for storing application-specific data on any DBusConnection.
void dbus_connection_set_change_sigpipe(dbus_bool_t will_modify_sigpipe)
This function sets a global flag for whether dbus_connection_new() will set SIGPIPE behavior to SIG_I...
long dbus_connection_get_max_message_size(DBusConnection *connection)
Gets the value set by dbus_connection_set_max_message_size().
void dbus_connection_free_data_slot(dbus_int32_t *slot_p)
Deallocates a global ID for connection data slots.
dbus_bool_t(* DBusAddTimeoutFunction)(DBusTimeout *timeout, void *data)
Called when libdbus needs a new timeout to be monitored by the main loop.
void dbus_connection_set_max_received_unix_fds(DBusConnection *connection, long n)
Sets the maximum total number of unix fds that can be used for all messages received on this connecti...
dbus_bool_t dbus_connection_set_data(DBusConnection *connection, dbus_int32_t slot, void *data, DBusFreeFunction free_data_func)
Stores a pointer on a DBusConnection, along with an optional function to be used for freeing the data...
DBusDispatchStatus dbus_connection_get_dispatch_status(DBusConnection *connection)
Gets the current state of the incoming message queue.
DBusMessage * dbus_connection_send_with_reply_and_block(DBusConnection *connection, DBusMessage *message, int timeout_milliseconds, DBusError *error)
Sends a message and blocks a certain time period while waiting for a reply.
dbus_bool_t dbus_connection_try_register_fallback(DBusConnection *connection, const char *path, const DBusObjectPathVTable *vtable, void *user_data, DBusError *error)
Registers a fallback handler for a given subsection of the object hierarchy.
dbus_bool_t dbus_connection_get_adt_audit_session_data(DBusConnection *connection, void **data, dbus_int32_t *data_size)
Gets the ADT audit data of the connection if any.
DBusMessage * dbus_connection_borrow_message(DBusConnection *connection)
Returns the first-received message from the incoming message queue, leaving it in the queue.
dbus_bool_t dbus_connection_send_with_reply(DBusConnection *connection, DBusMessage *message, DBusPendingCall **pending_return, int timeout_milliseconds)
Queues a message to send, as with dbus_connection_send(), but also returns a DBusPendingCall used to ...
void dbus_connection_set_windows_user_function(DBusConnection *connection, DBusAllowWindowsUserFunction function, void *data, DBusFreeFunction free_data_function)
Sets a predicate function used to determine whether a given user ID is allowed to connect.
dbus_bool_t dbus_connection_get_is_anonymous(DBusConnection *connection)
Gets whether the connection is not authenticated as a specific user.
dbus_bool_t dbus_connection_set_timeout_functions(DBusConnection *connection, DBusAddTimeoutFunction add_function, DBusRemoveTimeoutFunction remove_function, DBusTimeoutToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function)
Sets the timeout functions for the connection.
void(* DBusRemoveWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus no longer needs a watch to be monitored by the main loop.
dbus_bool_t(* DBusAllowUnixUserFunction)(DBusConnection *connection, unsigned long uid, void *data)
Called during authentication to check whether the given UNIX user ID is allowed to connect,...
DBusDispatchStatus
Indicates the status of incoming data on a DBusConnection.
dbus_bool_t dbus_connection_register_fallback(DBusConnection *connection, const char *path, const DBusObjectPathVTable *vtable, void *user_data)
Registers a fallback handler for a given subsection of the object hierarchy.
DBusConnection * dbus_connection_open(const char *address, DBusError *error)
Gets a connection to a remote address.
void dbus_connection_free_preallocated_send(DBusConnection *connection, DBusPreallocatedSend *preallocated)
Frees preallocated message-sending resources from dbus_connection_preallocate_send().
long dbus_connection_get_outgoing_unix_fds(DBusConnection *connection)
Gets the approximate number of uni fds of all messages in the outgoing message queue.
void(* DBusWakeupMainFunction)(void *data)
Called when the main loop's thread should be notified that there's now work to do.
void dbus_connection_set_allow_anonymous(DBusConnection *connection, dbus_bool_t value)
This function must be called on the server side of a connection when the connection is first seen in ...
dbus_bool_t dbus_connection_add_filter(DBusConnection *connection, DBusHandleMessageFunction function, void *user_data, DBusFreeFunction free_data_function)
Adds a message filter.
dbus_bool_t dbus_connection_send(DBusConnection *connection, DBusMessage *message, dbus_uint32_t *serial)
Adds a message to the outgoing message queue.
DBusConnection * dbus_connection_ref(DBusConnection *connection)
Increments the reference count of a DBusConnection.
void dbus_connection_set_builtin_filters_enabled(DBusConnection *connection, dbus_bool_t value)
Enables the builtin filtering of messages.
char * dbus_connection_get_server_id(DBusConnection *connection)
Gets the ID of the server address we are authenticated to, if this connection is on the client side.
dbus_bool_t(* DBusAllowWindowsUserFunction)(DBusConnection *connection, const char *user_sid, void *data)
Called during authentication to check whether the given Windows user ID is allowed to connect,...
dbus_bool_t dbus_connection_set_watch_functions(DBusConnection *connection, DBusAddWatchFunction add_function, DBusRemoveWatchFunction remove_function, DBusWatchToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function)
Sets the watch functions for the connection.
void(* DBusRemoveTimeoutFunction)(DBusTimeout *timeout, void *data)
Called when libdbus no longer needs a timeout to be monitored by the main loop.
dbus_bool_t dbus_connection_get_unix_process_id(DBusConnection *connection, unsigned long *pid)
Gets the process ID of the connection if any.
dbus_bool_t dbus_connection_get_unix_user(DBusConnection *connection, unsigned long *uid)
Gets the UNIX user ID of the connection if known.
void dbus_connection_set_route_peer_messages(DBusConnection *connection, dbus_bool_t value)
Normally DBusConnection automatically handles all messages to the org.freedesktop....
@ DBUS_DISPATCH_NEED_MEMORY
More memory is needed to continue.
@ DBUS_DISPATCH_COMPLETE
All currently available data has been processed.
@ DBUS_DISPATCH_DATA_REMAINS
There is more data to potentially convert to messages.
void _dbus_data_slot_allocator_free(DBusDataSlotAllocator *allocator, dbus_int32_t *slot_id_p)
Deallocates an ID previously allocated with _dbus_data_slot_allocator_alloc().
void _dbus_data_slot_list_init(DBusDataSlotList *list)
Initializes a slot list.
void _dbus_data_slot_list_free(DBusDataSlotList *list)
Frees the data slot list and all data slots contained in it, calling application-provided free functi...
void * _dbus_data_slot_list_get(DBusDataSlotAllocator *allocator, DBusDataSlotList *list, int slot)
Retrieves data previously set with _dbus_data_slot_list_set_data().
dbus_bool_t _dbus_data_slot_list_set(DBusDataSlotAllocator *allocator, DBusDataSlotList *list, int slot, void *data, DBusFreeFunction free_data_func, DBusFreeFunction *old_free_func, void **old_data)
Stores a pointer in the data slot list, along with an optional function to be used for freeing the da...
dbus_bool_t _dbus_data_slot_allocator_alloc(DBusDataSlotAllocator *allocator, dbus_int32_t *slot_id_p)
Allocates an integer ID to be used for storing data in a DBusDataSlotList.
Definition: dbus-dataslot.c:72
#define DBUS_ERROR_INIT
Expands to a suitable initializer for a DBusError on the stack.
Definition: dbus-errors.h:64
void dbus_move_error(DBusError *src, DBusError *dest)
Moves an error src into dest, freeing src and overwriting dest.
Definition: dbus-errors.c:281
dbus_bool_t dbus_error_has_name(const DBusError *error, const char *name)
Checks whether the error is set and has the given name.
Definition: dbus-errors.c:304
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
Definition: dbus-errors.c:356
void dbus_error_free(DBusError *error)
Frees an error that's been set (or just initialized), then reinitializes the error as in dbus_error_i...
Definition: dbus-errors.c:213
int _dbus_hash_table_get_n_entries(DBusHashTable *table)
Gets the number of hash entries in a hash table.
Definition: dbus-hash.c:1461
void * _dbus_hash_iter_get_value(DBusHashIter *iter)
Gets the value of the current entry.
Definition: dbus-hash.c:620
dbus_bool_t _dbus_hash_table_insert_int(DBusHashTable *table, int key, void *value)
Creates a hash entry with the given key and value.
Definition: dbus-hash.c:1312
dbus_bool_t _dbus_hash_table_insert_string(DBusHashTable *table, char *key, void *value)
Creates a hash entry with the given key and value.
Definition: dbus-hash.c:1278
void _dbus_hash_table_unref(DBusHashTable *table)
Decrements the reference count for a hash table, freeing the hash table if the count reaches zero.
Definition: dbus-hash.c:368
dbus_bool_t _dbus_hash_iter_next(DBusHashIter *iter)
Move the hash iterator forward one step, to the next hash entry.
Definition: dbus-hash.c:550
void _dbus_hash_iter_init(DBusHashTable *table, DBusHashIter *iter)
Initializes a hash table iterator.
Definition: dbus-hash.c:524
DBusHashTable * _dbus_hash_table_new(DBusHashType type, DBusFreeFunction key_free_function, DBusFreeFunction value_free_function)
Constructs a new hash table.
Definition: dbus-hash.c:292
dbus_bool_t _dbus_hash_table_remove_int(DBusHashTable *table, int key)
Removes the hash entry for the given key.
Definition: dbus-hash.c:1215
dbus_bool_t _dbus_hash_table_remove_string(DBusHashTable *table, const char *key)
Removes the hash entry for the given key.
Definition: dbus-hash.c:1187
void * _dbus_hash_table_lookup_string(DBusHashTable *table, const char *key)
Looks up the value for a given string in a hash table of type DBUS_HASH_STRING.
Definition: dbus-hash.c:1113
void _dbus_hash_iter_remove_entry(DBusHashIter *iter)
Removes the current entry from the hash table.
Definition: dbus-hash.c:599
void * _dbus_hash_table_lookup_int(DBusHashTable *table, int key)
Looks up the value for a given integer in a hash table of type DBUS_HASH_INT.
Definition: dbus-hash.c:1138
@ DBUS_HASH_INT
Hash keys are integers.
Definition: dbus-hash.h:70
@ DBUS_HASH_STRING
Hash keys are strings.
Definition: dbus-hash.h:69
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
#define _DBUS_UNLOCK(name)
Unlocks a global lock.
#define _DBUS_LOCK(name)
Locks a global lock, initializing it first if necessary.
void _dbus_warn_check_failed(const char *format,...)
Prints a "critical" warning to stderr when an assertion fails; differs from _dbus_warn primarily in t...
char * _dbus_strdup(const char *str)
Duplicates a string.
dbus_bool_t _dbus_get_local_machine_uuid_encoded(DBusString *uuid_str, DBusError *error)
Gets the hex-encoded UUID of the machine this function is executed on.
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
#define _DBUS_LOCK_NAME(name)
Expands to name of a global lock variable.
DBusList * _dbus_list_get_first_link(DBusList **list)
Gets the first link in the list.
Definition: dbus-list.c:597
dbus_bool_t _dbus_list_copy(DBusList **list, DBusList **dest)
Copies a list.
Definition: dbus-list.c:727
DBusList * _dbus_list_pop_first_link(DBusList **list)
Removes the first link in the list and returns it.
Definition: dbus-list.c:658
void * _dbus_list_get_last(DBusList **list)
Gets the last data in the list.
Definition: dbus-list.c:626
dbus_bool_t _dbus_list_remove(DBusList **list, void *data)
Removes a value from the list.
Definition: dbus-list.c:418
void _dbus_list_append_link(DBusList **list, DBusList *link)
Appends a link to the list.
Definition: dbus-list.c:318
void _dbus_list_clear_full(DBusList **list, DBusFreeFunction function)
Free every link and every element in the list.
Definition: dbus-list.c:570
void _dbus_list_remove_link(DBusList **list, DBusList *link)
Removes a link from the list.
Definition: dbus-list.c:530
void * _dbus_list_get_first(DBusList **list)
Gets the first data in the list.
Definition: dbus-list.c:642
DBusList * _dbus_list_get_last_link(DBusList **list)
Gets the last link in the list.
Definition: dbus-list.c:610
void _dbus_list_unlink(DBusList **list, DBusList *link)
Removes the given link from the list, but doesn't free it.
Definition: dbus-list.c:502
#define _dbus_list_get_prev_link(list, link)
Gets the previous link in the list, or NULL if there are no more links.
Definition: dbus-list.h:122
void _dbus_list_free_link(DBusList *link)
Frees a linked list node allocated with _dbus_list_alloc_link.
Definition: dbus-list.c:257
void * _dbus_list_pop_first(DBusList **list)
Removes the first value in the list and returns it.
Definition: dbus-list.c:679
void _dbus_list_foreach(DBusList **list, DBusForeachFunction function, void *data)
Calls the given function for each element in the list.
Definition: dbus-list.c:789
void _dbus_list_clear(DBusList **list)
Frees all links in the list and sets the list head to NULL.
Definition: dbus-list.c:545
void _dbus_list_prepend_link(DBusList **list, DBusList *link)
Prepends a link to the list.
Definition: dbus-list.c:336
dbus_bool_t _dbus_list_prepend(DBusList **list, void *data)
Prepends a value to the list.
Definition: dbus-list.c:295
DBusList * _dbus_list_alloc_link(void *data)
Allocates a linked list node.
Definition: dbus-list.c:245
dbus_bool_t _dbus_list_append(DBusList **list, void *data)
Appends a value to the list.
Definition: dbus-list.c:273
#define _dbus_list_get_next_link(list, link)
Gets the next link in the list, or NULL if there are no more links.
Definition: dbus-list.h:121
#define NULL
A null pointer, defined appropriately for C or C++.
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".
int _dbus_current_generation
_dbus_current_generation is used to track each time that dbus_shutdown() is called,...
Definition: dbus-memory.c:774
DBUS_PRIVATE_EXPORT dbus_bool_t _dbus_register_shutdown_func(DBusShutdownFunction function, void *data)
Register a cleanup function to be called exactly once the next time dbus_shutdown() is called.
Definition: dbus-memory.c:803
void(* DBusFreeFunction)(void *memory)
The type of a function which frees a block of memory.
Definition: dbus-memory.h:65
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:694
#define dbus_new(type, count)
Safe macro for using dbus_malloc().
Definition: dbus-memory.h:59
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
Definition: dbus-memory.h:60
void dbus_free_string_array(char **str_array)
Frees a NULL-terminated array of strings.
Definition: dbus-memory.c:742
void dbus_message_set_serial(DBusMessage *message, dbus_uint32_t serial)
Sets the serial number of a message.
Definition: dbus-message.c:301
void dbus_message_lock(DBusMessage *message)
Locks a message.
Definition: dbus-message.c:431
const char * dbus_message_type_to_string(int type)
Utility function to convert a D-Bus message type into a machine-readable string (not translated).
void _dbus_message_remove_counter(DBusMessage *message, DBusCounter *counter)
Removes a counter tracking the size/unix fds of this message, and decrements the counter by the size/...
Definition: dbus-message.c:399
void _dbus_message_add_counter_link(DBusMessage *message, DBusList *link)
Adds a counter to be incremented immediately with the size/unix fds of this message,...
Definition: dbus-message.c:327
dbus_bool_t dbus_message_has_interface(DBusMessage *message, const char *iface)
Checks if the message has an interface.
void dbus_message_set_no_reply(DBusMessage *message, dbus_bool_t no_reply)
Sets a flag indicating that the message does not want a reply; if this flag is set,...
dbus_bool_t dbus_message_iter_append_basic(DBusMessageIter *iter, int type, const void *value)
Appends a basic-typed value to the message.
const char * dbus_message_get_path(DBusMessage *message)
Gets the object path this message is being sent to (for DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitt...
const char * dbus_message_get_interface(DBusMessage *message)
Gets the interface this message is being sent to (for DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitted...
DBusMessage * dbus_message_new_error(DBusMessage *reply_to, const char *error_name, const char *error_message)
Creates a new message that is an error reply to another message.
dbus_uint32_t dbus_message_get_serial(DBusMessage *message)
Returns the serial of a message or 0 if none has been specified.
int dbus_message_get_type(DBusMessage *message)
Gets the type of a message.
dbus_bool_t dbus_message_append_args(DBusMessage *message, int first_arg_type,...)
Appends fields to a message given a variable argument list.
DBusMessage * dbus_message_new_signal(const char *path, const char *iface, const char *name)
Constructs a new message representing a signal emission.
DBusMessage * dbus_message_ref(DBusMessage *message)
Increments the reference count of a DBusMessage.
dbus_bool_t dbus_message_set_error_name(DBusMessage *message, const char *error_name)
Sets the name of the error (DBUS_MESSAGE_TYPE_ERROR).
dbus_uint32_t dbus_message_get_reply_serial(DBusMessage *message)
Returns the serial that the message is a reply to or 0 if none.
DBusMessage * dbus_message_new_method_return(DBusMessage *method_call)
Constructs a message that is a reply to a method call.
const char * dbus_message_get_destination(DBusMessage *message)
Gets the destination of a message or NULL if there is none set.
void dbus_message_unref(DBusMessage *message)
Decrements the reference count of a DBusMessage, freeing the message if the count reaches 0.
DBusMessage * dbus_message_new(int message_type)
Constructs a new message of the given message type.
dbus_bool_t dbus_set_error_from_message(DBusError *error, DBusMessage *message)
Sets a DBusError based on the contents of the given message.
dbus_bool_t dbus_message_is_method_call(DBusMessage *message, const char *iface, const char *method)
Checks whether the message is a method call with the given interface and member fields.
dbus_bool_t dbus_message_set_reply_serial(DBusMessage *message, dbus_uint32_t reply_serial)
Sets the reply serial of a message (the serial of the message this is a reply to).
dbus_bool_t dbus_message_is_signal(DBusMessage *message, const char *iface, const char *signal_name)
Checks whether the message is a signal with the given interface and member fields.
const char * dbus_message_get_signature(DBusMessage *message)
Gets the type signature of the message, i.e.
const char * dbus_message_get_member(DBusMessage *message)
Gets the interface member being invoked (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted (DBUS_MESSAGE_TYPE...
void dbus_message_iter_init_append(DBusMessage *message, DBusMessageIter *iter)
Initializes a DBusMessageIter for appending arguments to the end of a message.
void _dbus_object_tree_free_all_unlocked(DBusObjectTree *tree)
Free all the handlers in the tree.
void _dbus_object_tree_unregister_and_unlock(DBusObjectTree *tree, const char **path)
Unregisters an object subtree that was registered with the same path.
void _dbus_object_tree_unref(DBusObjectTree *tree)
Decrement the reference count.
dbus_bool_t _dbus_object_tree_list_registered_and_unlock(DBusObjectTree *tree, const char **parent_path, char ***child_entries)
Lists the registered fallback handlers and object path handlers at the given parent_path.
dbus_bool_t _dbus_decompose_path(const char *data, int len, char ***path, int *path_len)
Decompose an object path.
dbus_bool_t _dbus_object_tree_register(DBusObjectTree *tree, dbus_bool_t fallback, const char **path, const DBusObjectPathVTable *vtable, void *user_data, DBusError *error)
Registers a new subtree in the global object tree.
void * _dbus_object_tree_get_user_data_unlocked(DBusObjectTree *tree, const char **path)
Looks up the data passed to _dbus_object_tree_register() for a handler at the given path.
DBusHandlerResult _dbus_object_tree_dispatch_and_unlock(DBusObjectTree *tree, DBusMessage *message, dbus_bool_t *found_object)
Tries to dispatch a message by directing it to handler for the object path listed in the message head...
DBusObjectTree * _dbus_object_tree_new(DBusConnection *connection)
Creates a new object tree, representing a mapping from paths to handler vtables.
void _dbus_pending_call_finish_completion(DBusPendingCall *pending)
Call the notifier function for the pending call.
DBusConnection * _dbus_pending_call_get_connection_and_lock(DBusPendingCall *pending)
Gets the connection associated with this pending call.
DBUS_PRIVATE_EXPORT DBusPendingCall * _dbus_pending_call_ref_unlocked(DBusPendingCall *pending)
Increments the reference count on a pending call, while the lock on its connection is already held.
void _dbus_pending_call_queue_timeout_error_unlocked(DBusPendingCall *pending, DBusConnection *connection)
If the pending call hasn't been timed out, add its timeout error reply to the connection's incoming m...
DBUS_PRIVATE_EXPORT void _dbus_pending_call_unref_and_unlock(DBusPendingCall *pending)
Decrements the reference count on a pending call, freeing it if the count reaches 0.
dbus_bool_t _dbus_pending_call_get_completed_unlocked(DBusPendingCall *pending)
Checks whether the pending call has received a reply yet, or not.
void _dbus_pending_call_set_reply_unlocked(DBusPendingCall *pending, DBusMessage *message)
Sets the reply of a pending call with the given message, or if the message is NULL,...
DBUS_PRIVATE_EXPORT DBusPendingCall * _dbus_pending_call_new_unlocked(DBusConnection *connection, int timeout_milliseconds, DBusTimeoutHandler timeout_handler)
Creates a new pending reply object.
dbus_bool_t _dbus_pending_call_set_timeout_error_unlocked(DBusPendingCall *pending, DBusMessage *message, dbus_uint32_t serial)
Sets the reply message associated with the pending call to a timeout error.
#define CONNECTION_LOCK(connection)
Internals of DBusPendingCall.
#define CONNECTION_UNLOCK(connection)
shorter and more visible way to write _dbus_connection_unlock()
void _dbus_pending_call_start_completion_unlocked(DBusPendingCall *pending)
Sets the pending call to completed.
dbus_bool_t _dbus_pending_call_is_timeout_added_unlocked(DBusPendingCall *pending)
Checks to see if a timeout has been added.
dbus_uint32_t _dbus_pending_call_get_reply_serial_unlocked(DBusPendingCall *pending)
Gets the reply's serial number.
DBusConnection * _dbus_pending_call_get_connection_unlocked(DBusPendingCall *pending)
Gets the connection associated with this pending call.
DBusTimeout * _dbus_pending_call_get_timeout_unlocked(DBusPendingCall *pending)
Retrives the timeout.
void _dbus_pending_call_set_timeout_added_unlocked(DBusPendingCall *pending, dbus_bool_t is_added)
Sets wether the timeout has been added.
DBusPendingCall * dbus_pending_call_ref(DBusPendingCall *pending)
Increments the reference count on a pending call.
DBusMessage * dbus_pending_call_steal_reply(DBusPendingCall *pending)
Gets the reply, or returns NULL if none has been received yet.
void dbus_pending_call_block(DBusPendingCall *pending)
Block until the pending call is completed.
dbus_bool_t dbus_pending_call_get_completed(DBusPendingCall *pending)
Checks whether the pending call has received a reply yet, or not.
void dbus_pending_call_unref(DBusPendingCall *pending)
Decrements the reference count on a pending call, freeing it if the count reaches 0.
#define DBUS_MESSAGE_TYPE_METHOD_CALL
Message type of a method call message, see dbus_message_get_type()
#define DBUS_MESSAGE_TYPE_ERROR
Message type of an error reply message, see dbus_message_get_type()
#define DBUS_ERROR_UNKNOWN_METHOD
Method name you invoked isn't known by the object you invoked it on.
#define DBUS_TYPE_UNIX_FD
Type code marking a unix file descriptor.
#define DBUS_ERROR_OBJECT_PATH_IN_USE
There's already an object with the requested object path.
#define DBUS_MESSAGE_TYPE_SIGNAL
Message type of a signal message, see dbus_message_get_type()
#define DBUS_TYPE_STRING
Type code marking a UTF-8 encoded, nul-terminated Unicode string.
#define DBUS_ERROR_UNKNOWN_OBJECT
Object you invoked a method on isn't known.
#define DBUS_TYPE_INVALID
Type code that is never equal to a legitimate type code.
Definition: dbus-protocol.h:62
#define DBUS_ERROR_FAILED
A generic error; "something went wrong" - see the error message for more.
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
#define DBUS_ERROR_DISCONNECTED
The connection is disconnected and you're trying to use it.
DBusCounter * _dbus_counter_new(void)
Creates a new DBusCounter.
long _dbus_counter_get_unix_fd_value(DBusCounter *counter)
Gets the current value of the unix fd counter.
void _dbus_counter_unref(DBusCounter *counter)
Decrements refcount of the counter and possibly finalizes the counter.
long _dbus_counter_get_size_value(DBusCounter *counter)
Gets the current value of the size counter.
DBusCounter * _dbus_counter_ref(DBusCounter *counter)
Increments refcount of the counter.
DBusHandlerResult
Results that a message handler can return.
Definition: dbus-shared.h:69
#define DBUS_PATH_LOCAL
The object path used in local/in-process-generated messages.
Definition: dbus-shared.h:84
#define DBUS_INTERFACE_LOCAL
This is a special interface whose methods can only be invoked by the local implementation (messages f...
Definition: dbus-shared.h:107
#define DBUS_INTERFACE_PEER
The interface supported by most dbus peers.
Definition: dbus-shared.h:101
@ DBUS_HANDLER_RESULT_NEED_MEMORY
Need more memory in order to return DBUS_HANDLER_RESULT_HANDLED or DBUS_HANDLER_RESULT_NOT_YET_HANDLE...
Definition: dbus-shared.h:72
@ DBUS_HANDLER_RESULT_HANDLED
Message has had its effect - no need to run more handlers.
Definition: dbus-shared.h:70
@ DBUS_HANDLER_RESULT_NOT_YET_HANDLED
Message has not had any effect - see if other handlers want it.
Definition: dbus-shared.h:71
dbus_bool_t dbus_type_is_valid(int typecode)
Return TRUE if the argument is a valid typecode.
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:182
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as #_DBUS_STRING_I...
Definition: dbus-string.c:278
dbus_bool_t _dbus_string_append_printf(DBusString *str, const char *format,...)
Appends a printf-style formatted string to the DBusString.
Definition: dbus-string.c:1147
const char * _dbus_string_get_const_data(const DBusString *str)
Gets the raw character buffer from a const string.
Definition: dbus-string.c:513
void _dbus_exit(int code)
Exit the process, returning the given value.
void _dbus_atomic_set_nonzero(DBusAtomic *atomic)
Atomically set the value of an integer to something nonzero.
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
dbus_int32_t _dbus_atomic_get(DBusAtomic *atomic)
Atomically get the value of an integer.
void _dbus_disable_sigpipe(void)
signal (SIGPIPE, SIG_IGN);
void _dbus_sleep_milliseconds(int milliseconds)
Sleeps the given number of milliseconds.
void _dbus_atomic_set_zero(DBusAtomic *atomic)
Atomically set the value of an integer to 0.
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
void _dbus_get_monotonic_time(long *tv_sec, long *tv_usec)
Get current time, as in gettimeofday().
void _dbus_rmutex_new_at_location(DBusRMutex **location_p)
Creates a new mutex or creates a no-op mutex if threads are not initialized.
Definition: dbus-threads.c:56
void _dbus_cmutex_free_at_location(DBusCMutex **location_p)
Frees a DBusCMutex; does nothing if passed a NULL pointer.
Definition: dbus-threads.c:110
void _dbus_condvar_free_at_location(DBusCondVar **location_p)
Frees a condition variable; does nothing if passed a NULL pointer.
Definition: dbus-threads.c:227
DBUS_PRIVATE_EXPORT void _dbus_rmutex_unlock(DBusRMutex *mutex)
Unlocks a mutex.
Definition: dbus-threads.c:153
void _dbus_condvar_wait(DBusCondVar *cond, DBusCMutex *mutex)
Atomically unlocks the mutex and waits for the conditions variable to be signalled.
Definition: dbus-threads.c:243
void _dbus_condvar_new_at_location(DBusCondVar **location_p)
This does the same thing as _dbus_condvar_new.
Definition: dbus-threads.c:202
void _dbus_cmutex_new_at_location(DBusCMutex **location_p)
Creates a new mutex or creates a no-op mutex if threads are not initialized.
Definition: dbus-threads.c:80
void _dbus_condvar_wake_one(DBusCondVar *cond)
If there are threads waiting on the condition variable, wake up exactly one.
Definition: dbus-threads.c:281
dbus_bool_t _dbus_condvar_wait_timeout(DBusCondVar *cond, DBusCMutex *mutex, int timeout_milliseconds)
Atomically unlocks the mutex and waits for the conditions variable to be signalled,...
Definition: dbus-threads.c:264
void _dbus_cmutex_lock(DBusCMutex *mutex)
Locks a mutex.
Definition: dbus-threads.c:139
void _dbus_cmutex_unlock(DBusCMutex *mutex)
Unlocks a mutex.
Definition: dbus-threads.c:167
void _dbus_rmutex_free_at_location(DBusRMutex **location_p)
Frees a DBusRMutex; does nothing if passed a NULL pointer.
Definition: dbus-threads.c:97
struct DBusMutex DBusMutex
An opaque mutex type provided by the DBusThreadFunctions implementation installed by dbus_threads_ini...
Definition: dbus-threads.h:43
dbus_bool_t _dbus_timeout_list_add_timeout(DBusTimeoutList *timeout_list, DBusTimeout *timeout)
Adds a new timeout to the timeout list, invoking the application DBusAddTimeoutFunction if appropriat...
Definition: dbus-timeout.c:314
void _dbus_timeout_list_free(DBusTimeoutList *timeout_list)
Frees a DBusTimeoutList.
Definition: dbus-timeout.c:217
void _dbus_timeout_list_toggle_timeout(DBusTimeoutList *timeout_list, DBusTimeout *timeout, dbus_bool_t enabled)
Sets a timeout to the given enabled state, invoking the application's DBusTimeoutToggledFunction if a...
Definition: dbus-timeout.c:366
DBusTimeoutList * _dbus_timeout_list_new(void)
Creates a new timeout list.
Definition: dbus-timeout.c:200
dbus_bool_t _dbus_timeout_list_set_functions(DBusTimeoutList *timeout_list, DBusAddTimeoutFunction add_function, DBusRemoveTimeoutFunction remove_function, DBusTimeoutToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function)
Sets the timeout functions.
Definition: dbus-timeout.c:243
void _dbus_timeout_list_remove_timeout(DBusTimeoutList *timeout_list, DBusTimeout *timeout)
Removes a timeout from the timeout list, invoking the application's DBusRemoveTimeoutFunction if appr...
Definition: dbus-timeout.c:344
DBUS_EXPORT int dbus_timeout_get_interval(DBusTimeout *timeout)
Gets the timeout interval.
Definition: dbus-timeout.c:444
void _dbus_transport_set_max_message_size(DBusTransport *transport, long size)
See dbus_connection_set_max_message_size().
void _dbus_transport_set_max_received_size(DBusTransport *transport, long size)
See dbus_connection_set_max_received_size().
DBusDispatchStatus _dbus_transport_get_dispatch_status(DBusTransport *transport)
Reports our current dispatch status (whether there's buffered data to be queued as messages,...
int _dbus_transport_get_pending_fds_count(DBusTransport *transport)
Return how many file descriptors are pending in the loader.
dbus_bool_t _dbus_transport_get_adt_audit_session_data(DBusTransport *transport, void **data, int *data_size)
See dbus_connection_get_adt_audit_session_data().
dbus_bool_t _dbus_transport_get_windows_user(DBusTransport *transport, char **windows_sid_p)
See dbus_connection_get_windows_user().
dbus_bool_t _dbus_transport_queue_messages(DBusTransport *transport)
Processes data we've read while handling a watch, potentially converting some of it to messages and q...
dbus_bool_t _dbus_transport_get_socket_fd(DBusTransport *transport, DBusSocket *fd_p)
Get the socket file descriptor, if any.
const char * _dbus_transport_get_address(DBusTransport *transport)
Gets the address of a transport.
dbus_bool_t _dbus_transport_handle_watch(DBusTransport *transport, DBusWatch *watch, unsigned int condition)
Handles a watch by reading data, writing data, or disconnecting the transport, as appropriate for the...
DBusTransport * _dbus_transport_ref(DBusTransport *transport)
Increments the reference count for the transport.
dbus_bool_t _dbus_transport_peek_is_authenticated(DBusTransport *transport)
Returns TRUE if we have been authenticated.
void _dbus_transport_set_allow_anonymous(DBusTransport *transport, dbus_bool_t value)
See dbus_connection_set_allow_anonymous()
void _dbus_transport_disconnect(DBusTransport *transport)
Closes our end of the connection to a remote application.
long _dbus_transport_get_max_received_size(DBusTransport *transport)
See dbus_connection_get_max_received_size().
DBusCredentials * _dbus_transport_get_credentials(DBusTransport *transport)
If the transport has already been authenticated, return its credentials.
dbus_bool_t _dbus_transport_set_connection(DBusTransport *transport, DBusConnection *connection)
Sets the connection using this transport.
void _dbus_transport_set_unix_user_function(DBusTransport *transport, DBusAllowUnixUserFunction function, void *data, DBusFreeFunction free_data_function, void **old_data, DBusFreeFunction *old_free_data_function)
See dbus_connection_set_unix_user_function().
long _dbus_transport_get_max_message_unix_fds(DBusTransport *transport)
See dbus_connection_get_max_message_unix_fds().
void _dbus_transport_set_max_received_unix_fds(DBusTransport *transport, long n)
See dbus_connection_set_max_received_unix_fds().
void _dbus_transport_unref(DBusTransport *transport)
Decrements the reference count for the transport.
dbus_bool_t _dbus_transport_can_pass_unix_fd(DBusTransport *transport)
Returns TRUE if the transport supports sending unix fds.
dbus_bool_t _dbus_transport_try_to_authenticate(DBusTransport *transport)
Returns TRUE if we have been authenticated.
void _dbus_transport_do_iteration(DBusTransport *transport, unsigned int flags, int timeout_milliseconds)
Performs a single poll()/select() on the transport's file descriptors and then reads/writes data as a...
long _dbus_transport_get_max_received_unix_fds(DBusTransport *transport)
See dbus_connection_set_max_received_unix_fds().
dbus_bool_t _dbus_transport_get_is_connected(DBusTransport *transport)
Returns TRUE if the transport has not been disconnected.
void _dbus_transport_set_max_message_unix_fds(DBusTransport *transport, long n)
See dbus_connection_set_max_message_unix_fds().
void _dbus_transport_set_pending_fds_function(DBusTransport *transport, void(*callback)(void *), void *data)
Register a function to be called whenever the number of pending file descriptors in the loader change...
void _dbus_transport_set_windows_user_function(DBusTransport *transport, DBusAllowWindowsUserFunction function, void *data, DBusFreeFunction free_data_function, void **old_data, DBusFreeFunction *old_free_data_function)
See dbus_connection_set_windows_user_function().
long _dbus_transport_get_max_message_size(DBusTransport *transport)
See dbus_connection_get_max_message_size().
dbus_bool_t _dbus_transport_get_unix_process_id(DBusTransport *transport, unsigned long *pid)
See dbus_connection_get_unix_process_id().
DBusTransport * _dbus_transport_open(DBusAddressEntry *entry, DBusError *error)
Try to open a new transport for the given address entry.
const char * _dbus_transport_get_server_id(DBusTransport *transport)
Gets the id of the server we are connected to (see dbus_server_get_id()).
dbus_bool_t _dbus_transport_get_is_anonymous(DBusTransport *transport)
See dbus_connection_get_is_anonymous().
dbus_bool_t _dbus_transport_get_unix_user(DBusTransport *transport, unsigned long *uid)
See dbus_connection_get_unix_user().
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:37
int dbus_int32_t
A 32-bit signed integer on all platforms.
unsigned int dbus_uint32_t
A 32-bit unsigned integer on all platforms.
dbus_bool_t _dbus_watch_list_add_watch(DBusWatchList *watch_list, DBusWatch *watch)
Adds a new watch to the watch list, invoking the application DBusAddWatchFunction if appropriate.
Definition: dbus-watch.c:383
void _dbus_watch_list_toggle_watch(DBusWatchList *watch_list, DBusWatch *watch, dbus_bool_t enabled)
Sets a watch to the given enabled state, invoking the application's DBusWatchToggledFunction if appro...
Definition: dbus-watch.c:443
DBusWatchList * _dbus_watch_list_new(void)
Creates a new watch list.
Definition: dbus-watch.c:234
void _dbus_watch_list_free(DBusWatchList *watch_list)
Frees a DBusWatchList.
Definition: dbus-watch.c:251
dbus_bool_t _dbus_watch_list_set_functions(DBusWatchList *watch_list, DBusAddWatchFunction add_function, DBusRemoveWatchFunction remove_function, DBusWatchToggledFunction toggled_function, void *data, DBusFreeFunction free_data_function)
Sets the watch functions.
Definition: dbus-watch.c:297
void _dbus_watch_list_remove_watch(DBusWatchList *watch_list, DBusWatch *watch)
Removes a watch from the watch list, invoking the application's DBusRemoveWatchFunction if appropriat...
Definition: dbus-watch.c:416
Internals of DBusAddressEntry.
Definition: dbus-address.c:49
An atomic integer safe to increment or decrement from multiple threads.
Definition: dbus-sysdeps.h:340
Implementation details of DBusConnection.
void * dispatch_status_data
Application data for dispatch_status_function.
int n_outgoing
Length of outgoing queue.
DBusDataSlotList slot_list
Data stored by allocated integer ID.
dbus_bool_t dispatch_acquired
Someone has dispatch path (can drain incoming queue)
DBusCondVar * dispatch_cond
Notify when dispatch_acquired is available.
DBusWakeupMainFunction wakeup_main_function
Function to wake up the mainloop
unsigned int exit_on_disconnect
If TRUE, exit after handling disconnect signal.
DBusList * filter_list
List of filters.
unsigned int have_connection_lock
Used to check locking.
unsigned int disconnected_message_processed
We did our default handling of the disconnected message, such as closing the connection.
dbus_uint32_t client_serial
Client serial.
unsigned int disconnected_message_arrived
We popped or are dispatching the disconnected message.
DBusCounter * outgoing_counter
Counts size of outgoing messages.
unsigned int builtin_filters_enabled
If TRUE, handle org.freedesktop.DBus.Peer messages automatically, whether they have a bus name or not...
DBusCondVar * io_path_cond
Notify when io_path_acquired is available.
DBusAtomic refcount
Reference count.
DBusList * outgoing_messages
Queue of messages we need to send, send the end of the list first.
DBusFreeFunction free_dispatch_status_data
free dispatch_status_data
DBusRMutex * slot_mutex
Lock on slot_list so overall connection lock need not be taken.
DBusFreeFunction free_wakeup_main_data
free wakeup_main_data
DBusTransport * transport
Object that sends/receives messages over network.
DBusRMutex * mutex
Lock on the entire DBusConnection.
int n_incoming
Length of incoming queue.
dbus_bool_t io_path_acquired
Someone has transport io path (can use the transport to read/write messages)
DBusList * disconnect_message_link
Preallocated list node for queueing the disconnection message.
DBusCMutex * io_path_mutex
Protects io_path_acquired.
DBusList * incoming_messages
Queue of messages we have received, end of the list received most recently.
unsigned int shareable
TRUE if libdbus owns a reference to the connection and can return it from dbus_connection_open() more...
unsigned int route_peer_messages
If TRUE, if org.freedesktop.DBus.Peer messages have a bus name, don't handle them automatically.
DBusWatchList * watches
Stores active watches.
void * wakeup_main_data
Application data for wakeup_main_function.
DBusObjectTree * objects
Object path handlers registered with this connection.
char * server_guid
GUID of server if we are in shared_connections, NULL if server GUID is unknown or connection is priva...
DBusHashTable * pending_replies
Hash of message serials to DBusPendingCall.
DBusCMutex * dispatch_mutex
Protects dispatch_acquired.
DBusMessage * message_borrowed
Filled in if the first incoming message has been borrowed; dispatch_acquired will be set by the borro...
DBusTimeoutList * timeouts
Stores active timeouts.
DBusDispatchStatus last_dispatch_status
The last dispatch status we reported to the application.
DBusDispatchStatusFunction dispatch_status_function
Function on dispatch status changes
DBusList * expired_messages
Messages that will be released when we next unlock.
Internals of DBusCounter.
An allocator that tracks a set of slot IDs.
Definition: dbus-dataslot.h:58
Data structure that stores the actual user data set at a given slot.
Definition: dbus-dataslot.h:72
Object representing an exception.
Definition: dbus-errors.h:51
const char * name
public error name field
Definition: dbus-errors.h:52
const char * message
public error message field
Definition: dbus-errors.h:53
Hash iterator object.
Definition: dbus-hash.h:50
Internals of DBusHashTable.
Definition: dbus-hash.c:175
A node in a linked list.
Definition: dbus-list.h:37
void * data
Data stored at this element.
Definition: dbus-list.h:40
Internal struct representing a message filter function.
DBusAtomic refcount
Reference count.
DBusHandleMessageFunction function
Function to call to filter.
void * user_data
User data for the function.
DBusFreeFunction free_user_data_function
Function to free the user data.
DBusMessageIter struct; contains no public fields.
Definition: dbus-message.h:64
Internals of DBusMessage.
Virtual table that must be implemented to handle a portion of the object path hierarchy.
Internals of DBusObjectTree.
Implementation details of DBusPendingCall - all fields are private.
Internals of DBusPreallocatedSend.
DBusConnection * connection
Connection we'd send the message to.
DBusList * counter_link
Preallocated link in the resource counter.
DBusList * queue_link
Preallocated link in the queue.
Socket interface.
Definition: dbus-sysdeps.h:185
DBusTimeoutList implementation details.
Definition: dbus-timeout.c:183
Internals of DBusTimeout.
Definition: dbus-timeout.c:43
Object representing a transport such as a socket.
DBusWatchList implementation details.
Definition: dbus-watch.c:217
Implementation of DBusWatch.
Definition: dbus-watch.c:43