D-Bus 1.14.10
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 * Licensed under the Academic Free License version 2.1
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 */
23
24#include <config.h>
25#include "dbus-shared.h"
26#include "dbus-connection.h"
27#include "dbus-list.h"
28#include "dbus-timeout.h"
29#include "dbus-transport.h"
30#include "dbus-watch.h"
31#include "dbus-connection-internal.h"
32#include "dbus-pending-call-internal.h"
33#include "dbus-list.h"
34#include "dbus-hash.h"
35#include "dbus-message-internal.h"
36#include "dbus-message-private.h"
37#include "dbus-threads.h"
38#include "dbus-protocol.h"
39#include "dbus-dataslot.h"
40#include "dbus-string.h"
41#include "dbus-signature.h"
42#include "dbus-pending-call.h"
43#include "dbus-object-tree.h"
44#include "dbus-threads-internal.h"
45#include "dbus-bus.h"
46#include "dbus-marshal-basic.h"
47
48#ifdef DBUS_DISABLE_CHECKS
49#define TOOK_LOCK_CHECK(connection)
50#define RELEASING_LOCK_CHECK(connection)
51#define HAVE_LOCK_CHECK(connection)
52#else
53#define TOOK_LOCK_CHECK(connection) do { \
54 _dbus_assert (!(connection)->have_connection_lock); \
55 (connection)->have_connection_lock = TRUE; \
56 } while (0)
57#define RELEASING_LOCK_CHECK(connection) do { \
58 _dbus_assert ((connection)->have_connection_lock); \
59 (connection)->have_connection_lock = FALSE; \
60 } while (0)
61#define HAVE_LOCK_CHECK(connection) _dbus_assert ((connection)->have_connection_lock)
62/* A "DO_NOT_HAVE_LOCK_CHECK" is impossible since we need the lock to check the flag */
63#endif
64
65#define TRACE_LOCKS 1
66
67#define CONNECTION_LOCK(connection) do { \
68 if (TRACE_LOCKS) { _dbus_verbose ("LOCK\n"); } \
69 _dbus_rmutex_lock ((connection)->mutex); \
70 TOOK_LOCK_CHECK (connection); \
71 } while (0)
72
73#define CONNECTION_UNLOCK(connection) _dbus_connection_unlock (connection)
74
75#define SLOTS_LOCK(connection) do { \
76 _dbus_rmutex_lock ((connection)->slot_mutex); \
77 } while (0)
78
79#define SLOTS_UNLOCK(connection) do { \
80 _dbus_rmutex_unlock ((connection)->slot_mutex); \
81 } while (0)
82
83#define DISPATCH_STATUS_NAME(s) \
84 ((s) == DBUS_DISPATCH_COMPLETE ? "complete" : \
85 (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \
86 (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" : \
87 "???")
88
206static void
207_dbus_connection_trace_ref (DBusConnection *connection,
208 int old_refcount,
209 int new_refcount,
210 const char *why)
211{
212#ifdef DBUS_ENABLE_VERBOSE_MODE
213 static int enabled = -1;
214
215 _dbus_trace_ref ("DBusConnection", connection, old_refcount, new_refcount,
216 why, "DBUS_CONNECTION_TRACE", &enabled);
217#endif
218}
219
224
229{
232 void *user_data;
234};
235
236
241{
245};
246
247#if HAVE_DECL_MSG_NOSIGNAL
248static DBusAtomic _dbus_modify_sigpipe = { FALSE };
249#else
250static DBusAtomic _dbus_modify_sigpipe = { TRUE };
251#endif
252
257{
291 dbus_uint32_t client_serial;
308 /* These two MUST be bools and not bitfields, because they are protected by a separate lock
309 * from connection->mutex and all bitfields in a word have to be read/written together.
310 * So you can't have a different lock for different bitfields in the same word.
311 */
315 unsigned int shareable : 1;
317 unsigned int exit_on_disconnect : 1;
319 unsigned int builtin_filters_enabled : 1;
321 unsigned int route_peer_messages : 1;
331#ifndef DBUS_DISABLE_CHECKS
332 unsigned int have_connection_lock : 1;
333#endif
334
335#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
336 int generation;
337#endif
338};
339
340static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection);
341static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
342 DBusDispatchStatus new_status);
343static void _dbus_connection_last_unref (DBusConnection *connection);
344static void _dbus_connection_acquire_dispatch (DBusConnection *connection);
345static void _dbus_connection_release_dispatch (DBusConnection *connection);
346static DBusDispatchStatus _dbus_connection_flush_unlocked (DBusConnection *connection);
347static void _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection);
348static dbus_bool_t _dbus_connection_get_is_connected_unlocked (DBusConnection *connection);
349static dbus_bool_t _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
350 dbus_uint32_t client_serial);
351
352static DBusMessageFilter *
353_dbus_message_filter_ref (DBusMessageFilter *filter)
354{
355#ifdef DBUS_DISABLE_ASSERT
356 _dbus_atomic_inc (&filter->refcount);
357#else
358 dbus_int32_t old_value;
359
360 old_value = _dbus_atomic_inc (&filter->refcount);
361 _dbus_assert (old_value > 0);
362#endif
363
364 return filter;
365}
366
367static void
368_dbus_message_filter_unref (DBusMessageFilter *filter)
369{
370 dbus_int32_t old_value;
371
372 old_value = _dbus_atomic_dec (&filter->refcount);
373 _dbus_assert (old_value > 0);
374
375 if (old_value == 1)
376 {
377 if (filter->free_user_data_function)
378 (* filter->free_user_data_function) (filter->user_data);
379
380 dbus_free (filter);
381 }
382}
383
389void
391{
392 CONNECTION_LOCK (connection);
393}
394
400void
402{
403 DBusList *expired_messages;
404 DBusList *iter;
405
406 if (TRACE_LOCKS)
407 {
408 _dbus_verbose ("UNLOCK\n");
409 }
410
411 /* If we had messages that expired (fell off the incoming or outgoing
412 * queues) while we were locked, actually release them now */
413 expired_messages = connection->expired_messages;
414 connection->expired_messages = NULL;
415
416 RELEASING_LOCK_CHECK (connection);
417 _dbus_rmutex_unlock (connection->mutex);
418
419 for (iter = _dbus_list_pop_first_link (&expired_messages);
420 iter != NULL;
421 iter = _dbus_list_pop_first_link (&expired_messages))
422 {
423 DBusMessage *message = iter->data;
424
425 dbus_message_unref (message);
427 }
428}
429
437static void
438_dbus_connection_wakeup_mainloop (DBusConnection *connection)
439{
440 if (connection->wakeup_main_function)
441 (*connection->wakeup_main_function) (connection->wakeup_main_data);
442}
443
444#ifdef DBUS_ENABLE_EMBEDDED_TESTS
457void
458_dbus_connection_test_get_locks (DBusConnection *connection,
459 DBusMutex **mutex_loc,
460 DBusMutex **dispatch_mutex_loc,
461 DBusMutex **io_path_mutex_loc,
462 DBusCondVar **dispatch_cond_loc,
463 DBusCondVar **io_path_cond_loc)
464{
465 *mutex_loc = (DBusMutex *) connection->mutex;
466 *dispatch_mutex_loc = (DBusMutex *) connection->dispatch_mutex;
467 *io_path_mutex_loc = (DBusMutex *) connection->io_path_mutex;
468 *dispatch_cond_loc = connection->dispatch_cond;
469 *io_path_cond_loc = connection->io_path_cond;
470}
471#endif
472
481void
483 DBusList *link)
484{
485 DBusPendingCall *pending;
486 dbus_uint32_t reply_serial;
487 DBusMessage *message;
488
490
492 link);
493 message = link->data;
494
495 /* If this is a reply we're waiting on, remove timeout for it */
496 reply_serial = dbus_message_get_reply_serial (message);
497 if (reply_serial != 0)
498 {
499 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
500 reply_serial);
501 if (pending != NULL)
502 {
506
508 }
509 }
510
511
512
513 connection->n_incoming += 1;
514
515 _dbus_connection_wakeup_mainloop (connection);
516
517 _dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
518 message,
520 dbus_message_get_path (message) ?
521 dbus_message_get_path (message) :
522 "no path",
525 "no interface",
526 dbus_message_get_member (message) ?
527 dbus_message_get_member (message) :
528 "no member",
531 connection,
532 connection->n_incoming);
533
534 _dbus_message_trace_ref (message, -1, -1,
535 "_dbus_conection_queue_received_message_link");
536}
537
546void
548 DBusList *link)
549{
550 HAVE_LOCK_CHECK (connection);
551
552 _dbus_list_append_link (&connection->incoming_messages, link);
553
554 connection->n_incoming += 1;
555
556 _dbus_connection_wakeup_mainloop (connection);
557
558 _dbus_message_trace_ref (link->data, -1, -1,
559 "_dbus_connection_queue_synthesized_message_link");
560
561 _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
562 link->data, connection, connection->n_incoming);
563}
564
565
575{
576 HAVE_LOCK_CHECK (connection);
577 return connection->outgoing_messages != NULL;
578}
579
591{
592 dbus_bool_t v;
593
594 _dbus_return_val_if_fail (connection != NULL, FALSE);
595
596 CONNECTION_LOCK (connection);
598 CONNECTION_UNLOCK (connection);
599
600 return v;
601}
602
612{
613 HAVE_LOCK_CHECK (connection);
614
615 return _dbus_list_get_last (&connection->outgoing_messages);
616}
617
626void
628 DBusMessage *message)
629{
630 DBusList *link;
631
632 HAVE_LOCK_CHECK (connection);
633
634 /* This can be called before we even complete authentication, since
635 * it's called on disconnect to clean up the outgoing queue.
636 * It's also called as we successfully send each message.
637 */
638
639 link = _dbus_list_get_last_link (&connection->outgoing_messages);
640 _dbus_assert (link != NULL);
641 _dbus_assert (link->data == message);
642
644 link);
645 _dbus_list_prepend_link (&connection->expired_messages, link);
646
647 connection->n_outgoing -= 1;
648
649 _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
650 message,
652 dbus_message_get_path (message) ?
653 dbus_message_get_path (message) :
654 "no path",
657 "no interface",
658 dbus_message_get_member (message) ?
659 dbus_message_get_member (message) :
660 "no member",
662 connection, connection->n_outgoing);
663
664 /* It's OK that in principle we call the notify function, because for the
665 * outgoing limit, there isn't one */
666 _dbus_message_remove_counter (message, connection->outgoing_counter);
667
668 /* The message will actually be unreffed when we unlock */
669}
670
673 DBusWatch *watch);
676 DBusWatch *watch);
679 DBusWatch *watch,
680 dbus_bool_t enabled);
681
682static dbus_bool_t
683protected_change_watch (DBusConnection *connection,
684 DBusWatch *watch,
685 DBusWatchAddFunction add_function,
686 DBusWatchRemoveFunction remove_function,
687 DBusWatchToggleFunction toggle_function,
688 dbus_bool_t enabled)
689{
690 dbus_bool_t retval;
691
692 HAVE_LOCK_CHECK (connection);
693
694 /* The original purpose of protected_change_watch() was to hold a
695 * ref on the connection while dropping the connection lock, then
696 * calling out to the app. This was a broken hack that did not
697 * work, since the connection was in a hosed state (no WatchList
698 * field) while calling out.
699 *
700 * So for now we'll just keep the lock while calling out. This means
701 * apps are not allowed to call DBusConnection methods inside a
702 * watch function or they will deadlock.
703 *
704 * The "real fix" is to use the _and_unlock() pattern found
705 * elsewhere in the code, to defer calling out to the app until
706 * we're about to drop locks and return flow of control to the app
707 * anyway.
708 *
709 * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
710 */
711
712 if (connection->watches)
713 {
714 if (add_function)
715 retval = (* add_function) (connection->watches, watch);
716 else if (remove_function)
717 {
718 retval = TRUE;
719 (* remove_function) (connection->watches, watch);
720 }
721 else
722 {
723 retval = TRUE;
724 (* toggle_function) (connection->watches, watch, enabled);
725 }
726 return retval;
727 }
728 else
729 return FALSE;
730}
731
732
746 DBusWatch *watch)
747{
748 return protected_change_watch (connection, watch,
750 NULL, NULL, FALSE);
751}
752
762void
764 DBusWatch *watch)
765{
766 protected_change_watch (connection, watch,
767 NULL,
769 NULL, FALSE);
770}
771
782void
784 DBusWatch *watch,
785 dbus_bool_t enabled)
786{
787 _dbus_assert (watch != NULL);
788
789 protected_change_watch (connection, watch,
790 NULL, NULL,
792 enabled);
793}
794
797 DBusTimeout *timeout);
800 DBusTimeout *timeout);
803 DBusTimeout *timeout,
804 dbus_bool_t enabled);
805
806static dbus_bool_t
807protected_change_timeout (DBusConnection *connection,
808 DBusTimeout *timeout,
809 DBusTimeoutAddFunction add_function,
810 DBusTimeoutRemoveFunction remove_function,
811 DBusTimeoutToggleFunction toggle_function,
812 dbus_bool_t enabled)
813{
814 dbus_bool_t retval;
815
816 HAVE_LOCK_CHECK (connection);
817
818 /* The original purpose of protected_change_timeout() was to hold a
819 * ref on the connection while dropping the connection lock, then
820 * calling out to the app. This was a broken hack that did not
821 * work, since the connection was in a hosed state (no TimeoutList
822 * field) while calling out.
823 *
824 * So for now we'll just keep the lock while calling out. This means
825 * apps are not allowed to call DBusConnection methods inside a
826 * timeout function or they will deadlock.
827 *
828 * The "real fix" is to use the _and_unlock() pattern found
829 * elsewhere in the code, to defer calling out to the app until
830 * we're about to drop locks and return flow of control to the app
831 * anyway.
832 *
833 * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
834 */
835
836 if (connection->timeouts)
837 {
838 if (add_function)
839 retval = (* add_function) (connection->timeouts, timeout);
840 else if (remove_function)
841 {
842 retval = TRUE;
843 (* remove_function) (connection->timeouts, timeout);
844 }
845 else
846 {
847 retval = TRUE;
848 (* toggle_function) (connection->timeouts, timeout, enabled);
849 }
850 return retval;
851 }
852 else
853 return FALSE;
854}
855
870 DBusTimeout *timeout)
871{
872 return protected_change_timeout (connection, timeout,
874 NULL, NULL, FALSE);
875}
876
886void
888 DBusTimeout *timeout)
889{
890 protected_change_timeout (connection, timeout,
891 NULL,
893 NULL, FALSE);
894}
895
906void
908 DBusTimeout *timeout,
909 dbus_bool_t enabled)
910{
911 protected_change_timeout (connection, timeout,
912 NULL, NULL,
914 enabled);
915}
916
917static dbus_bool_t
918_dbus_connection_attach_pending_call_unlocked (DBusConnection *connection,
919 DBusPendingCall *pending)
920{
921 dbus_uint32_t reply_serial;
922 DBusTimeout *timeout;
923
924 HAVE_LOCK_CHECK (connection);
925
926 reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
927
928 _dbus_assert (reply_serial != 0);
929
930 timeout = _dbus_pending_call_get_timeout_unlocked (pending);
931
932 if (timeout)
933 {
934 if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
935 return FALSE;
936
938 reply_serial,
939 pending))
940 {
941 _dbus_connection_remove_timeout_unlocked (connection, timeout);
942
944 HAVE_LOCK_CHECK (connection);
945 return FALSE;
946 }
947
949 }
950 else
951 {
953 reply_serial,
954 pending))
955 {
956 HAVE_LOCK_CHECK (connection);
957 return FALSE;
958 }
959 }
960
962
963 HAVE_LOCK_CHECK (connection);
964
965 return TRUE;
966}
967
968static void
969free_pending_call_on_hash_removal (void *data)
970{
971 DBusPendingCall *pending;
972 DBusConnection *connection;
973
974 if (data == NULL)
975 return;
976
977 pending = data;
978
979 connection = _dbus_pending_call_get_connection_unlocked (pending);
980
981 HAVE_LOCK_CHECK (connection);
982
984 {
987
989 }
990
991 /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock
992 * here, but the pending call finalizer could in principle call out to
993 * application code so we pretty much have to... some larger code reorg
994 * might be needed.
995 */
998 CONNECTION_LOCK (connection);
1000}
1001
1002static void
1003_dbus_connection_detach_pending_call_unlocked (DBusConnection *connection,
1004 DBusPendingCall *pending)
1005{
1006 /* This ends up unlocking to call the pending call finalizer, which is unexpected to
1007 * say the least.
1008 */
1011}
1012
1013static void
1014_dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection,
1015 DBusPendingCall *pending)
1016{
1017 /* The idea here is to avoid finalizing the pending call
1018 * with the lock held, since there's a destroy notifier
1019 * in pending call that goes out to application code.
1020 *
1021 * There's an extra unlock inside the hash table
1022 * "free pending call" function FIXME...
1023 */
1027
1031
1033
1035}
1036
1045void
1047 DBusPendingCall *pending)
1048{
1049 CONNECTION_LOCK (connection);
1050 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
1051}
1052
1062static dbus_bool_t
1063_dbus_connection_acquire_io_path (DBusConnection *connection,
1064 int timeout_milliseconds)
1065{
1066 dbus_bool_t we_acquired;
1067
1068 HAVE_LOCK_CHECK (connection);
1069
1070 /* We don't want the connection to vanish */
1071 _dbus_connection_ref_unlocked (connection);
1072
1073 /* We will only touch io_path_acquired which is protected by our mutex */
1074 CONNECTION_UNLOCK (connection);
1075
1076 _dbus_verbose ("locking io_path_mutex\n");
1077 _dbus_cmutex_lock (connection->io_path_mutex);
1078
1079 _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n",
1080 connection->io_path_acquired, timeout_milliseconds);
1081
1082 we_acquired = FALSE;
1083
1084 if (connection->io_path_acquired)
1085 {
1086 if (timeout_milliseconds != -1)
1087 {
1088 _dbus_verbose ("waiting %d for IO path to be acquirable\n",
1089 timeout_milliseconds);
1090
1091 if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
1092 connection->io_path_mutex,
1093 timeout_milliseconds))
1094 {
1095 /* We timed out before anyone signaled. */
1096 /* (writing the loop to handle the !timedout case by
1097 * waiting longer if needed is a pain since dbus
1098 * wraps pthread_cond_timedwait to take a relative
1099 * time instead of absolute, something kind of stupid
1100 * on our part. for now it doesn't matter, we will just
1101 * end up back here eventually.)
1102 */
1103 }
1104 }
1105 else
1106 {
1107 while (connection->io_path_acquired)
1108 {
1109 _dbus_verbose ("waiting for IO path to be acquirable\n");
1110 _dbus_condvar_wait (connection->io_path_cond,
1111 connection->io_path_mutex);
1112 }
1113 }
1114 }
1115
1116 if (!connection->io_path_acquired)
1117 {
1118 we_acquired = TRUE;
1119 connection->io_path_acquired = TRUE;
1120 }
1121
1122 _dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n",
1123 connection->io_path_acquired, we_acquired);
1124
1125 _dbus_verbose ("unlocking io_path_mutex\n");
1126 _dbus_cmutex_unlock (connection->io_path_mutex);
1127
1128 CONNECTION_LOCK (connection);
1129
1130 HAVE_LOCK_CHECK (connection);
1131
1133
1134 return we_acquired;
1135}
1136
1144static void
1145_dbus_connection_release_io_path (DBusConnection *connection)
1146{
1147 HAVE_LOCK_CHECK (connection);
1148
1149 _dbus_verbose ("locking io_path_mutex\n");
1150 _dbus_cmutex_lock (connection->io_path_mutex);
1151
1152 _dbus_assert (connection->io_path_acquired);
1153
1154 _dbus_verbose ("start connection->io_path_acquired = %d\n",
1155 connection->io_path_acquired);
1156
1157 connection->io_path_acquired = FALSE;
1159
1160 _dbus_verbose ("unlocking io_path_mutex\n");
1161 _dbus_cmutex_unlock (connection->io_path_mutex);
1162}
1163
1199void
1201 DBusPendingCall *pending,
1202 unsigned int flags,
1203 int timeout_milliseconds)
1204{
1205 _dbus_verbose ("start\n");
1206
1207 HAVE_LOCK_CHECK (connection);
1208
1209 if (connection->n_outgoing == 0)
1210 flags &= ~DBUS_ITERATION_DO_WRITING;
1211
1212 if (_dbus_connection_acquire_io_path (connection,
1213 (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
1214 {
1215 HAVE_LOCK_CHECK (connection);
1216
1217 if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending))
1218 {
1219 _dbus_verbose ("pending call completed while acquiring I/O path");
1220 }
1221 else if ( (pending != NULL) &&
1222 _dbus_connection_peek_for_reply_unlocked (connection,
1224 {
1225 _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)");
1226 }
1227 else
1228 {
1230 flags, timeout_milliseconds);
1231 }
1232
1233 _dbus_connection_release_io_path (connection);
1234 }
1235
1236 HAVE_LOCK_CHECK (connection);
1237
1238 _dbus_verbose ("end\n");
1239}
1240
1252{
1253 DBusConnection *connection;
1254 DBusWatchList *watch_list;
1255 DBusTimeoutList *timeout_list;
1256 DBusHashTable *pending_replies;
1257 DBusList *disconnect_link;
1258 DBusMessage *disconnect_message;
1259 DBusCounter *outgoing_counter;
1260 DBusObjectTree *objects;
1261
1262 watch_list = NULL;
1263 connection = NULL;
1264 pending_replies = NULL;
1265 timeout_list = NULL;
1266 disconnect_link = NULL;
1267 disconnect_message = NULL;
1268 outgoing_counter = NULL;
1269 objects = NULL;
1270
1271 watch_list = _dbus_watch_list_new ();
1272 if (watch_list == NULL)
1273 goto error;
1274
1275 timeout_list = _dbus_timeout_list_new ();
1276 if (timeout_list == NULL)
1277 goto error;
1278
1279 pending_replies =
1281 NULL,
1282 (DBusFreeFunction)free_pending_call_on_hash_removal);
1283 if (pending_replies == NULL)
1284 goto error;
1285
1286 connection = dbus_new0 (DBusConnection, 1);
1287 if (connection == NULL)
1288 goto error;
1289
1290 _dbus_rmutex_new_at_location (&connection->mutex);
1291 if (connection->mutex == NULL)
1292 goto error;
1293
1295 if (connection->io_path_mutex == NULL)
1296 goto error;
1297
1299 if (connection->dispatch_mutex == NULL)
1300 goto error;
1301
1303 if (connection->dispatch_cond == NULL)
1304 goto error;
1305
1307 if (connection->io_path_cond == NULL)
1308 goto error;
1309
1311 if (connection->slot_mutex == NULL)
1312 goto error;
1313
1314 disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
1316 "Disconnected");
1317
1318 if (disconnect_message == NULL)
1319 goto error;
1320
1321 disconnect_link = _dbus_list_alloc_link (disconnect_message);
1322 if (disconnect_link == NULL)
1323 goto error;
1324
1325 outgoing_counter = _dbus_counter_new ();
1326 if (outgoing_counter == NULL)
1327 goto error;
1328
1329 objects = _dbus_object_tree_new (connection);
1330 if (objects == NULL)
1331 goto error;
1332
1333 if (_dbus_atomic_get (&_dbus_modify_sigpipe) != 0)
1335
1336 /* initialized to 0: use atomic op to avoid mixing atomic and non-atomic */
1337 _dbus_atomic_inc (&connection->refcount);
1338 connection->transport = transport;
1339 connection->watches = watch_list;
1340 connection->timeouts = timeout_list;
1341 connection->pending_replies = pending_replies;
1342 connection->outgoing_counter = outgoing_counter;
1343 connection->filter_list = NULL;
1344 connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
1345 connection->objects = objects;
1346 connection->exit_on_disconnect = FALSE;
1347 connection->shareable = FALSE;
1348 connection->builtin_filters_enabled = TRUE;
1349 connection->route_peer_messages = FALSE;
1350 connection->disconnected_message_arrived = FALSE;
1352
1353#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
1354 connection->generation = _dbus_current_generation;
1355#endif
1356
1357 _dbus_data_slot_list_init (&connection->slot_list);
1358
1359 connection->client_serial = 1;
1360
1361 connection->disconnect_message_link = disconnect_link;
1362
1363 CONNECTION_LOCK (connection);
1364
1365 if (!_dbus_transport_set_connection (transport, connection))
1366 {
1367 CONNECTION_UNLOCK (connection);
1368
1369 goto error;
1370 }
1371
1372 _dbus_transport_ref (transport);
1373
1374 CONNECTION_UNLOCK (connection);
1375
1376 _dbus_connection_trace_ref (connection, 0, 1, "new_for_transport");
1377 return connection;
1378
1379 error:
1380 if (disconnect_message != NULL)
1381 dbus_message_unref (disconnect_message);
1382
1383 if (disconnect_link != NULL)
1384 _dbus_list_free_link (disconnect_link);
1385
1386 if (connection != NULL)
1387 {
1390 _dbus_rmutex_free_at_location (&connection->mutex);
1394 dbus_free (connection);
1395 }
1396 if (pending_replies)
1397 _dbus_hash_table_unref (pending_replies);
1398
1399 if (watch_list)
1400 _dbus_watch_list_free (watch_list);
1401
1402 if (timeout_list)
1403 _dbus_timeout_list_free (timeout_list);
1404
1405 if (outgoing_counter)
1406 _dbus_counter_unref (outgoing_counter);
1407
1408 if (objects)
1409 _dbus_object_tree_unref (objects);
1410
1411 return NULL;
1412}
1413
1423{
1424 dbus_int32_t old_refcount;
1425
1426 _dbus_assert (connection != NULL);
1427 _dbus_assert (connection->generation == _dbus_current_generation);
1428
1429 HAVE_LOCK_CHECK (connection);
1430
1431 old_refcount = _dbus_atomic_inc (&connection->refcount);
1432 _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1,
1433 "ref_unlocked");
1434
1435 return connection;
1436}
1437
1444void
1446{
1447 dbus_int32_t old_refcount;
1448
1449 HAVE_LOCK_CHECK (connection);
1450
1451 _dbus_assert (connection != NULL);
1452
1453 old_refcount = _dbus_atomic_dec (&connection->refcount);
1454
1455 _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1,
1456 "unref_unlocked");
1457
1458 if (old_refcount == 1)
1459 _dbus_connection_last_unref (connection);
1460}
1461
1471dbus_uint32_t
1473{
1474 dbus_uint32_t serial;
1475
1476 serial = connection->client_serial++;
1477
1478 if (connection->client_serial == 0)
1479 connection->client_serial = 1;
1480
1481 return serial;
1482}
1483
1499 unsigned int condition,
1500 void *data)
1501{
1502 DBusConnection *connection;
1503 dbus_bool_t retval;
1504 DBusDispatchStatus status;
1505
1506 connection = data;
1507
1508 _dbus_verbose ("start\n");
1509
1510 CONNECTION_LOCK (connection);
1511
1512 if (!_dbus_connection_acquire_io_path (connection, 1))
1513 {
1514 /* another thread is handling the message */
1515 CONNECTION_UNLOCK (connection);
1516 return TRUE;
1517 }
1518
1519 HAVE_LOCK_CHECK (connection);
1520 retval = _dbus_transport_handle_watch (connection->transport,
1521 watch, condition);
1522
1523 _dbus_connection_release_io_path (connection);
1524
1525 HAVE_LOCK_CHECK (connection);
1526
1527 _dbus_verbose ("middle\n");
1528
1529 status = _dbus_connection_get_dispatch_status_unlocked (connection);
1530
1531 /* this calls out to user code */
1532 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
1533
1534 _dbus_verbose ("end\n");
1535
1536 return retval;
1537}
1538
1539/* Protected by _DBUS_LOCK (shared_connections) */
1540static DBusHashTable *shared_connections = NULL;
1541static DBusList *shared_connections_no_guid = NULL;
1542
1543static void
1544close_connection_on_shutdown (DBusConnection *connection)
1545{
1546 DBusMessage *message;
1547
1548 dbus_connection_ref (connection);
1550
1551 /* Churn through to the Disconnected message */
1552 while ((message = dbus_connection_pop_message (connection)))
1553 {
1554 dbus_message_unref (message);
1555 }
1556 dbus_connection_unref (connection);
1557}
1558
1559static void
1560shared_connections_shutdown (void *data)
1561{
1562 int n_entries;
1563
1564 if (!_DBUS_LOCK (shared_connections))
1565 {
1566 /* We'd have initialized locks before adding anything, so there
1567 * can't be anything there. */
1568 return;
1569 }
1570
1571 /* This is a little bit unpleasant... better ideas? */
1572 while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
1573 {
1574 DBusConnection *connection;
1575 DBusHashIter iter;
1576
1577 _dbus_hash_iter_init (shared_connections, &iter);
1578 _dbus_hash_iter_next (&iter);
1579
1580 connection = _dbus_hash_iter_get_value (&iter);
1581
1582 _DBUS_UNLOCK (shared_connections);
1583 close_connection_on_shutdown (connection);
1584 if (!_DBUS_LOCK (shared_connections))
1585 _dbus_assert_not_reached ("global locks were already initialized");
1586
1587 /* The connection should now be dead and not in our hash ... */
1588 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
1589 }
1590
1591 _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
1592
1593 _dbus_hash_table_unref (shared_connections);
1594 shared_connections = NULL;
1595
1596 if (shared_connections_no_guid != NULL)
1597 {
1598 DBusConnection *connection;
1599 connection = _dbus_list_pop_first (&shared_connections_no_guid);
1600 while (connection != NULL)
1601 {
1602 _DBUS_UNLOCK (shared_connections);
1603 close_connection_on_shutdown (connection);
1604 if (!_DBUS_LOCK (shared_connections))
1605 _dbus_assert_not_reached ("global locks were already initialized");
1606 connection = _dbus_list_pop_first (&shared_connections_no_guid);
1607 }
1608 }
1609
1610 shared_connections_no_guid = NULL;
1611
1612 _DBUS_UNLOCK (shared_connections);
1613}
1614
1615static dbus_bool_t
1616connection_lookup_shared (DBusAddressEntry *entry,
1617 DBusConnection **result)
1618{
1619 _dbus_verbose ("checking for existing connection\n");
1620
1621 *result = NULL;
1622
1623 if (!_DBUS_LOCK (shared_connections))
1624 {
1625 /* If it was shared, we'd have initialized global locks when we put
1626 * it in shared_connections. */
1627 return FALSE;
1628 }
1629
1630 if (shared_connections == NULL)
1631 {
1632 _dbus_verbose ("creating shared_connections hash table\n");
1633
1634 shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
1635 dbus_free,
1636 NULL);
1637 if (shared_connections == NULL)
1638 {
1639 _DBUS_UNLOCK (shared_connections);
1640 return FALSE;
1641 }
1642
1643 if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
1644 {
1645 _dbus_hash_table_unref (shared_connections);
1646 shared_connections = NULL;
1647 _DBUS_UNLOCK (shared_connections);
1648 return FALSE;
1649 }
1650
1651 _dbus_verbose (" successfully created shared_connections\n");
1652
1653 _DBUS_UNLOCK (shared_connections);
1654 return TRUE; /* no point looking up in the hash we just made */
1655 }
1656 else
1657 {
1658 const char *guid;
1659
1660 guid = dbus_address_entry_get_value (entry, "guid");
1661
1662 if (guid != NULL)
1663 {
1664 DBusConnection *connection;
1665
1666 connection = _dbus_hash_table_lookup_string (shared_connections,
1667 guid);
1668
1669 if (connection)
1670 {
1671 /* The DBusConnection can't be finalized without taking
1672 * the shared_connections lock to remove it from the
1673 * hash. So it's safe to ref the connection here.
1674 * However, it may be disconnected if the Disconnected
1675 * message hasn't been processed yet, in which case we
1676 * want to pretend it isn't in the hash and avoid
1677 * returning it.
1678 *
1679 * The idea is to avoid ever returning a disconnected connection
1680 * from dbus_connection_open(). We could just synchronously
1681 * drop our shared ref to the connection on connection disconnect,
1682 * and then assert here that the connection is connected, but
1683 * that causes reentrancy headaches.
1684 */
1685 CONNECTION_LOCK (connection);
1686 if (_dbus_connection_get_is_connected_unlocked (connection))
1687 {
1688 _dbus_connection_ref_unlocked (connection);
1689 *result = connection;
1690 _dbus_verbose ("looked up existing connection to server guid %s\n",
1691 guid);
1692 }
1693 else
1694 {
1695 _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
1696 guid);
1697 }
1698 CONNECTION_UNLOCK (connection);
1699 }
1700 }
1701
1702 _DBUS_UNLOCK (shared_connections);
1703 return TRUE;
1704 }
1705}
1706
1707static dbus_bool_t
1708connection_record_shared_unlocked (DBusConnection *connection,
1709 const char *guid)
1710{
1711 char *guid_key;
1712 char *guid_in_connection;
1713
1714 HAVE_LOCK_CHECK (connection);
1715 _dbus_assert (connection->server_guid == NULL);
1716 _dbus_assert (connection->shareable);
1717
1718 /* get a hard ref on this connection, even if
1719 * we won't in fact store it in the hash, we still
1720 * need to hold a ref on it until it's disconnected.
1721 */
1722 _dbus_connection_ref_unlocked (connection);
1723
1724 if (guid == NULL)
1725 {
1726 if (!_DBUS_LOCK (shared_connections))
1727 return FALSE;
1728
1729 if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
1730 {
1731 _DBUS_UNLOCK (shared_connections);
1732 return FALSE;
1733 }
1734
1735 _DBUS_UNLOCK (shared_connections);
1736 return TRUE; /* don't store in the hash */
1737 }
1738
1739 /* A separate copy of the key is required in the hash table, because
1740 * we don't have a lock on the connection when we are doing a hash
1741 * lookup.
1742 */
1743
1744 guid_key = _dbus_strdup (guid);
1745 if (guid_key == NULL)
1746 return FALSE;
1747
1748 guid_in_connection = _dbus_strdup (guid);
1749 if (guid_in_connection == NULL)
1750 {
1751 dbus_free (guid_key);
1752 return FALSE;
1753 }
1754
1755 if (!_DBUS_LOCK (shared_connections))
1756 {
1757 dbus_free (guid_in_connection);
1758 dbus_free (guid_key);
1759 return FALSE;
1760 }
1761
1762 _dbus_assert (shared_connections != NULL);
1763
1764 if (!_dbus_hash_table_insert_string (shared_connections,
1765 guid_key, connection))
1766 {
1767 dbus_free (guid_key);
1768 dbus_free (guid_in_connection);
1769 _DBUS_UNLOCK (shared_connections);
1770 return FALSE;
1771 }
1772
1773 connection->server_guid = guid_in_connection;
1774
1775 _dbus_verbose ("stored connection to %s to be shared\n",
1776 connection->server_guid);
1777
1778 _DBUS_UNLOCK (shared_connections);
1779
1780 _dbus_assert (connection->server_guid != NULL);
1781
1782 return TRUE;
1783}
1784
1785static void
1786connection_forget_shared_unlocked (DBusConnection *connection)
1787{
1788 HAVE_LOCK_CHECK (connection);
1789
1790 if (!connection->shareable)
1791 return;
1792
1793 if (!_DBUS_LOCK (shared_connections))
1794 {
1795 /* If it was shared, we'd have initialized global locks when we put
1796 * it in the table; so it can't be there. */
1797 return;
1798 }
1799
1800 if (connection->server_guid != NULL)
1801 {
1802 _dbus_verbose ("dropping connection to %s out of the shared table\n",
1803 connection->server_guid);
1804
1805 if (!_dbus_hash_table_remove_string (shared_connections,
1806 connection->server_guid))
1807 _dbus_assert_not_reached ("connection was not in the shared table");
1808
1809 dbus_free (connection->server_guid);
1810 connection->server_guid = NULL;
1811 }
1812 else
1813 {
1814 _dbus_list_remove (&shared_connections_no_guid, connection);
1815 }
1816
1817 _DBUS_UNLOCK (shared_connections);
1818
1819 /* remove our reference held on all shareable connections */
1821}
1822
1823static DBusConnection*
1824connection_try_from_address_entry (DBusAddressEntry *entry,
1825 DBusError *error)
1826{
1827 DBusTransport *transport;
1828 DBusConnection *connection;
1829
1830 transport = _dbus_transport_open (entry, error);
1831
1832 if (transport == NULL)
1833 {
1834 _DBUS_ASSERT_ERROR_IS_SET (error);
1835 return NULL;
1836 }
1837
1838 connection = _dbus_connection_new_for_transport (transport);
1839
1840 _dbus_transport_unref (transport);
1841
1842 if (connection == NULL)
1843 {
1844 _DBUS_SET_OOM (error);
1845 return NULL;
1846 }
1847
1848#ifndef DBUS_DISABLE_CHECKS
1849 _dbus_assert (!connection->have_connection_lock);
1850#endif
1851 return connection;
1852}
1853
1854/*
1855 * If the shared parameter is true, then any existing connection will
1856 * be used (and if a new connection is created, it will be available
1857 * for use by others). If the shared parameter is false, a new
1858 * connection will always be created, and the new connection will
1859 * never be returned to other callers.
1860 *
1861 * @param address the address
1862 * @param shared whether the connection is shared or private
1863 * @param error error return
1864 * @returns the connection or #NULL on error
1865 */
1866static DBusConnection*
1867_dbus_connection_open_internal (const char *address,
1868 dbus_bool_t shared,
1869 DBusError *error)
1870{
1871 DBusConnection *connection;
1872 DBusAddressEntry **entries;
1873 DBusError tmp_error = DBUS_ERROR_INIT;
1874 DBusError first_error = DBUS_ERROR_INIT;
1875 int len, i;
1876
1877 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1878
1879 _dbus_verbose ("opening %s connection to: %s\n",
1880 shared ? "shared" : "private", address);
1881
1882 if (!dbus_parse_address (address, &entries, &len, error))
1883 return NULL;
1884
1885 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1886
1887 connection = NULL;
1888
1889 for (i = 0; i < len; i++)
1890 {
1891 if (shared)
1892 {
1893 if (!connection_lookup_shared (entries[i], &connection))
1894 _DBUS_SET_OOM (&tmp_error);
1895 }
1896
1897 if (connection == NULL)
1898 {
1899 connection = connection_try_from_address_entry (entries[i],
1900 &tmp_error);
1901
1902 if (connection != NULL && shared)
1903 {
1904 const char *guid;
1905
1906 connection->shareable = TRUE;
1907
1908 /* guid may be NULL */
1909 guid = dbus_address_entry_get_value (entries[i], "guid");
1910
1911 CONNECTION_LOCK (connection);
1912
1913 if (!connection_record_shared_unlocked (connection, guid))
1914 {
1915 _DBUS_SET_OOM (&tmp_error);
1916 _dbus_connection_close_possibly_shared_and_unlock (connection);
1917 dbus_connection_unref (connection);
1918 connection = NULL;
1919 }
1920 else
1921 CONNECTION_UNLOCK (connection);
1922 }
1923 }
1924
1925 if (connection)
1926 break;
1927
1928 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
1929
1930 if (i == 0)
1931 dbus_move_error (&tmp_error, &first_error);
1932 else
1933 dbus_error_free (&tmp_error);
1934 }
1935
1936 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1937 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
1938
1939 if (connection == NULL)
1940 {
1941 _DBUS_ASSERT_ERROR_IS_SET (&first_error);
1942 dbus_move_error (&first_error, error);
1943 }
1944 else
1945 dbus_error_free (&first_error);
1946
1947 dbus_address_entries_free (entries);
1948 return connection;
1949}
1950
1959void
1961{
1962 _dbus_assert (connection != NULL);
1963 _dbus_assert (connection->generation == _dbus_current_generation);
1964
1965 CONNECTION_LOCK (connection);
1966 _dbus_connection_close_possibly_shared_and_unlock (connection);
1967}
1968
1970_dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
1971{
1972 DBusPreallocatedSend *preallocated;
1973
1974 HAVE_LOCK_CHECK (connection);
1975
1976 _dbus_assert (connection != NULL);
1977
1978 preallocated = dbus_new (DBusPreallocatedSend, 1);
1979 if (preallocated == NULL)
1980 return NULL;
1981
1982 preallocated->queue_link = _dbus_list_alloc_link (NULL);
1983 if (preallocated->queue_link == NULL)
1984 goto failed_0;
1985
1986 preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
1987 if (preallocated->counter_link == NULL)
1988 goto failed_1;
1989
1990 _dbus_counter_ref (preallocated->counter_link->data);
1991
1992 preallocated->connection = connection;
1993
1994 return preallocated;
1995
1996 failed_1:
1997 _dbus_list_free_link (preallocated->queue_link);
1998 failed_0:
1999 dbus_free (preallocated);
2000
2001 return NULL;
2002}
2003
2004/* Called with lock held, does not update dispatch status */
2005static void
2006_dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection,
2007 DBusPreallocatedSend *preallocated,
2008 DBusMessage *message,
2009 dbus_uint32_t *client_serial)
2010{
2011 dbus_uint32_t serial;
2012
2013 preallocated->queue_link->data = message;
2015 preallocated->queue_link);
2016
2017 /* It's OK that we'll never call the notify function, because for the
2018 * outgoing limit, there isn't one */
2020 preallocated->counter_link);
2021
2022 dbus_free (preallocated);
2023 preallocated = NULL;
2024
2025 dbus_message_ref (message);
2026
2027 connection->n_outgoing += 1;
2028
2029 _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
2030 message,
2032 dbus_message_get_path (message) ?
2033 dbus_message_get_path (message) :
2034 "no path",
2035 dbus_message_get_interface (message) ?
2036 dbus_message_get_interface (message) :
2037 "no interface",
2038 dbus_message_get_member (message) ?
2039 dbus_message_get_member (message) :
2040 "no member",
2044 "null",
2045 connection,
2046 connection->n_outgoing);
2047
2048 if (dbus_message_get_serial (message) == 0)
2049 {
2050 serial = _dbus_connection_get_next_client_serial (connection);
2051 dbus_message_set_serial (message, serial);
2052 if (client_serial)
2053 *client_serial = serial;
2054 }
2055 else
2056 {
2057 if (client_serial)
2058 *client_serial = dbus_message_get_serial (message);
2059 }
2060
2061 _dbus_verbose ("Message %p serial is %u\n",
2062 message, dbus_message_get_serial (message));
2063
2064 dbus_message_lock (message);
2065
2066 /* Now we need to run an iteration to hopefully just write the messages
2067 * out immediately, and otherwise get them queued up
2068 */
2070 NULL,
2071 DBUS_ITERATION_DO_WRITING,
2072 -1);
2073
2074 /* If stuff is still queued up, be sure we wake up the main loop */
2075 if (connection->n_outgoing > 0)
2076 _dbus_connection_wakeup_mainloop (connection);
2077}
2078
2079static void
2080_dbus_connection_send_preallocated_and_unlock (DBusConnection *connection,
2081 DBusPreallocatedSend *preallocated,
2082 DBusMessage *message,
2083 dbus_uint32_t *client_serial)
2084{
2085 DBusDispatchStatus status;
2086
2087 HAVE_LOCK_CHECK (connection);
2088
2089 _dbus_connection_send_preallocated_unlocked_no_update (connection,
2090 preallocated,
2091 message, client_serial);
2092
2093 _dbus_verbose ("middle\n");
2094 status = _dbus_connection_get_dispatch_status_unlocked (connection);
2095
2096 /* this calls out to user code */
2097 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2098}
2099
2111 DBusMessage *message,
2112 dbus_uint32_t *client_serial)
2113{
2114 DBusPreallocatedSend *preallocated;
2115
2116 _dbus_assert (connection != NULL);
2117 _dbus_assert (message != NULL);
2118
2119 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
2120 if (preallocated == NULL)
2121 {
2122 CONNECTION_UNLOCK (connection);
2123 return FALSE;
2124 }
2125
2126 _dbus_connection_send_preallocated_and_unlock (connection,
2127 preallocated,
2128 message,
2129 client_serial);
2130 return TRUE;
2131}
2132
2157void
2159{
2160 dbus_int32_t refcount;
2161
2162 CONNECTION_LOCK (connection);
2163
2164 refcount = _dbus_atomic_get (&connection->refcount);
2165 /* The caller should have at least one ref */
2166 _dbus_assert (refcount >= 1);
2167
2168 if (refcount == 1)
2169 _dbus_connection_close_possibly_shared_and_unlock (connection);
2170 else
2171 CONNECTION_UNLOCK (connection);
2172}
2173
2174
2184static void
2185_dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
2186{
2187 if (timeout_milliseconds == -1)
2189 else if (timeout_milliseconds < 100)
2190 ; /* just busy loop */
2191 else if (timeout_milliseconds <= 1000)
2192 _dbus_sleep_milliseconds (timeout_milliseconds / 3);
2193 else
2195}
2196
2197static DBusMessage *
2198generate_local_error_message (dbus_uint32_t serial,
2199 const char *error_name,
2200 const char *error_msg)
2201{
2202 DBusMessage *message;
2204 if (!message)
2205 goto out;
2206
2207 if (!dbus_message_set_error_name (message, error_name))
2208 {
2209 dbus_message_unref (message);
2210 message = NULL;
2211 goto out;
2212 }
2213
2214 dbus_message_set_no_reply (message, TRUE);
2215
2216 if (!dbus_message_set_reply_serial (message,
2217 serial))
2218 {
2219 dbus_message_unref (message);
2220 message = NULL;
2221 goto out;
2222 }
2223
2224 if (error_msg != NULL)
2225 {
2226 DBusMessageIter iter;
2227
2228 dbus_message_iter_init_append (message, &iter);
2231 &error_msg))
2232 {
2233 dbus_message_unref (message);
2234 message = NULL;
2235 goto out;
2236 }
2237 }
2238
2239 out:
2240 return message;
2241}
2242
2243/*
2244 * Peek the incoming queue to see if we got reply for a specific serial
2245 */
2246static dbus_bool_t
2247_dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
2248 dbus_uint32_t client_serial)
2249{
2250 DBusList *link;
2251 HAVE_LOCK_CHECK (connection);
2252
2253 link = _dbus_list_get_first_link (&connection->incoming_messages);
2254
2255 while (link != NULL)
2256 {
2257 DBusMessage *reply = link->data;
2258
2259 if (dbus_message_get_reply_serial (reply) == client_serial)
2260 {
2261 _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial);
2262 return TRUE;
2263 }
2264 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
2265 }
2266
2267 return FALSE;
2268}
2269
2270/* This is slightly strange since we can pop a message here without
2271 * the dispatch lock.
2272 */
2273static DBusMessage*
2274check_for_reply_unlocked (DBusConnection *connection,
2275 dbus_uint32_t client_serial)
2276{
2277 DBusList *link;
2278
2279 HAVE_LOCK_CHECK (connection);
2280
2281 link = _dbus_list_get_first_link (&connection->incoming_messages);
2282
2283 while (link != NULL)
2284 {
2285 DBusMessage *reply = link->data;
2286
2287 if (dbus_message_get_reply_serial (reply) == client_serial)
2288 {
2289 _dbus_list_remove_link (&connection->incoming_messages, link);
2290 connection->n_incoming -= 1;
2291 return reply;
2292 }
2293 link = _dbus_list_get_next_link (&connection->incoming_messages, link);
2294 }
2295
2296 return NULL;
2297}
2298
2299static void
2300connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
2301{
2302 /* We can't iterate over the hash in the normal way since we'll be
2303 * dropping the lock for each item. So we restart the
2304 * iter each time as we drain the hash table.
2305 */
2306
2307 while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
2308 {
2309 DBusPendingCall *pending;
2310 DBusHashIter iter;
2311
2312 _dbus_hash_iter_init (connection->pending_replies, &iter);
2313 _dbus_hash_iter_next (&iter);
2314
2315 pending = _dbus_hash_iter_get_value (&iter);
2317
2319 connection);
2320
2326
2328 CONNECTION_LOCK (connection);
2329 }
2330 HAVE_LOCK_CHECK (connection);
2331}
2332
2333static void
2334complete_pending_call_and_unlock (DBusConnection *connection,
2335 DBusPendingCall *pending,
2336 DBusMessage *message)
2337{
2338 _dbus_pending_call_set_reply_unlocked (pending, message);
2339 _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */
2341 _dbus_connection_detach_pending_call_and_unlock (connection, pending);
2342
2343 /* Must be called unlocked since it invokes app callback */
2345 dbus_pending_call_unref (pending);
2346}
2347
2348static dbus_bool_t
2349check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection,
2350 DBusPendingCall *pending)
2351{
2352 DBusMessage *reply;
2353 DBusDispatchStatus status;
2354
2355 reply = check_for_reply_unlocked (connection,
2357 if (reply != NULL)
2358 {
2359 _dbus_verbose ("checked for reply\n");
2360
2361 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
2362
2363 complete_pending_call_and_unlock (connection, pending, reply);
2364 dbus_message_unref (reply);
2365
2366 CONNECTION_LOCK (connection);
2367 status = _dbus_connection_get_dispatch_status_unlocked (connection);
2368 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2369 dbus_pending_call_unref (pending);
2370
2371 return TRUE;
2372 }
2373
2374 return FALSE;
2375}
2376
2391void
2393{
2394 long start_tv_sec, start_tv_usec;
2395 long tv_sec, tv_usec;
2396 DBusDispatchStatus status;
2397 DBusConnection *connection;
2398 dbus_uint32_t client_serial;
2399 DBusTimeout *timeout;
2400 int timeout_milliseconds, elapsed_milliseconds;
2401
2402 _dbus_assert (pending != NULL);
2403
2404 if (dbus_pending_call_get_completed (pending))
2405 return;
2406
2407 dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
2408
2409 connection = _dbus_pending_call_get_connection_and_lock (pending);
2410
2411 /* Flush message queue - note, can affect dispatch status */
2412 _dbus_connection_flush_unlocked (connection);
2413
2414 client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
2415
2416 /* note that timeout_milliseconds is limited to a smallish value
2417 * in _dbus_pending_call_new() so overflows aren't possible
2418 * below
2419 */
2420 timeout = _dbus_pending_call_get_timeout_unlocked (pending);
2421 _dbus_get_monotonic_time (&start_tv_sec, &start_tv_usec);
2422 if (timeout)
2423 {
2424 timeout_milliseconds = dbus_timeout_get_interval (timeout);
2425
2426 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n",
2427 timeout_milliseconds,
2428 client_serial,
2429 start_tv_sec, start_tv_usec);
2430 }
2431 else
2432 {
2433 timeout_milliseconds = -1;
2434
2435 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial);
2436 }
2437
2438 /* check to see if we already got the data off the socket */
2439 /* from another blocked pending call */
2440 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
2441 return;
2442
2443 /* Now we wait... */
2444 /* always block at least once as we know we don't have the reply yet */
2446 pending,
2447 DBUS_ITERATION_DO_READING |
2448 DBUS_ITERATION_BLOCK,
2449 timeout_milliseconds);
2450
2451 recheck_status:
2452
2453 _dbus_verbose ("top of recheck\n");
2454
2455 HAVE_LOCK_CHECK (connection);
2456
2457 /* queue messages and get status */
2458
2459 status = _dbus_connection_get_dispatch_status_unlocked (connection);
2460
2461 /* the get_completed() is in case a dispatch() while we were blocking
2462 * got the reply instead of us.
2463 */
2465 {
2466 _dbus_verbose ("Pending call completed by dispatch\n");
2467 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2468 dbus_pending_call_unref (pending);
2469 return;
2470 }
2471
2472 if (status == DBUS_DISPATCH_DATA_REMAINS)
2473 {
2474 if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
2475 return;
2476 }
2477
2478 _dbus_get_monotonic_time (&tv_sec, &tv_usec);
2479 elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
2480 (tv_usec - start_tv_usec) / 1000;
2481
2482 if (!_dbus_connection_get_is_connected_unlocked (connection))
2483 {
2484 DBusMessage *error_msg;
2485
2486 error_msg = generate_local_error_message (client_serial,
2488 "Connection was disconnected before a reply was received");
2489
2490 /* on OOM error_msg is set to NULL */
2491 complete_pending_call_and_unlock (connection, pending, error_msg);
2492 if (error_msg != NULL)
2493 dbus_message_unref (error_msg);
2494 dbus_pending_call_unref (pending);
2495 return;
2496 }
2497 else if (connection->disconnect_message_link == NULL)
2498 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
2499 else if (timeout == NULL)
2500 {
2501 if (status == DBUS_DISPATCH_NEED_MEMORY)
2502 {
2503 /* Try sleeping a bit, as we aren't sure we need to block for reading,
2504 * we may already have a reply in the buffer and just can't process
2505 * it.
2506 */
2507 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
2508
2509 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
2510 }
2511 else
2512 {
2513 /* block again, we don't have the reply buffered yet. */
2515 pending,
2516 DBUS_ITERATION_DO_READING |
2517 DBUS_ITERATION_BLOCK,
2518 timeout_milliseconds - elapsed_milliseconds);
2519 }
2520
2521 goto recheck_status;
2522 }
2523 else if (tv_sec < start_tv_sec)
2524 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
2525 else if (elapsed_milliseconds < timeout_milliseconds)
2526 {
2527 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds);
2528
2529 if (status == DBUS_DISPATCH_NEED_MEMORY)
2530 {
2531 /* Try sleeping a bit, as we aren't sure we need to block for reading,
2532 * we may already have a reply in the buffer and just can't process
2533 * it.
2534 */
2535 _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
2536
2537 _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
2538 }
2539 else
2540 {
2541 /* block again, we don't have the reply buffered yet. */
2543 pending,
2544 DBUS_ITERATION_DO_READING |
2545 DBUS_ITERATION_BLOCK,
2546 timeout_milliseconds - elapsed_milliseconds);
2547 }
2548
2549 goto recheck_status;
2550 }
2551
2552 _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n",
2553 elapsed_milliseconds);
2554
2556
2557 /* unlock and call user code */
2558 complete_pending_call_and_unlock (connection, pending, NULL);
2559
2560 /* update user code on dispatch status */
2561 CONNECTION_LOCK (connection);
2562 status = _dbus_connection_get_dispatch_status_unlocked (connection);
2563 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2564 dbus_pending_call_unref (pending);
2565}
2566
2572int
2574{
2576}
2577
2585void
2587 DBusPendingFdsChangeFunction callback,
2588 void *data)
2589{
2591 callback, data);
2592}
2593
2631dbus_connection_open (const char *address,
2632 DBusError *error)
2633{
2634 DBusConnection *connection;
2635
2636 _dbus_return_val_if_fail (address != NULL, NULL);
2637 _dbus_return_val_if_error_is_set (error, NULL);
2638
2639 connection = _dbus_connection_open_internal (address,
2640 TRUE,
2641 error);
2642
2643 return connection;
2644}
2645
2674dbus_connection_open_private (const char *address,
2675 DBusError *error)
2676{
2677 DBusConnection *connection;
2678
2679 _dbus_return_val_if_fail (address != NULL, NULL);
2680 _dbus_return_val_if_error_is_set (error, NULL);
2681
2682 connection = _dbus_connection_open_internal (address,
2683 FALSE,
2684 error);
2685
2686 return connection;
2687}
2688
2697{
2698 dbus_int32_t old_refcount;
2699
2700 _dbus_return_val_if_fail (connection != NULL, NULL);
2701 _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
2702 old_refcount = _dbus_atomic_inc (&connection->refcount);
2703 _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1,
2704 "ref");
2705
2706 return connection;
2707}
2708
2709static void
2710free_outgoing_message (void *element,
2711 void *data)
2712{
2713 DBusMessage *message = element;
2714 DBusConnection *connection = data;
2715
2716 _dbus_message_remove_counter (message, connection->outgoing_counter);
2717 dbus_message_unref (message);
2718}
2719
2720/* This is run without the mutex held, but after the last reference
2721 * to the connection has been dropped we should have no thread-related
2722 * problems
2723 */
2724static void
2725_dbus_connection_last_unref (DBusConnection *connection)
2726{
2727 DBusList *link;
2728
2729 _dbus_verbose ("Finalizing connection %p\n", connection);
2730
2731 _dbus_assert (_dbus_atomic_get (&connection->refcount) == 0);
2732
2733 /* You have to disconnect the connection before unref:ing it. Otherwise
2734 * you won't get the disconnected message.
2735 */
2737 _dbus_assert (connection->server_guid == NULL);
2738
2739 /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
2741
2746
2747 _dbus_watch_list_free (connection->watches);
2748 connection->watches = NULL;
2749
2750 _dbus_timeout_list_free (connection->timeouts);
2751 connection->timeouts = NULL;
2752
2753 _dbus_data_slot_list_free (&connection->slot_list);
2754
2755 link = _dbus_list_get_first_link (&connection->filter_list);
2756 while (link != NULL)
2757 {
2758 DBusMessageFilter *filter = link->data;
2759 DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
2760
2761 filter->function = NULL;
2762 _dbus_message_filter_unref (filter); /* calls app callback */
2763 link->data = NULL;
2764
2765 link = next;
2766 }
2767 _dbus_list_clear (&connection->filter_list);
2768
2769 /* ---- Done with stuff that invokes application callbacks */
2770
2771 _dbus_object_tree_unref (connection->objects);
2772
2774 connection->pending_replies = NULL;
2775
2777 free_outgoing_message,
2778 connection);
2779 _dbus_list_clear (&connection->outgoing_messages);
2780
2783
2785
2786 _dbus_transport_unref (connection->transport);
2787
2788 if (connection->disconnect_message_link)
2789 {
2790 DBusMessage *message = connection->disconnect_message_link->data;
2791 dbus_message_unref (message);
2793 }
2794
2797
2800
2802
2803 _dbus_rmutex_free_at_location (&connection->mutex);
2804
2805 dbus_free (connection);
2806}
2807
2827void
2829{
2830 dbus_int32_t old_refcount;
2831
2832 _dbus_return_if_fail (connection != NULL);
2833 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
2834
2835 old_refcount = _dbus_atomic_dec (&connection->refcount);
2836
2837 _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1,
2838 "unref");
2839
2840 if (old_refcount == 1)
2841 {
2842#ifndef DBUS_DISABLE_CHECKS
2844 {
2845 _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",
2846 connection->shareable ?
2847 "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection." :
2848 "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.");
2849 return;
2850 }
2851#endif
2852 _dbus_connection_last_unref (connection);
2853 }
2854}
2855
2856/*
2857 * Note that the transport can disconnect itself (other end drops us)
2858 * and in that case this function never runs. So this function must
2859 * not do anything more than disconnect the transport and update the
2860 * dispatch status.
2861 *
2862 * If the transport self-disconnects, then we assume someone will
2863 * dispatch the connection to cause the dispatch status update.
2864 */
2865static void
2866_dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
2867{
2868 DBusDispatchStatus status;
2869
2870 HAVE_LOCK_CHECK (connection);
2871
2872 _dbus_verbose ("Disconnecting %p\n", connection);
2873
2874 /* We need to ref because update_dispatch_status_and_unlock will unref
2875 * the connection if it was shared and libdbus was the only remaining
2876 * refcount holder.
2877 */
2878 _dbus_connection_ref_unlocked (connection);
2879
2881
2882 /* This has the side effect of queuing the disconnect message link
2883 * (unless we don't have enough memory, possibly, so don't assert it).
2884 * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open
2885 * should never again return the newly-disconnected connection.
2886 *
2887 * However, we only unref the shared connection and exit_on_disconnect when
2888 * the disconnect message reaches the head of the message queue,
2889 * NOT when it's first queued.
2890 */
2891 status = _dbus_connection_get_dispatch_status_unlocked (connection);
2892
2893 /* This calls out to user code */
2894 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2895
2896 /* Could also call out to user code */
2897 dbus_connection_unref (connection);
2898}
2899
2942void
2944{
2945 _dbus_return_if_fail (connection != NULL);
2946 _dbus_return_if_fail (connection->generation == _dbus_current_generation);
2947
2948 CONNECTION_LOCK (connection);
2949
2950#ifndef DBUS_DISABLE_CHECKS
2951 if (connection->shareable)
2952 {
2953 CONNECTION_UNLOCK (connection);
2954
2955 _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.");
2956 return;
2957 }
2958#endif
2959
2960 _dbus_connection_close_possibly_shared_and_unlock (connection);
2961}
2962
2963static dbus_bool_t
2964_dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
2965{
2966 HAVE_LOCK_CHECK (connection);
2967 return _dbus_transport_get_is_connected (connection->transport);
2968}
2969
2985{
2986 dbus_bool_t res;
2987
2988 _dbus_return_val_if_fail (connection != NULL, FALSE);
2989
2990 CONNECTION_LOCK (connection);
2991 res = _dbus_connection_get_is_connected_unlocked (connection);
2992 CONNECTION_UNLOCK (connection);
2993
2994 return res;
2995}
2996
3007{
3008 dbus_bool_t res;
3009
3010 _dbus_return_val_if_fail (connection != NULL, FALSE);
3011
3012 CONNECTION_LOCK (connection);
3014 CONNECTION_UNLOCK (connection);
3015
3016 return res;
3017}
3018
3041{
3042 dbus_bool_t res;
3043
3044 _dbus_return_val_if_fail (connection != NULL, FALSE);
3045
3046 CONNECTION_LOCK (connection);
3047 res = _dbus_transport_get_is_anonymous (connection->transport);
3048 CONNECTION_UNLOCK (connection);
3049
3050 return res;
3051}
3052
3084char*
3086{
3087 char *id;
3088
3089 _dbus_return_val_if_fail (connection != NULL, NULL);
3090
3091 CONNECTION_LOCK (connection);
3093 CONNECTION_UNLOCK (connection);
3094
3095 return id;
3096}
3097
3117 int type)
3118{
3119 _dbus_return_val_if_fail (connection != NULL, FALSE);
3120
3121 if (!dbus_type_is_valid (type))
3122 return FALSE;
3123
3124 if (type != DBUS_TYPE_UNIX_FD)
3125 return TRUE;
3126
3127#ifdef HAVE_UNIX_FD_PASSING
3128 {
3129 dbus_bool_t b;
3130
3131 CONNECTION_LOCK(connection);
3133 CONNECTION_UNLOCK(connection);
3134
3135 return b;
3136 }
3137#endif
3138
3139 return FALSE;
3140}
3141
3155void
3157 dbus_bool_t exit_on_disconnect)
3158{
3159 _dbus_return_if_fail (connection != NULL);
3160
3161 CONNECTION_LOCK (connection);
3162 connection->exit_on_disconnect = exit_on_disconnect != FALSE;
3163 CONNECTION_UNLOCK (connection);
3164}
3165
3177{
3178 DBusPreallocatedSend *preallocated;
3179
3180 _dbus_return_val_if_fail (connection != NULL, NULL);
3181
3182 CONNECTION_LOCK (connection);
3183
3184 preallocated =
3185 _dbus_connection_preallocate_send_unlocked (connection);
3186
3187 CONNECTION_UNLOCK (connection);
3188
3189 return preallocated;
3190}
3191
3201void
3203 DBusPreallocatedSend *preallocated)
3204{
3205 _dbus_return_if_fail (connection != NULL);
3206 _dbus_return_if_fail (preallocated != NULL);
3207 _dbus_return_if_fail (connection == preallocated->connection);
3208
3209 _dbus_list_free_link (preallocated->queue_link);
3210 _dbus_counter_unref (preallocated->counter_link->data);
3211 _dbus_list_free_link (preallocated->counter_link);
3212 dbus_free (preallocated);
3213}
3214
3227void
3229 DBusPreallocatedSend *preallocated,
3230 DBusMessage *message,
3231 dbus_uint32_t *client_serial)
3232{
3233 _dbus_return_if_fail (connection != NULL);
3234 _dbus_return_if_fail (preallocated != NULL);
3235 _dbus_return_if_fail (message != NULL);
3236 _dbus_return_if_fail (preallocated->connection == connection);
3237 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
3238 dbus_message_get_member (message) != NULL);
3239 _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
3240 (dbus_message_get_interface (message) != NULL &&
3241 dbus_message_get_member (message) != NULL));
3242
3243 CONNECTION_LOCK (connection);
3244
3245#ifdef HAVE_UNIX_FD_PASSING
3246
3247 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
3248 message->n_unix_fds > 0)
3249 {
3250 /* Refuse to send fds on a connection that cannot handle
3251 them. Unfortunately we cannot return a proper error here, so
3252 the best we can is just return. */
3253 CONNECTION_UNLOCK (connection);
3254 return;
3255 }
3256
3257#endif
3258
3259 _dbus_connection_send_preallocated_and_unlock (connection,
3260 preallocated,
3261 message, client_serial);
3262}
3263
3264static dbus_bool_t
3265_dbus_connection_send_unlocked_no_update (DBusConnection *connection,
3266 DBusMessage *message,
3267 dbus_uint32_t *client_serial)
3268{
3269 DBusPreallocatedSend *preallocated;
3270
3271 _dbus_assert (connection != NULL);
3272 _dbus_assert (message != NULL);
3273
3274 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
3275 if (preallocated == NULL)
3276 return FALSE;
3277
3278 _dbus_connection_send_preallocated_unlocked_no_update (connection,
3279 preallocated,
3280 message,
3281 client_serial);
3282 return TRUE;
3283}
3284
3314 DBusMessage *message,
3315 dbus_uint32_t *serial)
3316{
3317 _dbus_return_val_if_fail (connection != NULL, FALSE);
3318 _dbus_return_val_if_fail (message != NULL, FALSE);
3319
3320 CONNECTION_LOCK (connection);
3321
3322#ifdef HAVE_UNIX_FD_PASSING
3323
3324 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
3325 message->n_unix_fds > 0)
3326 {
3327 /* Refuse to send fds on a connection that cannot handle
3328 them. Unfortunately we cannot return a proper error here, so
3329 the best we can is just return. */
3330 CONNECTION_UNLOCK (connection);
3331 return FALSE;
3332 }
3333
3334#endif
3335
3336 return _dbus_connection_send_and_unlock (connection,
3337 message,
3338 serial);
3339}
3340
3341static dbus_bool_t
3342reply_handler_timeout (void *data)
3343{
3344 DBusConnection *connection;
3345 DBusDispatchStatus status;
3346 DBusPendingCall *pending = data;
3347
3348 connection = _dbus_pending_call_get_connection_and_lock (pending);
3349 _dbus_connection_ref_unlocked (connection);
3350
3352 connection);
3356
3357 _dbus_verbose ("middle\n");
3358 status = _dbus_connection_get_dispatch_status_unlocked (connection);
3359
3360 /* Unlocks, and calls out to user code */
3361 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3362 dbus_connection_unref (connection);
3363
3364 return TRUE;
3365}
3366
3411 DBusMessage *message,
3412 DBusPendingCall **pending_return,
3413 int timeout_milliseconds)
3414{
3415 DBusPendingCall *pending;
3416 dbus_int32_t serial = -1;
3417 DBusDispatchStatus status;
3418
3419 _dbus_return_val_if_fail (connection != NULL, FALSE);
3420 _dbus_return_val_if_fail (message != NULL, FALSE);
3421 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
3422
3423 if (pending_return)
3424 *pending_return = NULL;
3425
3426 CONNECTION_LOCK (connection);
3427
3428#ifdef HAVE_UNIX_FD_PASSING
3429
3430 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
3431 message->n_unix_fds > 0)
3432 {
3433 /* Refuse to send fds on a connection that cannot handle
3434 them. Unfortunately we cannot return a proper error here, so
3435 the best we can do is return TRUE but leave *pending_return
3436 as NULL. */
3437 CONNECTION_UNLOCK (connection);
3438 return TRUE;
3439 }
3440
3441#endif
3442
3443 if (!_dbus_connection_get_is_connected_unlocked (connection))
3444 {
3445 CONNECTION_UNLOCK (connection);
3446
3447 return TRUE;
3448 }
3449
3450 pending = _dbus_pending_call_new_unlocked (connection,
3451 timeout_milliseconds,
3452 reply_handler_timeout);
3453
3454 if (pending == NULL)
3455 {
3456 CONNECTION_UNLOCK (connection);
3457 return FALSE;
3458 }
3459
3460 /* Assign a serial to the message */
3461 serial = dbus_message_get_serial (message);
3462 if (serial == 0)
3463 {
3464 serial = _dbus_connection_get_next_client_serial (connection);
3465 dbus_message_set_serial (message, serial);
3466 }
3467
3468 if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
3469 goto error;
3470
3471 /* Insert the serial in the pending replies hash;
3472 * hash takes a refcount on DBusPendingCall.
3473 * Also, add the timeout.
3474 */
3475 if (!_dbus_connection_attach_pending_call_unlocked (connection,
3476 pending))
3477 goto error;
3478
3479 if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
3480 {
3481 _dbus_connection_detach_pending_call_and_unlock (connection,
3482 pending);
3483 goto error_unlocked;
3484 }
3485
3486 if (pending_return)
3487 *pending_return = pending; /* hand off refcount */
3488 else
3489 {
3490 _dbus_connection_detach_pending_call_unlocked (connection, pending);
3491 /* we still have a ref to the pending call in this case, we unref
3492 * after unlocking, below
3493 */
3494 }
3495
3496 status = _dbus_connection_get_dispatch_status_unlocked (connection);
3497
3498 /* this calls out to user code */
3499 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3500
3501 if (pending_return == NULL)
3502 dbus_pending_call_unref (pending);
3503
3504 return TRUE;
3505
3506 error:
3507 CONNECTION_UNLOCK (connection);
3508 error_unlocked:
3509 dbus_pending_call_unref (pending);
3510 return FALSE;
3511}
3512
3547 DBusMessage *message,
3548 int timeout_milliseconds,
3549 DBusError *error)
3550{
3551 DBusMessage *reply;
3552 DBusPendingCall *pending;
3553
3554 _dbus_return_val_if_fail (connection != NULL, NULL);
3555 _dbus_return_val_if_fail (message != NULL, NULL);
3556 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
3557 _dbus_return_val_if_error_is_set (error, NULL);
3558
3559#ifdef HAVE_UNIX_FD_PASSING
3560
3561 CONNECTION_LOCK (connection);
3562 if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
3563 message->n_unix_fds > 0)
3564 {
3565 CONNECTION_UNLOCK (connection);
3566 dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection.");
3567 return NULL;
3568 }
3569 CONNECTION_UNLOCK (connection);
3570
3571#endif
3572
3573 if (!dbus_connection_send_with_reply (connection, message,
3574 &pending, timeout_milliseconds))
3575 {
3576 _DBUS_SET_OOM (error);
3577 return NULL;
3578 }
3579
3580 if (pending == NULL)
3581 {
3582 dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
3583 return NULL;
3584 }
3585
3586 dbus_pending_call_block (pending);
3587
3588 reply = dbus_pending_call_steal_reply (pending);
3589 dbus_pending_call_unref (pending);
3590
3591 /* call_complete_and_unlock() called from pending_call_block() should
3592 * always fill this in.
3593 */
3594 _dbus_assert (reply != NULL);
3595
3596 if (dbus_set_error_from_message (error, reply))
3597 {
3598 dbus_message_unref (reply);
3599 return NULL;
3600 }
3601 else
3602 return reply;
3603}
3604
3613static DBusDispatchStatus
3614_dbus_connection_flush_unlocked (DBusConnection *connection)
3615{
3616 /* We have to specify DBUS_ITERATION_DO_READING here because
3617 * otherwise we could have two apps deadlock if they are both doing
3618 * a flush(), and the kernel buffers fill up. This could change the
3619 * dispatch status.
3620 */
3621 DBusDispatchStatus status;
3622
3623 HAVE_LOCK_CHECK (connection);
3624
3625 while (connection->n_outgoing > 0 &&
3626 _dbus_connection_get_is_connected_unlocked (connection))
3627 {
3628 _dbus_verbose ("doing iteration in\n");
3629 HAVE_LOCK_CHECK (connection);
3631 NULL,
3632 DBUS_ITERATION_DO_READING |
3633 DBUS_ITERATION_DO_WRITING |
3634 DBUS_ITERATION_BLOCK,
3635 -1);
3636 }
3637
3638 HAVE_LOCK_CHECK (connection);
3639 _dbus_verbose ("middle\n");
3640 status = _dbus_connection_get_dispatch_status_unlocked (connection);
3641
3642 HAVE_LOCK_CHECK (connection);
3643 return status;
3644}
3645
3651void
3653{
3654 /* We have to specify DBUS_ITERATION_DO_READING here because
3655 * otherwise we could have two apps deadlock if they are both doing
3656 * a flush(), and the kernel buffers fill up. This could change the
3657 * dispatch status.
3658 */
3659 DBusDispatchStatus status;
3660
3661 _dbus_return_if_fail (connection != NULL);
3662
3663 CONNECTION_LOCK (connection);
3664
3665 status = _dbus_connection_flush_unlocked (connection);
3666
3667 HAVE_LOCK_CHECK (connection);
3668 /* Unlocks and calls out to user code */
3669 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3670
3671 _dbus_verbose ("end\n");
3672}
3673
3684static dbus_bool_t
3685_dbus_connection_read_write_dispatch (DBusConnection *connection,
3686 int timeout_milliseconds,
3687 dbus_bool_t dispatch)
3688{
3689 DBusDispatchStatus dstatus;
3690 dbus_bool_t progress_possible;
3691
3692 /* Need to grab a ref here in case we're a private connection and
3693 * the user drops the last ref in a handler we call; see bug
3694 * https://bugs.freedesktop.org/show_bug.cgi?id=15635
3695 */
3696 dbus_connection_ref (connection);
3697 dstatus = dbus_connection_get_dispatch_status (connection);
3698
3699 if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
3700 {
3701 _dbus_verbose ("doing dispatch\n");
3702 dbus_connection_dispatch (connection);
3703 CONNECTION_LOCK (connection);
3704 }
3705 else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
3706 {
3707 _dbus_verbose ("pausing for memory\n");
3708 _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
3709 CONNECTION_LOCK (connection);
3710 }
3711 else
3712 {
3713 CONNECTION_LOCK (connection);
3714 if (_dbus_connection_get_is_connected_unlocked (connection))
3715 {
3716 _dbus_verbose ("doing iteration\n");
3718 NULL,
3719 DBUS_ITERATION_DO_READING |
3720 DBUS_ITERATION_DO_WRITING |
3721 DBUS_ITERATION_BLOCK,
3722 timeout_milliseconds);
3723 }
3724 }
3725
3726 HAVE_LOCK_CHECK (connection);
3727 /* If we can dispatch, we can make progress until the Disconnected message
3728 * has been processed; if we can only read/write, we can make progress
3729 * as long as the transport is open.
3730 */
3731 if (dispatch)
3732 progress_possible = connection->n_incoming != 0 ||
3733 connection->disconnect_message_link != NULL;
3734 else
3735 progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
3736
3737 CONNECTION_UNLOCK (connection);
3738
3739 dbus_connection_unref (connection);
3740
3741 return progress_possible; /* TRUE if we can make more progress */
3742}
3743
3744
3781 int timeout_milliseconds)
3782{
3783 _dbus_return_val_if_fail (connection != NULL, FALSE);
3784 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
3785 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
3786}
3787
3813 int timeout_milliseconds)
3814{
3815 _dbus_return_val_if_fail (connection != NULL, FALSE);
3816 _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
3817 return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
3818}
3819
3820/* We need to call this anytime we pop the head of the queue, and then
3821 * update_dispatch_status_and_unlock needs to be called afterward
3822 * which will "process" the disconnected message and set
3823 * disconnected_message_processed.
3824 */
3825static void
3826check_disconnected_message_arrived_unlocked (DBusConnection *connection,
3827 DBusMessage *head_of_queue)
3828{
3829 HAVE_LOCK_CHECK (connection);
3830
3831 /* checking that the link is NULL is an optimization to avoid the is_signal call */
3832 if (connection->disconnect_message_link == NULL &&
3833 dbus_message_is_signal (head_of_queue,
3835 "Disconnected"))
3836 {
3837 connection->disconnected_message_arrived = TRUE;
3838 }
3839}
3840
3862{
3863 DBusDispatchStatus status;
3864 DBusMessage *message;
3865
3866 _dbus_return_val_if_fail (connection != NULL, NULL);
3867
3868 _dbus_verbose ("start\n");
3869
3870 /* this is called for the side effect that it queues
3871 * up any messages from the transport
3872 */
3873 status = dbus_connection_get_dispatch_status (connection);
3874 if (status != DBUS_DISPATCH_DATA_REMAINS)
3875 return NULL;
3876
3877 CONNECTION_LOCK (connection);
3878
3879 _dbus_connection_acquire_dispatch (connection);
3880
3881 /* While a message is outstanding, the dispatch lock is held */
3882 _dbus_assert (connection->message_borrowed == NULL);
3883
3884 connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
3885
3886 message = connection->message_borrowed;
3887
3888 check_disconnected_message_arrived_unlocked (connection, message);
3889
3890 /* Note that we KEEP the dispatch lock until the message is returned */
3891 if (message == NULL)
3892 _dbus_connection_release_dispatch (connection);
3893
3894 CONNECTION_UNLOCK (connection);
3895
3896 _dbus_message_trace_ref (message, -1, -1, "dbus_connection_borrow_message");
3897
3898 /* We don't update dispatch status until it's returned or stolen */
3899
3900 return message;
3901}
3902
3911void
3913 DBusMessage *message)
3914{
3915 DBusDispatchStatus status;
3916
3917 _dbus_return_if_fail (connection != NULL);
3918 _dbus_return_if_fail (message != NULL);
3919 _dbus_return_if_fail (message == connection->message_borrowed);
3920 _dbus_return_if_fail (connection->dispatch_acquired);
3921
3922 CONNECTION_LOCK (connection);
3923
3924 _dbus_assert (message == connection->message_borrowed);
3925
3926 connection->message_borrowed = NULL;
3927
3928 _dbus_connection_release_dispatch (connection);
3929
3930 status = _dbus_connection_get_dispatch_status_unlocked (connection);
3931 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3932
3933 _dbus_message_trace_ref (message, -1, -1, "dbus_connection_return_message");
3934}
3935
3945void
3947 DBusMessage *message)
3948{
3949 DBusMessage *pop_message;
3950 DBusDispatchStatus status;
3951
3952 _dbus_return_if_fail (connection != NULL);
3953 _dbus_return_if_fail (message != NULL);
3954 _dbus_return_if_fail (message == connection->message_borrowed);
3955 _dbus_return_if_fail (connection->dispatch_acquired);
3956
3957 CONNECTION_LOCK (connection);
3958
3959 _dbus_assert (message == connection->message_borrowed);
3960
3961 pop_message = _dbus_list_pop_first (&connection->incoming_messages);
3962 _dbus_assert (message == pop_message);
3963 (void) pop_message; /* unused unless asserting */
3964
3965 connection->n_incoming -= 1;
3966
3967 _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
3968 message, connection->n_incoming);
3969
3970 connection->message_borrowed = NULL;
3971
3972 _dbus_connection_release_dispatch (connection);
3973
3974 status = _dbus_connection_get_dispatch_status_unlocked (connection);
3975 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3976 _dbus_message_trace_ref (message, -1, -1,
3977 "dbus_connection_steal_borrowed_message");
3978}
3979
3980/* See dbus_connection_pop_message, but requires the caller to own
3981 * the lock before calling. May drop the lock while running.
3982 */
3983static DBusList*
3984_dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
3985{
3986 HAVE_LOCK_CHECK (connection);
3987
3988 _dbus_assert (connection->message_borrowed == NULL);
3989
3990 if (connection->n_incoming > 0)
3991 {
3992 DBusList *link;
3993
3994 link = _dbus_list_pop_first_link (&connection->incoming_messages);
3995 connection->n_incoming -= 1;
3996
3997 _dbus_verbose ("Message %p (%s %s %s %s sig:'%s' serial:%u) removed from incoming queue %p, %d incoming\n",
3998 link->data,
4000 dbus_message_get_path (link->data) ?
4001 dbus_message_get_path (link->data) :
4002 "no path",
4005 "no interface",
4008 "no member",
4011 connection, connection->n_incoming);
4012
4013 _dbus_message_trace_ref (link->data, -1, -1,
4014 "_dbus_connection_pop_message_link_unlocked");
4015
4016 check_disconnected_message_arrived_unlocked (connection, link->data);
4017
4018 return link;
4019 }
4020 else
4021 return NULL;
4022}
4023
4024/* See dbus_connection_pop_message, but requires the caller to own
4025 * the lock before calling. May drop the lock while running.
4026 */
4027static DBusMessage*
4028_dbus_connection_pop_message_unlocked (DBusConnection *connection)
4029{
4030 DBusList *link;
4031
4032 HAVE_LOCK_CHECK (connection);
4033
4034 link = _dbus_connection_pop_message_link_unlocked (connection);
4035
4036 if (link != NULL)
4037 {
4038 DBusMessage *message;
4039
4040 message = link->data;
4041
4042 _dbus_list_free_link (link);
4043
4044 return message;
4045 }
4046 else
4047 return NULL;
4048}
4049
4050static void
4051_dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
4052 DBusList *message_link)
4053{
4054 HAVE_LOCK_CHECK (connection);
4055
4056 _dbus_assert (message_link != NULL);
4057 /* You can't borrow a message while a link is outstanding */
4058 _dbus_assert (connection->message_borrowed == NULL);
4059 /* We had to have the dispatch lock across the pop/putback */
4060 _dbus_assert (connection->dispatch_acquired);
4061
4063 message_link);
4064 connection->n_incoming += 1;
4065
4066 _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n",
4067 message_link->data,
4069 dbus_message_get_interface (message_link->data) ?
4070 dbus_message_get_interface (message_link->data) :
4071 "no interface",
4072 dbus_message_get_member (message_link->data) ?
4073 dbus_message_get_member (message_link->data) :
4074 "no member",
4075 dbus_message_get_signature (message_link->data),
4076 connection, connection->n_incoming);
4077
4078 _dbus_message_trace_ref (message_link->data, -1, -1,
4079 "_dbus_connection_putback_message_link_unlocked");
4080}
4081
4103{
4104 DBusMessage *message;
4105 DBusDispatchStatus status;
4106
4107 _dbus_verbose ("start\n");
4108
4109 /* this is called for the side effect that it queues
4110 * up any messages from the transport
4111 */
4112 status = dbus_connection_get_dispatch_status (connection);
4113 if (status != DBUS_DISPATCH_DATA_REMAINS)
4114 return NULL;
4115
4116 CONNECTION_LOCK (connection);
4117 _dbus_connection_acquire_dispatch (connection);
4118 HAVE_LOCK_CHECK (connection);
4119
4120 message = _dbus_connection_pop_message_unlocked (connection);
4121
4122 _dbus_verbose ("Returning popped message %p\n", message);
4123
4124 _dbus_connection_release_dispatch (connection);
4125
4126 status = _dbus_connection_get_dispatch_status_unlocked (connection);
4127 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
4128
4129 return message;
4130}
4131
4139static void
4140_dbus_connection_acquire_dispatch (DBusConnection *connection)
4141{
4142 HAVE_LOCK_CHECK (connection);
4143
4144 _dbus_connection_ref_unlocked (connection);
4145 CONNECTION_UNLOCK (connection);
4146
4147 _dbus_verbose ("locking dispatch_mutex\n");
4148 _dbus_cmutex_lock (connection->dispatch_mutex);
4149
4150 while (connection->dispatch_acquired)
4151 {
4152 _dbus_verbose ("waiting for dispatch to be acquirable\n");
4153 _dbus_condvar_wait (connection->dispatch_cond,
4154 connection->dispatch_mutex);
4155 }
4156
4157 _dbus_assert (!connection->dispatch_acquired);
4158
4159 connection->dispatch_acquired = TRUE;
4160
4161 _dbus_verbose ("unlocking dispatch_mutex\n");
4162 _dbus_cmutex_unlock (connection->dispatch_mutex);
4163
4164 CONNECTION_LOCK (connection);
4166}
4167
4175static void
4176_dbus_connection_release_dispatch (DBusConnection *connection)
4177{
4178 HAVE_LOCK_CHECK (connection);
4179
4180 _dbus_verbose ("locking dispatch_mutex\n");
4181 _dbus_cmutex_lock (connection->dispatch_mutex);
4182
4183 _dbus_assert (connection->dispatch_acquired);
4184
4185 connection->dispatch_acquired = FALSE;
4187
4188 _dbus_verbose ("unlocking dispatch_mutex\n");
4189 _dbus_cmutex_unlock (connection->dispatch_mutex);
4190}
4191
4192static void
4193_dbus_connection_failed_pop (DBusConnection *connection,
4194 DBusList *message_link)
4195{
4197 message_link);
4198 connection->n_incoming += 1;
4199}
4200
4201/* Note this may be called multiple times since we don't track whether we already did it */
4202static void
4203notify_disconnected_unlocked (DBusConnection *connection)
4204{
4205 HAVE_LOCK_CHECK (connection);
4206
4207 /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected
4208 * connection from dbus_bus_get(). We make the same guarantee for
4209 * dbus_connection_open() but in a different way since we don't want to
4210 * unref right here; we instead check for connectedness before returning
4211 * the connection from the hash.
4212 */
4214
4215 /* Dump the outgoing queue, we aren't going to be able to
4216 * send it now, and we'd like accessors like
4217 * dbus_connection_get_outgoing_size() to be accurate.
4218 */
4219 if (connection->n_outgoing > 0)
4220 {
4221 DBusList *link;
4222
4223 _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
4224 connection->n_outgoing);
4225
4226 while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
4227 {
4228 _dbus_connection_message_sent_unlocked (connection, link->data);
4229 }
4230 }
4231}
4232
4233/* Note this may be called multiple times since we don't track whether we already did it */
4234static DBusDispatchStatus
4235notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
4236{
4237 HAVE_LOCK_CHECK (connection);
4238
4239 if (connection->disconnect_message_link != NULL)
4240 {
4241 _dbus_verbose ("Sending disconnect message\n");
4242
4243 /* If we have pending calls, queue their timeouts - we want the Disconnected
4244 * to be the last message, after these timeouts.
4245 */
4246 connection_timeout_and_complete_all_pending_calls_unlocked (connection);
4247
4248 /* We haven't sent the disconnect message already,
4249 * and all real messages have been queued up.
4250 */
4252 connection->disconnect_message_link);
4253 connection->disconnect_message_link = NULL;
4254
4256 }
4257
4259}
4260
4261static DBusDispatchStatus
4262_dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
4263{
4264 HAVE_LOCK_CHECK (connection);
4265
4266 if (connection->n_incoming > 0)
4268 else if (!_dbus_transport_queue_messages (connection->transport))
4270 else
4271 {
4272 DBusDispatchStatus status;
4273 dbus_bool_t is_connected;
4274
4275 status = _dbus_transport_get_dispatch_status (connection->transport);
4276 is_connected = _dbus_transport_get_is_connected (connection->transport);
4277
4278 _dbus_verbose ("dispatch status = %s is_connected = %d\n",
4279 DISPATCH_STATUS_NAME (status), is_connected);
4280
4281 if (!is_connected)
4282 {
4283 /* It's possible this would be better done by having an explicit
4284 * notification from _dbus_transport_disconnect() that would
4285 * synchronously do this, instead of waiting for the next dispatch
4286 * status check. However, probably not good to change until it causes
4287 * a problem.
4288 */
4289 notify_disconnected_unlocked (connection);
4290
4291 /* I'm not sure this is needed; the idea is that we want to
4292 * queue the Disconnected only after we've read all the
4293 * messages, but if we're disconnected maybe we are guaranteed
4294 * to have read them all ?
4295 */
4296 if (status == DBUS_DISPATCH_COMPLETE)
4297 status = notify_disconnected_and_dispatch_complete_unlocked (connection);
4298 }
4299
4300 if (status != DBUS_DISPATCH_COMPLETE)
4301 return status;
4302 else if (connection->n_incoming > 0)
4304 else
4306 }
4307}
4308
4309static void
4310_dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
4311 DBusDispatchStatus new_status)
4312{
4313 dbus_bool_t changed;
4315 void *data;
4316
4317 HAVE_LOCK_CHECK (connection);
4318
4319 _dbus_connection_ref_unlocked (connection);
4320
4321 changed = new_status != connection->last_dispatch_status;
4322
4323 connection->last_dispatch_status = new_status;
4324
4325 function = connection->dispatch_status_function;
4326 data = connection->dispatch_status_data;
4327
4328 if (connection->disconnected_message_arrived &&
4329 !connection->disconnected_message_processed)
4330 {
4332
4333 /* this does an unref, but we have a ref
4334 * so we should not run the finalizer here
4335 * inside the lock.
4336 */
4337 connection_forget_shared_unlocked (connection);
4338
4339 if (connection->exit_on_disconnect)
4340 {
4341 CONNECTION_UNLOCK (connection);
4342
4343 _dbus_verbose ("Exiting on Disconnected signal\n");
4344 _dbus_exit (1);
4345 _dbus_assert_not_reached ("Call to exit() returned");
4346 }
4347 }
4348
4349 /* We drop the lock */
4350 CONNECTION_UNLOCK (connection);
4351
4352 if (changed && function)
4353 {
4354 _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
4355 connection, new_status,
4356 DISPATCH_STATUS_NAME (new_status));
4357 (* function) (connection, new_status, data);
4358 }
4359
4360 dbus_connection_unref (connection);
4361}
4362
4390{
4391 DBusDispatchStatus status;
4392
4393 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
4394
4395 _dbus_verbose ("start\n");
4396
4397 CONNECTION_LOCK (connection);
4398
4399 status = _dbus_connection_get_dispatch_status_unlocked (connection);
4400
4401 CONNECTION_UNLOCK (connection);
4402
4403 return status;
4404}
4405
4409static DBusHandlerResult
4410_dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
4411 DBusMessage *message)
4412{
4413 dbus_bool_t sent = FALSE;
4414 DBusMessage *ret = NULL;
4415 DBusList *expire_link;
4416
4417 if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
4418 {
4419 /* This means we're letting the bus route this message */
4421 }
4422
4424 {
4426 }
4427
4428 /* Preallocate a linked-list link, so that if we need to dispose of a
4429 * message, we can attach it to the expired list */
4430 expire_link = _dbus_list_alloc_link (NULL);
4431
4432 if (!expire_link)
4434
4435 if (dbus_message_is_method_call (message,
4437 "Ping"))
4438 {
4439 ret = dbus_message_new_method_return (message);
4440 if (ret == NULL)
4441 goto out;
4442
4443 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
4444 }
4445 else if (dbus_message_is_method_call (message,
4447 "GetMachineId"))
4448 {
4449 DBusString uuid;
4450 DBusError error = DBUS_ERROR_INIT;
4451
4452 if (!_dbus_string_init (&uuid))
4453 goto out;
4454
4455 if (_dbus_get_local_machine_uuid_encoded (&uuid, &error))
4456 {
4457 const char *v_STRING;
4458
4459 ret = dbus_message_new_method_return (message);
4460
4461 if (ret == NULL)
4462 {
4463 _dbus_string_free (&uuid);
4464 goto out;
4465 }
4466
4467 v_STRING = _dbus_string_get_const_data (&uuid);
4468 if (dbus_message_append_args (ret,
4469 DBUS_TYPE_STRING, &v_STRING,
4471 {
4472 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
4473 }
4474 }
4475 else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
4476 {
4477 dbus_error_free (&error);
4478 goto out;
4479 }
4480 else
4481 {
4482 ret = dbus_message_new_error (message, error.name, error.message);
4483 dbus_error_free (&error);
4484
4485 if (ret == NULL)
4486 goto out;
4487
4488 sent = _dbus_connection_send_unlocked_no_update (connection, ret,
4489 NULL);
4490 }
4491
4492 _dbus_string_free (&uuid);
4493 }
4494 else
4495 {
4496 /* We need to bounce anything else with this interface, otherwise apps
4497 * could start extending the interface and when we added extensions
4498 * here to DBusConnection we'd break those apps.
4499 */
4500 ret = dbus_message_new_error (message,
4502 "Unknown method invoked on org.freedesktop.DBus.Peer interface");
4503 if (ret == NULL)
4504 goto out;
4505
4506 sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
4507 }
4508
4509out:
4510 if (ret == NULL)
4511 {
4512 _dbus_list_free_link (expire_link);
4513 }
4514 else
4515 {
4516 /* It'll be safe to unref the reply when we unlock */
4517 expire_link->data = ret;
4518 _dbus_list_prepend_link (&connection->expired_messages, expire_link);
4519 }
4520
4521 if (!sent)
4523
4525}
4526
4533static DBusHandlerResult
4534_dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
4535 DBusMessage *message)
4536{
4537 /* We just run one filter for now but have the option to run more
4538 if the spec calls for it in the future */
4539
4540 return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
4541}
4542
4587{
4588 DBusMessage *message;
4589 DBusList *link, *filter_list_copy, *message_link;
4590 DBusHandlerResult result;
4591 DBusPendingCall *pending;
4592 dbus_int32_t reply_serial;
4593 DBusDispatchStatus status;
4594 dbus_bool_t found_object;
4595
4596 _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
4597
4598 _dbus_verbose ("\n");
4599
4600 CONNECTION_LOCK (connection);
4601 status = _dbus_connection_get_dispatch_status_unlocked (connection);
4602 if (status != DBUS_DISPATCH_DATA_REMAINS)
4603 {
4604 /* unlocks and calls out to user code */
4605 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
4606 return status;
4607 }
4608
4609 /* We need to ref the connection since the callback could potentially
4610 * drop the last ref to it
4611 */
4612 _dbus_connection_ref_unlocked (connection);
4613
4614 _dbus_connection_acquire_dispatch (connection);
4615 HAVE_LOCK_CHECK (connection);
4616
4617 message_link = _dbus_connection_pop_message_link_unlocked (connection);
4618 if (message_link == NULL)
4619 {
4620 /* another thread dispatched our stuff */
4621
4622 _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
4623
4624 _dbus_connection_release_dispatch (connection);
4625
4626 status = _dbus_connection_get_dispatch_status_unlocked (connection);
4627
4628 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
4629
4630 dbus_connection_unref (connection);
4631
4632 return status;
4633 }
4634
4635 message = message_link->data;
4636
4637 _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n",
4638 message,
4640 dbus_message_get_interface (message) ?
4641 dbus_message_get_interface (message) :
4642 "no interface",
4643 dbus_message_get_member (message) ?
4644 dbus_message_get_member (message) :
4645 "no member",
4646 dbus_message_get_signature (message));
4647
4649
4650 /* Pending call handling must be first, because if you do
4651 * dbus_connection_send_with_reply_and_block() or
4652 * dbus_pending_call_block() then no handlers/filters will be run on
4653 * the reply. We want consistent semantics in the case where we
4654 * dbus_connection_dispatch() the reply.
4655 */
4656
4657 reply_serial = dbus_message_get_reply_serial (message);
4658 pending = _dbus_hash_table_lookup_int (connection->pending_replies,
4659 reply_serial);
4660 if (pending)
4661 {
4662 _dbus_verbose ("Dispatching a pending reply\n");
4663 complete_pending_call_and_unlock (connection, pending, message);
4664 pending = NULL; /* it's probably unref'd */
4665
4666 CONNECTION_LOCK (connection);
4667 _dbus_verbose ("pending call completed in dispatch\n");
4669 goto out;
4670 }
4671
4672 /* If skipping builtin filters, we are probably a monitor. */
4673 if (connection->builtin_filters_enabled)
4674 {
4675 result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
4677 goto out;
4678 }
4679
4680 if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
4681 {
4682 _dbus_connection_release_dispatch (connection);
4683 HAVE_LOCK_CHECK (connection);
4684
4685 _dbus_connection_failed_pop (connection, message_link);
4686
4687 /* unlocks and calls user code */
4688 _dbus_connection_update_dispatch_status_and_unlock (connection,
4690 dbus_connection_unref (connection);
4691
4693 }
4694
4695 for (link = _dbus_list_get_first_link (&filter_list_copy);
4696 link != NULL;
4697 link = _dbus_list_get_next_link (&filter_list_copy, link))
4698 _dbus_message_filter_ref (link->data);
4699
4700 /* We're still protected from dispatch() reentrancy here
4701 * since we acquired the dispatcher
4702 */
4703 CONNECTION_UNLOCK (connection);
4704
4705 link = _dbus_list_get_first_link (&filter_list_copy);
4706 while (link != NULL)
4707 {
4708 DBusMessageFilter *filter = link->data;
4709 DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
4710
4711 if (filter->function == NULL)
4712 {
4713 _dbus_verbose (" filter was removed in a callback function\n");
4714 link = next;
4715 continue;
4716 }
4717
4718 _dbus_verbose (" running filter on message %p\n", message);
4719 result = (* filter->function) (connection, message, filter->user_data);
4720
4722 break;
4723
4724 link = next;
4725 }
4726
4727 _dbus_list_clear_full (&filter_list_copy,
4728 (DBusFreeFunction) _dbus_message_filter_unref);
4729
4730 CONNECTION_LOCK (connection);
4731
4732 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
4733 {
4734 _dbus_verbose ("No memory\n");
4735 goto out;
4736 }
4737 else if (result == DBUS_HANDLER_RESULT_HANDLED)
4738 {
4739 _dbus_verbose ("filter handled message in dispatch\n");
4740 goto out;
4741 }
4742
4743 /* We're still protected from dispatch() reentrancy here
4744 * since we acquired the dispatcher
4745 */
4746 _dbus_verbose (" running object path dispatch on message %p (%s %s %s '%s')\n",
4747 message,
4749 dbus_message_get_interface (message) ?
4750 dbus_message_get_interface (message) :
4751 "no interface",
4752 dbus_message_get_member (message) ?
4753 dbus_message_get_member (message) :
4754 "no member",
4755 dbus_message_get_signature (message));
4756
4757 HAVE_LOCK_CHECK (connection);
4758 result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
4759 message,
4760 &found_object);
4761
4762 CONNECTION_LOCK (connection);
4763
4765 {
4766 _dbus_verbose ("object tree handled message in dispatch\n");
4767 goto out;
4768 }
4769
4771 {
4772 DBusMessage *reply;
4773 DBusString str;
4774 DBusPreallocatedSend *preallocated;
4775 DBusList *expire_link;
4776
4777 _dbus_verbose (" sending error %s\n",
4779
4780 if (!_dbus_string_init (&str))
4781 {
4783 _dbus_verbose ("no memory for error string in dispatch\n");
4784 goto out;
4785 }
4786
4787 if (!_dbus_string_append_printf (&str,
4788 "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
4789 dbus_message_get_member (message),
4791 dbus_message_get_interface (message)))
4792 {
4793 _dbus_string_free (&str);
4795 _dbus_verbose ("no memory for error string in dispatch\n");
4796 goto out;
4797 }
4798
4799 reply = dbus_message_new_error (message,
4801 _dbus_string_get_const_data (&str));
4802 _dbus_string_free (&str);
4803
4804 if (reply == NULL)
4805 {
4807 _dbus_verbose ("no memory for error reply in dispatch\n");
4808 goto out;
4809 }
4810
4811 expire_link = _dbus_list_alloc_link (reply);
4812
4813 if (expire_link == NULL)
4814 {
4815 dbus_message_unref (reply);
4817 _dbus_verbose ("no memory for error send in dispatch\n");
4818 goto out;
4819 }
4820
4821 preallocated = _dbus_connection_preallocate_send_unlocked (connection);
4822
4823 if (preallocated == NULL)
4824 {
4825 _dbus_list_free_link (expire_link);
4826 /* It's OK that this is finalized, because it hasn't been seen by
4827 * anything that could attach user callbacks */
4828 dbus_message_unref (reply);
4830 _dbus_verbose ("no memory for error send in dispatch\n");
4831 goto out;
4832 }
4833
4834 _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
4835 reply, NULL);
4836 /* reply will be freed when we release the lock */
4837 _dbus_list_prepend_link (&connection->expired_messages, expire_link);
4838
4840 }
4841
4842 _dbus_verbose (" done dispatching %p (%s %s %s '%s') on connection %p\n", message,
4844 dbus_message_get_interface (message) ?
4845 dbus_message_get_interface (message) :
4846 "no interface",
4847 dbus_message_get_member (message) ?
4848 dbus_message_get_member (message) :
4849 "no member",
4851 connection);
4852
4853 out:
4854 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
4855 {
4856 _dbus_verbose ("out of memory\n");
4857
4858 /* Put message back, and we'll start over.
4859 * Yes this means handlers must be idempotent if they
4860 * don't return HANDLED; c'est la vie.
4861 */
4862 _dbus_connection_putback_message_link_unlocked (connection,
4863 message_link);
4864 /* now we don't want to free them */
4865 message_link = NULL;
4866 message = NULL;
4867 }
4868 else
4869 {
4870 _dbus_verbose (" ... done dispatching\n");
4871 }
4872
4873 _dbus_connection_release_dispatch (connection);
4874 HAVE_LOCK_CHECK (connection);
4875
4876 if (message != NULL)
4877 {
4878 /* We don't want this message to count in maximum message limits when
4879 * computing the dispatch status, below. We have to drop the lock
4880 * temporarily, because finalizing a message can trigger callbacks.
4881 *
4882 * We have a reference to the connection, and we don't use any cached
4883 * pointers to the connection's internals below this point, so it should
4884 * be safe to drop the lock and take it back. */
4885 CONNECTION_UNLOCK (connection);
4886 dbus_message_unref (message);
4887 CONNECTION_LOCK (connection);
4888 }
4889
4890 if (message_link != NULL)
4891 _dbus_list_free_link (message_link);
4892
4893 _dbus_verbose ("before final status update\n");
4894 status = _dbus_connection_get_dispatch_status_unlocked (connection);
4895
4896 /* unlocks and calls user code */
4897 _dbus_connection_update_dispatch_status_and_unlock (connection, status);
4898
4899 dbus_connection_unref (connection);
4900
4901 return status;
4902}
4903
4967 DBusAddWatchFunction add_function,
4968 DBusRemoveWatchFunction remove_function,
4969 DBusWatchToggledFunction toggled_function,
4970 void *data,
4971 DBusFreeFunction free_data_function)
4972{
4973 dbus_bool_t retval;
4974
4975 _dbus_return_val_if_fail (connection != NULL, FALSE);
4976
4977 CONNECTION_LOCK (connection);
4978
4979 retval = _dbus_watch_list_set_functions (connection->watches,
4980 add_function, remove_function,
4981 toggled_function,
4982 data, free_data_function);
4983
4984 CONNECTION_UNLOCK (connection);
4985
4986 return retval;
4987}
4988
5030 DBusAddTimeoutFunction add_function,
5031 DBusRemoveTimeoutFunction remove_function,
5032 DBusTimeoutToggledFunction toggled_function,
5033 void *data,
5034 DBusFreeFunction free_data_function)
5035{
5036 dbus_bool_t retval;
5037
5038 _dbus_return_val_if_fail (connection != NULL, FALSE);
5039
5040 CONNECTION_LOCK (connection);
5041
5042 retval = _dbus_timeout_list_set_functions (connection->timeouts,
5043 add_function, remove_function,
5044 toggled_function,
5045 data, free_data_function);
5046
5047 CONNECTION_UNLOCK (connection);
5048
5049 return retval;
5050}
5051
5066void
5068 DBusWakeupMainFunction wakeup_main_function,
5069 void *data,
5070 DBusFreeFunction free_data_function)
5071{
5072 void *old_data;
5073 DBusFreeFunction old_free_data;
5074
5075 _dbus_return_if_fail (connection != NULL);
5076
5077 CONNECTION_LOCK (connection);
5078 old_data = connection->wakeup_main_data;
5079 old_free_data = connection->free_wakeup_main_data;
5080
5081 connection->wakeup_main_function = wakeup_main_function;
5082 connection->wakeup_main_data = data;
5083 connection->free_wakeup_main_data = free_data_function;
5084
5085 CONNECTION_UNLOCK (connection);
5086
5087 /* Callback outside the lock */
5088 if (old_free_data)
5089 (*old_free_data) (old_data);
5090}
5091
5112void
5115 void *data,
5116 DBusFreeFunction free_data_function)
5117{
5118 void *old_data;
5119 DBusFreeFunction old_free_data;
5120
5121 _dbus_return_if_fail (connection != NULL);
5122
5123 CONNECTION_LOCK (connection);
5124 old_data = connection->dispatch_status_data;
5125 old_free_data = connection->free_dispatch_status_data;
5126
5127 connection->dispatch_status_function = function;
5128 connection->dispatch_status_data = data;
5129 connection->free_dispatch_status_data = free_data_function;
5130
5131 CONNECTION_UNLOCK (connection);
5132
5133 /* Callback outside the lock */
5134 if (old_free_data)
5135 (*old_free_data) (old_data);
5136}
5137
5159 int *fd)
5160{
5161 _dbus_return_val_if_fail (connection != NULL, FALSE);
5162 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
5163
5164#ifdef DBUS_WIN
5165 /* FIXME do this on a lower level */
5166 return FALSE;
5167#endif
5168
5169 return dbus_connection_get_socket(connection, fd);
5170}
5171
5189 int *fd)
5190{
5191 dbus_bool_t retval;
5192 DBusSocket s = DBUS_SOCKET_INIT;
5193
5194 _dbus_return_val_if_fail (connection != NULL, FALSE);
5195 _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
5196
5197 CONNECTION_LOCK (connection);
5198
5199 retval = _dbus_transport_get_socket_fd (connection->transport, &s);
5200
5201 if (retval)
5202 {
5203 *fd = _dbus_socket_get_int (s);
5204 }
5205
5206 CONNECTION_UNLOCK (connection);
5207
5208 return retval;
5209}
5210
5211
5236 unsigned long *uid)
5237{
5238 dbus_bool_t result;
5239
5240 _dbus_return_val_if_fail (connection != NULL, FALSE);
5241 _dbus_return_val_if_fail (uid != NULL, FALSE);
5242
5243 CONNECTION_LOCK (connection);
5244
5246 result = FALSE;
5247 else
5248 result = _dbus_transport_get_unix_user (connection->transport,
5249 uid);
5250
5251#ifdef DBUS_WIN
5252 _dbus_assert (!result);
5253#endif
5254
5255 CONNECTION_UNLOCK (connection);
5256
5257 return result;
5258}
5259
5272 unsigned long *pid)
5273{
5274 dbus_bool_t result;
5275
5276 _dbus_return_val_if_fail (connection != NULL, FALSE);
5277 _dbus_return_val_if_fail (pid != NULL, FALSE);
5278
5279 CONNECTION_LOCK (connection);
5280
5282 result = FALSE;
5283 else
5284 result = _dbus_transport_get_unix_process_id (connection->transport,
5285 pid);
5286
5287 CONNECTION_UNLOCK (connection);
5288
5289 return result;
5290}
5291
5305 void **data,
5306 dbus_int32_t *data_size)
5307{
5308 dbus_bool_t result;
5309
5310 _dbus_return_val_if_fail (connection != NULL, FALSE);
5311 _dbus_return_val_if_fail (data != NULL, FALSE);
5312 _dbus_return_val_if_fail (data_size != NULL, FALSE);
5313
5314 CONNECTION_LOCK (connection);
5315
5317 result = FALSE;
5318 else
5320 data,
5321 data_size);
5322 CONNECTION_UNLOCK (connection);
5323
5324 return result;
5325}
5326
5349void
5352 void *data,
5353 DBusFreeFunction free_data_function)
5354{
5355 void *old_data = NULL;
5356 DBusFreeFunction old_free_function = NULL;
5357
5358 _dbus_return_if_fail (connection != NULL);
5359
5360 CONNECTION_LOCK (connection);
5362 function, data, free_data_function,
5363 &old_data, &old_free_function);
5364 CONNECTION_UNLOCK (connection);
5365
5366 if (old_free_function != NULL)
5367 (* old_free_function) (old_data);
5368}
5369
5370/* Same calling convention as dbus_connection_get_windows_user */
5372_dbus_connection_get_linux_security_label (DBusConnection *connection,
5373 char **label_p)
5374{
5375 dbus_bool_t result;
5376
5377 _dbus_assert (connection != NULL);
5378 _dbus_assert (label_p != NULL);
5379
5380 CONNECTION_LOCK (connection);
5381
5383 result = FALSE;
5384 else
5385 result = _dbus_transport_get_linux_security_label (connection->transport,
5386 label_p);
5387#ifndef __linux__
5388 _dbus_assert (!result);
5389#endif
5390
5391 CONNECTION_UNLOCK (connection);
5392
5393 return result;
5394}
5395
5397_dbus_connection_get_credentials (DBusConnection *connection)
5398{
5399 DBusCredentials *result;
5400
5401 _dbus_assert (connection != NULL);
5402
5403 CONNECTION_LOCK (connection);
5404
5406 result = NULL;
5407 else
5408 result = _dbus_transport_get_credentials (connection->transport);
5409
5410 CONNECTION_UNLOCK (connection);
5411
5412 return result;
5413}
5414
5448 char **windows_sid_p)
5449{
5450 dbus_bool_t result;
5451
5452 _dbus_return_val_if_fail (connection != NULL, FALSE);
5453 _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
5454
5455 CONNECTION_LOCK (connection);
5456
5458 result = FALSE;
5459 else
5460 result = _dbus_transport_get_windows_user (connection->transport,
5461 windows_sid_p);
5462
5463#ifdef DBUS_UNIX
5464 _dbus_assert (!result);
5465#endif
5466
5467 CONNECTION_UNLOCK (connection);
5468
5469 return result;
5470}
5471
5493void
5496 void *data,
5497 DBusFreeFunction free_data_function)
5498{
5499 void *old_data = NULL;
5500 DBusFreeFunction old_free_function = NULL;
5501
5502 _dbus_return_if_fail (connection != NULL);
5503
5504 CONNECTION_LOCK (connection);
5506 function, data, free_data_function,
5507 &old_data, &old_free_function);
5508 CONNECTION_UNLOCK (connection);
5509
5510 if (old_free_function != NULL)
5511 (* old_free_function) (old_data);
5512}
5513
5540void
5542 dbus_bool_t value)
5543{
5544 _dbus_return_if_fail (connection != NULL);
5545
5546 CONNECTION_LOCK (connection);
5548 CONNECTION_UNLOCK (connection);
5549}
5550
5572void
5574 dbus_bool_t value)
5575{
5576 _dbus_assert (connection != NULL);
5577
5578 CONNECTION_LOCK (connection);
5579 connection->builtin_filters_enabled = value;
5580 CONNECTION_UNLOCK (connection);
5581}
5582
5600void
5602 dbus_bool_t value)
5603{
5604 _dbus_return_if_fail (connection != NULL);
5605
5606 CONNECTION_LOCK (connection);
5607 connection->route_peer_messages = value;
5608 CONNECTION_UNLOCK (connection);
5609}
5610
5635 void *user_data,
5636 DBusFreeFunction free_data_function)
5637{
5638 DBusMessageFilter *filter;
5639
5640 _dbus_return_val_if_fail (connection != NULL, FALSE);
5641 _dbus_return_val_if_fail (function != NULL, FALSE);
5642
5643 filter = dbus_new0 (DBusMessageFilter, 1);
5644 if (filter == NULL)
5645 return FALSE;
5646
5647 _dbus_atomic_inc (&filter->refcount);
5648
5649 CONNECTION_LOCK (connection);
5650
5651 if (!_dbus_list_append (&connection->filter_list,
5652 filter))
5653 {
5654 _dbus_message_filter_unref (filter);
5655 CONNECTION_UNLOCK (connection);
5656 return FALSE;
5657 }
5658
5659 /* Fill in filter after all memory allocated,
5660 * so we don't run the free_user_data_function
5661 * if the add_filter() fails
5662 */
5663
5664 filter->function = function;
5665 filter->user_data = user_data;
5666 filter->free_user_data_function = free_data_function;
5667
5668 CONNECTION_UNLOCK (connection);
5669 return TRUE;
5670}
5671
5684void
5687 void *user_data)
5688{
5689 DBusList *link;
5690 DBusMessageFilter *filter;
5691
5692 _dbus_return_if_fail (connection != NULL);
5693 _dbus_return_if_fail (function != NULL);
5694
5695 CONNECTION_LOCK (connection);
5696
5697 filter = NULL;
5698
5699 link = _dbus_list_get_last_link (&connection->filter_list);
5700 while (link != NULL)
5701 {
5702 filter = link->data;
5703
5704 if (filter->function == function &&
5705 filter->user_data == user_data)
5706 {
5707 _dbus_list_remove_link (&connection->filter_list, link);
5708 filter->function = NULL;
5709
5710 break;
5711 }
5712
5713 link = _dbus_list_get_prev_link (&connection->filter_list, link);
5714 filter = NULL;
5715 }
5716
5717 CONNECTION_UNLOCK (connection);
5718
5719#ifndef DBUS_DISABLE_CHECKS
5720 if (filter == NULL)
5721 {
5722 _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added",
5723 function, user_data);
5724 return;
5725 }
5726#endif
5727
5728 /* Call application code */
5729 if (filter->free_user_data_function)
5730 (* filter->free_user_data_function) (filter->user_data);
5731
5732 filter->free_user_data_function = NULL;
5733 filter->user_data = NULL;
5734
5735 _dbus_message_filter_unref (filter);
5736}
5737
5753static dbus_bool_t
5754_dbus_connection_register_object_path (DBusConnection *connection,
5755 dbus_bool_t fallback,
5756 const char *path,
5757 const DBusObjectPathVTable *vtable,
5758 void *user_data,
5759 DBusError *error)
5760{
5761 char **decomposed_path;
5762 dbus_bool_t retval;
5763
5764 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
5765 return FALSE;
5766
5767 CONNECTION_LOCK (connection);
5768
5769 retval = _dbus_object_tree_register (connection->objects,
5770 fallback,
5771 (const char **) decomposed_path, vtable,
5772 user_data, error);
5773
5774 CONNECTION_UNLOCK (connection);
5775
5776 dbus_free_string_array (decomposed_path);
5777
5778 return retval;
5779}
5780
5795 const char *path,
5796 const DBusObjectPathVTable *vtable,
5797 void *user_data,
5798 DBusError *error)
5799{
5800 _dbus_return_val_if_fail (connection != NULL, FALSE);
5801 _dbus_return_val_if_fail (path != NULL, FALSE);
5802 _dbus_return_val_if_fail (path[0] == '/', FALSE);
5803 _dbus_return_val_if_fail (vtable != NULL, FALSE);
5804
5805 return _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, error);
5806}
5807
5825 const char *path,
5826 const DBusObjectPathVTable *vtable,
5827 void *user_data)
5828{
5829 dbus_bool_t retval;
5830 DBusError error = DBUS_ERROR_INIT;
5831
5832 _dbus_return_val_if_fail (connection != NULL, FALSE);
5833 _dbus_return_val_if_fail (path != NULL, FALSE);
5834 _dbus_return_val_if_fail (path[0] == '/', FALSE);
5835 _dbus_return_val_if_fail (vtable != NULL, FALSE);
5836
5837 retval = _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, &error);
5838
5840 {
5841 _dbus_warn ("%s", error.message);
5842 dbus_error_free (&error);
5843 return FALSE;
5844 }
5845
5846 return retval;
5847}
5848
5865 const char *path,
5866 const DBusObjectPathVTable *vtable,
5867 void *user_data,
5868 DBusError *error)
5869{
5870 _dbus_return_val_if_fail (connection != NULL, FALSE);
5871 _dbus_return_val_if_fail (path != NULL, FALSE);
5872 _dbus_return_val_if_fail (path[0] == '/', FALSE);
5873 _dbus_return_val_if_fail (vtable != NULL, FALSE);
5874
5875 return _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, error);
5876}
5877
5897 const char *path,
5898 const DBusObjectPathVTable *vtable,
5899 void *user_data)
5900{
5901 dbus_bool_t retval;
5902 DBusError error = DBUS_ERROR_INIT;
5903
5904 _dbus_return_val_if_fail (connection != NULL, FALSE);
5905 _dbus_return_val_if_fail (path != NULL, FALSE);
5906 _dbus_return_val_if_fail (path[0] == '/', FALSE);
5907 _dbus_return_val_if_fail (vtable != NULL, FALSE);
5908
5909 retval = _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, &error);
5910
5912 {
5913 _dbus_warn ("%s", error.message);
5914 dbus_error_free (&error);
5915 return FALSE;
5916 }
5917
5918 return retval;
5919}
5920
5932 const char *path)
5933{
5934 char **decomposed_path;
5935
5936 _dbus_return_val_if_fail (connection != NULL, FALSE);
5937 _dbus_return_val_if_fail (path != NULL, FALSE);
5938 _dbus_return_val_if_fail (path[0] == '/', FALSE);
5939
5940 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
5941 return FALSE;
5942
5943 CONNECTION_LOCK (connection);
5944
5945 _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
5946
5947 dbus_free_string_array (decomposed_path);
5948
5949 return TRUE;
5950}
5951
5964 const char *path,
5965 void **data_p)
5966{
5967 char **decomposed_path;
5968
5969 _dbus_return_val_if_fail (connection != NULL, FALSE);
5970 _dbus_return_val_if_fail (path != NULL, FALSE);
5971 _dbus_return_val_if_fail (data_p != NULL, FALSE);
5972
5973 *data_p = NULL;
5974
5975 if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
5976 return FALSE;
5977
5978 CONNECTION_LOCK (connection);
5979
5980 *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
5981
5982 CONNECTION_UNLOCK (connection);
5983
5984 dbus_free_string_array (decomposed_path);
5985
5986 return TRUE;
5987}
5988
6001 const char *parent_path,
6002 char ***child_entries)
6003{
6004 char **decomposed_path;
6005 dbus_bool_t retval;
6006 _dbus_return_val_if_fail (connection != NULL, FALSE);
6007 _dbus_return_val_if_fail (parent_path != NULL, FALSE);
6008 _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
6009 _dbus_return_val_if_fail (child_entries != NULL, FALSE);
6010
6011 if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
6012 return FALSE;
6013
6014 CONNECTION_LOCK (connection);
6015
6017 (const char **) decomposed_path,
6018 child_entries);
6019 dbus_free_string_array (decomposed_path);
6020
6021 return retval;
6022}
6023
6024static DBusDataSlotAllocator slot_allocator =
6025 _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (connection_slots));
6026
6043{
6044 return _dbus_data_slot_allocator_alloc (&slot_allocator,
6045 slot_p);
6046}
6047
6059void
6061{
6062 _dbus_return_if_fail (*slot_p >= 0);
6063
6064 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
6065}
6066
6091 dbus_int32_t slot,
6092 void *data,
6093 DBusFreeFunction free_data_func)
6094{
6095 DBusFreeFunction old_free_func;
6096 void *old_data;
6097 dbus_bool_t retval;
6098
6099 _dbus_return_val_if_fail (connection != NULL, FALSE);
6100 _dbus_return_val_if_fail (slot >= 0, FALSE);
6101
6102 SLOTS_LOCK (connection);
6103
6104 retval = _dbus_data_slot_list_set (&slot_allocator,
6105 &connection->slot_list,
6106 slot, data, free_data_func,
6107 &old_free_func, &old_data);
6108
6109 SLOTS_UNLOCK (connection);
6110
6111 if (retval)
6112 {
6113 /* Do the actual free outside the connection lock */
6114 if (old_free_func)
6115 (* old_free_func) (old_data);
6116 }
6117
6118 return retval;
6119}
6120
6138void*
6140 dbus_int32_t slot)
6141{
6142 void *res;
6143
6144 _dbus_return_val_if_fail (connection != NULL, NULL);
6145 _dbus_return_val_if_fail (slot >= 0, NULL);
6146
6147 SLOTS_LOCK (connection);
6148
6149 res = _dbus_data_slot_list_get (&slot_allocator,
6150 &connection->slot_list,
6151 slot);
6152
6153 SLOTS_UNLOCK (connection);
6154
6155 return res;
6156}
6157
6164void
6166{
6167 if (will_modify_sigpipe)
6168 _dbus_atomic_set_nonzero (&_dbus_modify_sigpipe);
6169 else
6170 _dbus_atomic_set_zero (&_dbus_modify_sigpipe);
6171}
6172
6181void
6183 long size)
6184{
6185 _dbus_return_if_fail (connection != NULL);
6186
6187 CONNECTION_LOCK (connection);
6189 size);
6190 CONNECTION_UNLOCK (connection);
6191}
6192
6199long
6201{
6202 long res;
6203
6204 _dbus_return_val_if_fail (connection != NULL, 0);
6205
6206 CONNECTION_LOCK (connection);
6208 CONNECTION_UNLOCK (connection);
6209 return res;
6210}
6211
6220void
6222 long n)
6223{
6224 _dbus_return_if_fail (connection != NULL);
6225
6226 CONNECTION_LOCK (connection);
6228 n);
6229 CONNECTION_UNLOCK (connection);
6230}
6231
6238long
6240{
6241 long res;
6242
6243 _dbus_return_val_if_fail (connection != NULL, 0);
6244
6245 CONNECTION_LOCK (connection);
6247 CONNECTION_UNLOCK (connection);
6248 return res;
6249}
6250
6276void
6278 long size)
6279{
6280 _dbus_return_if_fail (connection != NULL);
6281
6282 CONNECTION_LOCK (connection);
6284 size);
6285 CONNECTION_UNLOCK (connection);
6286}
6287
6294long
6296{
6297 long res;
6298
6299 _dbus_return_val_if_fail (connection != NULL, 0);
6300
6301 CONNECTION_LOCK (connection);
6303 CONNECTION_UNLOCK (connection);
6304 return res;
6305}
6306
6318void
6320 long n)
6321{
6322 _dbus_return_if_fail (connection != NULL);
6323
6324 CONNECTION_LOCK (connection);
6326 n);
6327 CONNECTION_UNLOCK (connection);
6328}
6329
6336long
6338{
6339 long res;
6340
6341 _dbus_return_val_if_fail (connection != NULL, 0);
6342
6343 CONNECTION_LOCK (connection);
6345 CONNECTION_UNLOCK (connection);
6346 return res;
6347}
6348
6359long
6361{
6362 long res;
6363
6364 _dbus_return_val_if_fail (connection != NULL, 0);
6365
6366 CONNECTION_LOCK (connection);
6368 CONNECTION_UNLOCK (connection);
6369 return res;
6370}
6371
6372#ifdef DBUS_ENABLE_STATS
6373void
6374_dbus_connection_get_stats (DBusConnection *connection,
6375 dbus_uint32_t *in_messages,
6376 dbus_uint32_t *in_bytes,
6377 dbus_uint32_t *in_fds,
6378 dbus_uint32_t *in_peak_bytes,
6379 dbus_uint32_t *in_peak_fds,
6380 dbus_uint32_t *out_messages,
6381 dbus_uint32_t *out_bytes,
6382 dbus_uint32_t *out_fds,
6383 dbus_uint32_t *out_peak_bytes,
6384 dbus_uint32_t *out_peak_fds)
6385{
6386 CONNECTION_LOCK (connection);
6387
6388 if (in_messages != NULL)
6389 *in_messages = connection->n_incoming;
6390
6391 _dbus_transport_get_stats (connection->transport,
6392 in_bytes, in_fds, in_peak_bytes, in_peak_fds);
6393
6394 if (out_messages != NULL)
6395 *out_messages = connection->n_outgoing;
6396
6397 if (out_bytes != NULL)
6398 *out_bytes = _dbus_counter_get_size_value (connection->outgoing_counter);
6399
6400 if (out_fds != NULL)
6401 *out_fds = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
6402
6403 if (out_peak_bytes != NULL)
6404 *out_peak_bytes = _dbus_counter_get_peak_size_value (connection->outgoing_counter);
6405
6406 if (out_peak_fds != NULL)
6407 *out_peak_fds = _dbus_counter_get_peak_unix_fd_value (connection->outgoing_counter);
6408
6409 CONNECTION_UNLOCK (connection);
6410}
6411#endif /* DBUS_ENABLE_STATS */
6412
6420long
6422{
6423 long res;
6424
6425 _dbus_return_val_if_fail (connection != NULL, 0);
6426
6427 CONNECTION_LOCK (connection);
6429 CONNECTION_UNLOCK (connection);
6430 return res;
6431}
6432
6433#ifdef DBUS_ENABLE_EMBEDDED_TESTS
6440const char*
6441_dbus_connection_get_address (DBusConnection *connection)
6442{
6443 return _dbus_transport_get_address (connection->transport);
6444}
6445#endif
6446
void dbus_address_entries_free(DBusAddressEntry **entries)
Frees a NULL-terminated array of address entries.
Definition: dbus-address.c:192
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:366
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:247
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:388
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.
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_builtin_filters_enabled(DBusConnection *connection, dbus_bool_t value)
Enables the builtin filtering of messages.
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:70
#define DBUS_ERROR_INIT
Expands to a suitable initializer for a DBusError on the stack.
Definition: dbus-errors.h:62
void dbus_move_error(DBusError *src, DBusError *dest)
Moves an error src into dest, freeing src and overwriting dest.
Definition: dbus-errors.c:279
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:302
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:354
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:211
int _dbus_hash_table_get_n_entries(DBusHashTable *table)
Gets the number of hash entries in a hash table.
Definition: dbus-hash.c:1460
void * _dbus_hash_iter_get_value(DBusHashIter *iter)
Gets the value of the current entry.
Definition: dbus-hash.c:619
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:1311
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:1277
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:367
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:549
void _dbus_hash_iter_init(DBusHashTable *table, DBusHashIter *iter)
Initializes a hash table iterator.
Definition: dbus-hash.c:523
DBusHashTable * _dbus_hash_table_new(DBusHashType type, DBusFreeFunction key_free_function, DBusFreeFunction value_free_function)
Constructs a new hash table.
Definition: dbus-hash.c:291
dbus_bool_t _dbus_hash_table_remove_int(DBusHashTable *table, int key)
Removes the hash entry for the given key.
Definition: dbus-hash.c:1214
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:1186
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:1112
void _dbus_hash_iter_remove_entry(DBusHashIter *iter)
Removes the current entry from the hash table.
Definition: dbus-hash.c:598
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:1137
@ 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:595
dbus_bool_t _dbus_list_copy(DBusList **list, DBusList **dest)
Copies a list.
Definition: dbus-list.c:725
DBusList * _dbus_list_pop_first_link(DBusList **list)
Removes the first link in the list and returns it.
Definition: dbus-list.c:656
void * _dbus_list_get_last(DBusList **list)
Gets the last data in the list.
Definition: dbus-list.c:624
dbus_bool_t _dbus_list_remove(DBusList **list, void *data)
Removes a value from the list.
Definition: dbus-list.c:416
void _dbus_list_append_link(DBusList **list, DBusList *link)
Appends a link to the list.
Definition: dbus-list.c:316
void _dbus_list_clear_full(DBusList **list, DBusFreeFunction function)
Free every link and every element in the list.
Definition: dbus-list.c:568
void _dbus_list_remove_link(DBusList **list, DBusList *link)
Removes a link from the list.
Definition: dbus-list.c:528
void * _dbus_list_get_first(DBusList **list)
Gets the first data in the list.
Definition: dbus-list.c:640
DBusList * _dbus_list_get_last_link(DBusList **list)
Gets the last link in the list.
Definition: dbus-list.c:608
void _dbus_list_unlink(DBusList **list, DBusList *link)
Removes the given link from the list, but doesn't free it.
Definition: dbus-list.c:500
#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:120
void _dbus_list_free_link(DBusList *link)
Frees a linked list node allocated with _dbus_list_alloc_link.
Definition: dbus-list.c:255
void * _dbus_list_pop_first(DBusList **list)
Removes the first value in the list and returns it.
Definition: dbus-list.c:677
void _dbus_list_foreach(DBusList **list, DBusForeachFunction function, void *data)
Calls the given function for each element in the list.
Definition: dbus-list.c:787
void _dbus_list_clear(DBusList **list)
Frees all links in the list and sets the list head to NULL.
Definition: dbus-list.c:543
void _dbus_list_prepend_link(DBusList **list, DBusList *link)
Prepends a link to the list.
Definition: dbus-list.c:334
dbus_bool_t _dbus_list_prepend(DBusList **list, void *data)
Prepends a value to the list.
Definition: dbus-list.c:293
DBusList * _dbus_list_alloc_link(void *data)
Allocates a linked list node.
Definition: dbus-list.c:243
dbus_bool_t _dbus_list_append(DBusList **list, void *data)
Appends a value to the list.
Definition: dbus-list.c:271
#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:119
#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:772
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:801
void(* DBusFreeFunction)(void *memory)
The type of a function which frees a block of memory.
Definition: dbus-memory.h:63
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:692
#define dbus_new(type, count)
Safe macro for using dbus_malloc().
Definition: dbus-memory.h:57
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
Definition: dbus-memory.h:58
void dbus_free_string_array(char **str_array)
Frees a NULL-terminated array of strings.
Definition: dbus-memory.c:740
void dbus_message_set_serial(DBusMessage *message, dbus_uint32_t serial)
Sets the serial number of a message.
Definition: dbus-message.c:289
void dbus_message_lock(DBusMessage *message)
Locks a message.
Definition: dbus-message.c:419
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:387
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:315
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:60
#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:67
#define DBUS_PATH_LOCAL
The object path used in local/in-process-generated messages.
Definition: dbus-shared.h:82
#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:105
#define DBUS_INTERFACE_PEER
The interface supported by most dbus peers.
Definition: dbus-shared.h:99
@ 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:70
@ DBUS_HANDLER_RESULT_HANDLED
Message has had its effect - no need to run more handlers.
Definition: dbus-shared.h:68
@ DBUS_HANDLER_RESULT_NOT_YET_HANDLED
Message has not had any effect - see if other handlers want it.
Definition: dbus-shared.h:69
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:1145
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:54
void _dbus_cmutex_free_at_location(DBusCMutex **location_p)
Frees a DBusCMutex; does nothing if passed a NULL pointer.
Definition: dbus-threads.c:108
void _dbus_condvar_free_at_location(DBusCondVar **location_p)
Frees a condition variable; does nothing if passed a NULL pointer.
Definition: dbus-threads.c:225
DBUS_PRIVATE_EXPORT void _dbus_rmutex_unlock(DBusRMutex *mutex)
Unlocks a mutex.
Definition: dbus-threads.c:151
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:241
void _dbus_condvar_new_at_location(DBusCondVar **location_p)
This does the same thing as _dbus_condvar_new.
Definition: dbus-threads.c:200
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:78
void _dbus_condvar_wake_one(DBusCondVar *cond)
If there are threads waiting on the condition variable, wake up exactly one.
Definition: dbus-threads.c:279
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:262
void _dbus_cmutex_lock(DBusCMutex *mutex)
Locks a mutex.
Definition: dbus-threads.c:137
void _dbus_cmutex_unlock(DBusCMutex *mutex)
Unlocks a mutex.
Definition: dbus-threads.c:165
void _dbus_rmutex_free_at_location(DBusRMutex **location_p)
Frees a DBusRMutex; does nothing if passed a NULL pointer.
Definition: dbus-threads.c:95
struct DBusMutex DBusMutex
An opaque mutex type provided by the DBusThreadFunctions implementation installed by dbus_threads_ini...
Definition: dbus-threads.h:41
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:312
void _dbus_timeout_list_free(DBusTimeoutList *timeout_list)
Frees a DBusTimeoutList.
Definition: dbus-timeout.c:215
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:364
DBusTimeoutList * _dbus_timeout_list_new(void)
Creates a new timeout list.
Definition: dbus-timeout.c:198
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:241
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:342
DBUS_EXPORT int dbus_timeout_get_interval(DBusTimeout *timeout)
Gets the timeout interval.
Definition: dbus-timeout.c:442
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:35
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:381
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:441
DBusWatchList * _dbus_watch_list_new(void)
Creates a new watch list.
Definition: dbus-watch.c:232
void _dbus_watch_list_free(DBusWatchList *watch_list)
Frees a DBusWatchList.
Definition: dbus-watch.c:249
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:295
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:414
Internals of DBusAddressEntry.
Definition: dbus-address.c:47
An atomic integer safe to increment or decrement from multiple threads.
Definition: dbus-sysdeps.h:324
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:56
Data structure that stores the actual user data set at a given slot.
Definition: dbus-dataslot.h:70
Object representing an exception.
Definition: dbus-errors.h:49
const char * name
public error name field
Definition: dbus-errors.h:50
const char * message
public error message field
Definition: dbus-errors.h:51
Hash iterator object.
Definition: dbus-hash.h:50
Internals of DBusHashTable.
Definition: dbus-hash.c:174
A node in a linked list.
Definition: dbus-list.h:35
void * data
Data stored at this element.
Definition: dbus-list.h:38
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:62
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:181
DBusTimeoutList implementation details.
Definition: dbus-timeout.c:181
Internals of DBusTimeout.
Definition: dbus-timeout.c:41
Object representing a transport such as a socket.
DBusWatchList implementation details.
Definition: dbus-watch.c:215
Implementation of DBusWatch.
Definition: dbus-watch.c:41