D-Bus  1.7.4
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 
206 #ifdef DBUS_ENABLE_VERBOSE_MODE
207 static void
208 _dbus_connection_trace_ref (DBusConnection *connection,
209  int old_refcount,
210  int new_refcount,
211  const char *why)
212 {
213  static int enabled = -1;
214 
215  _dbus_trace_ref ("DBusConnection", connection, old_refcount, new_refcount,
216  why, "DBUS_CONNECTION_TRACE", &enabled);
217 }
218 #else
219 #define _dbus_connection_trace_ref(c,o,n,w) \
220  do \
221  {\
222  (void) (o); \
223  (void) (n); \
224  } while (0)
225 #endif
226 
231 
236 {
239  void *user_data;
241 };
242 
243 
248 {
252 };
253 
254 #if HAVE_DECL_MSG_NOSIGNAL
255 static dbus_bool_t _dbus_modify_sigpipe = FALSE;
256 #else
257 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
258 #endif
259 
264 {
313  char *server_guid;
315  /* These two MUST be bools and not bitfields, because they are protected by a separate lock
316  * from connection->mutex and all bitfields in a word have to be read/written together.
317  * So you can't have a different lock for different bitfields in the same word.
318  */
322  unsigned int shareable : 1;
324  unsigned int exit_on_disconnect : 1;
326  unsigned int route_peer_messages : 1;
328  unsigned int disconnected_message_arrived : 1;
336 #ifndef DBUS_DISABLE_CHECKS
337  unsigned int have_connection_lock : 1;
338 #endif
339 
340 #ifndef DBUS_DISABLE_CHECKS
342 #endif
343 };
344 
345 static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection);
346 static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
347  DBusDispatchStatus new_status);
348 static void _dbus_connection_last_unref (DBusConnection *connection);
349 static void _dbus_connection_acquire_dispatch (DBusConnection *connection);
350 static void _dbus_connection_release_dispatch (DBusConnection *connection);
351 static DBusDispatchStatus _dbus_connection_flush_unlocked (DBusConnection *connection, int timeout_milliseconds);
352 static void _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection);
353 static dbus_bool_t _dbus_connection_get_is_connected_unlocked (DBusConnection *connection);
354 static dbus_bool_t _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
355  dbus_uint32_t client_serial);
356 
357 static DBusMessageFilter *
358 _dbus_message_filter_ref (DBusMessageFilter *filter)
359 {
360 #ifdef DBUS_DISABLE_ASSERT
361  _dbus_atomic_inc (&filter->refcount);
362 #else
363  dbus_int32_t old_value;
364 
365  old_value = _dbus_atomic_inc (&filter->refcount);
366  _dbus_assert (old_value > 0);
367 #endif
368 
369  return filter;
370 }
371 
372 static void
373 _dbus_message_filter_unref (DBusMessageFilter *filter)
374 {
375  dbus_int32_t old_value;
376 
377  old_value = _dbus_atomic_dec (&filter->refcount);
378  _dbus_assert (old_value > 0);
379 
380  if (old_value == 1)
381  {
382  if (filter->free_user_data_function)
383  (* filter->free_user_data_function) (filter->user_data);
384 
385  dbus_free (filter);
386  }
387 }
388 
394 void
396 {
397  CONNECTION_LOCK (connection);
398 }
399 
405 void
407 {
408  DBusList *expired_messages;
409  DBusList *iter;
410 
411  if (TRACE_LOCKS)
412  {
413  _dbus_verbose ("UNLOCK\n");
414  }
415 
416  /* If we had messages that expired (fell off the incoming or outgoing
417  * queues) while we were locked, actually release them now */
418  expired_messages = connection->expired_messages;
419  connection->expired_messages = NULL;
420 
421  RELEASING_LOCK_CHECK (connection);
422  _dbus_rmutex_unlock (connection->mutex);
423 
424  for (iter = _dbus_list_pop_first_link (&expired_messages);
425  iter != NULL;
426  iter = _dbus_list_pop_first_link (&expired_messages))
427  {
428  DBusMessage *message = iter->data;
429 
430  dbus_message_unref (message);
431  _dbus_list_free_link (iter);
432  }
433 }
434 
442 static void
443 _dbus_connection_wakeup_mainloop (DBusConnection *connection)
444 {
445  if (connection->wakeup_main_function)
446  (*connection->wakeup_main_function) (connection->wakeup_main_data);
447 }
448 
449 #ifdef DBUS_BUILD_TESTS
450 
462 void
463 _dbus_connection_test_get_locks (DBusConnection *connection,
464  DBusMutex **mutex_loc,
465  DBusMutex **dispatch_mutex_loc,
466  DBusMutex **io_path_mutex_loc,
467  DBusCondVar **dispatch_cond_loc,
468  DBusCondVar **io_path_cond_loc)
469 {
470  *mutex_loc = (DBusMutex *) connection->mutex;
471  *dispatch_mutex_loc = (DBusMutex *) connection->dispatch_mutex;
472  *io_path_mutex_loc = (DBusMutex *) connection->io_path_mutex;
473  *dispatch_cond_loc = connection->dispatch_cond;
474  *io_path_cond_loc = connection->io_path_cond;
475 }
476 #endif
477 
486 void
488  DBusList *link)
489 {
490  DBusPendingCall *pending;
491  dbus_uint32_t reply_serial;
492  DBusMessage *message;
493 
495 
497  link);
498  message = link->data;
499 
500  /* If this is a reply we're waiting on, remove timeout for it */
501  reply_serial = dbus_message_get_reply_serial (message);
502  if (reply_serial != 0)
503  {
504  pending = _dbus_hash_table_lookup_int (connection->pending_replies,
505  reply_serial);
506  if (pending != NULL)
507  {
511 
513  }
514  }
515 
516 
517 
518  connection->n_incoming += 1;
519 
520  _dbus_connection_wakeup_mainloop (connection);
521 
522  _dbus_verbose ("Message %p (%s %s %s %s '%s' reply to %u) added to incoming queue %p, %d incoming\n",
523  message,
525  dbus_message_get_path (message) ?
526  dbus_message_get_path (message) :
527  "no path",
528  dbus_message_get_interface (message) ?
529  dbus_message_get_interface (message) :
530  "no interface",
531  dbus_message_get_member (message) ?
532  dbus_message_get_member (message) :
533  "no member",
534  dbus_message_get_signature (message),
536  connection,
537  connection->n_incoming);
538 
539  _dbus_message_trace_ref (message, -1, -1,
540  "_dbus_conection_queue_received_message_link");
541 }
542 
551 void
553  DBusList *link)
554 {
555  HAVE_LOCK_CHECK (connection);
556 
557  _dbus_list_append_link (&connection->incoming_messages, link);
558 
559  connection->n_incoming += 1;
560 
561  _dbus_connection_wakeup_mainloop (connection);
562 
563  _dbus_message_trace_ref (link->data, -1, -1,
564  "_dbus_connection_queue_synthesized_message_link");
565 
566  _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n",
567  link->data, connection, connection->n_incoming);
568 }
569 
570 
580 {
581  HAVE_LOCK_CHECK (connection);
582  return connection->outgoing_messages != NULL;
583 }
584 
596 {
597  dbus_bool_t v;
598 
599  _dbus_return_val_if_fail (connection != NULL, FALSE);
600 
601  CONNECTION_LOCK (connection);
603  CONNECTION_UNLOCK (connection);
604 
605  return v;
606 }
607 
617 {
618  HAVE_LOCK_CHECK (connection);
619 
620  return _dbus_list_get_last (&connection->outgoing_messages);
621 }
622 
631 void
633  DBusMessage *message)
634 {
635  DBusList *link;
636 
637  HAVE_LOCK_CHECK (connection);
638 
639  /* This can be called before we even complete authentication, since
640  * it's called on disconnect to clean up the outgoing queue.
641  * It's also called as we successfully send each message.
642  */
643 
644  link = _dbus_list_get_last_link (&connection->outgoing_messages);
645  _dbus_assert (link != NULL);
646  _dbus_assert (link->data == message);
647 
648  _dbus_list_unlink (&connection->outgoing_messages,
649  link);
650  _dbus_list_prepend_link (&connection->expired_messages, link);
651 
652  connection->n_outgoing -= 1;
653 
654  _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
655  message,
657  dbus_message_get_path (message) ?
658  dbus_message_get_path (message) :
659  "no path",
660  dbus_message_get_interface (message) ?
661  dbus_message_get_interface (message) :
662  "no interface",
663  dbus_message_get_member (message) ?
664  dbus_message_get_member (message) :
665  "no member",
666  dbus_message_get_signature (message),
667  connection, connection->n_outgoing);
668 
669  /* It's OK that in principle we call the notify function, because for the
670  * outgoing limit, there isn't one */
671  _dbus_message_remove_counter (message, connection->outgoing_counter);
672 
673  /* The message will actually be unreffed when we unlock */
674 }
675 
678  DBusWatch *watch);
680 typedef void (* DBusWatchRemoveFunction) (DBusWatchList *list,
681  DBusWatch *watch);
683 typedef void (* DBusWatchToggleFunction) (DBusWatchList *list,
684  DBusWatch *watch,
685  dbus_bool_t enabled);
686 
687 static dbus_bool_t
688 protected_change_watch (DBusConnection *connection,
689  DBusWatch *watch,
690  DBusWatchAddFunction add_function,
691  DBusWatchRemoveFunction remove_function,
692  DBusWatchToggleFunction toggle_function,
693  dbus_bool_t enabled)
694 {
695  dbus_bool_t retval;
696 
697  HAVE_LOCK_CHECK (connection);
698 
699  /* The original purpose of protected_change_watch() was to hold a
700  * ref on the connection while dropping the connection lock, then
701  * calling out to the app. This was a broken hack that did not
702  * work, since the connection was in a hosed state (no WatchList
703  * field) while calling out.
704  *
705  * So for now we'll just keep the lock while calling out. This means
706  * apps are not allowed to call DBusConnection methods inside a
707  * watch function or they will deadlock.
708  *
709  * The "real fix" is to use the _and_unlock() pattern found
710  * elsewhere in the code, to defer calling out to the app until
711  * we're about to drop locks and return flow of control to the app
712  * anyway.
713  *
714  * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
715  */
716 
717  if (connection->watches)
718  {
719  if (add_function)
720  retval = (* add_function) (connection->watches, watch);
721  else if (remove_function)
722  {
723  retval = TRUE;
724  (* remove_function) (connection->watches, watch);
725  }
726  else
727  {
728  retval = TRUE;
729  (* toggle_function) (connection->watches, watch, enabled);
730  }
731  return retval;
732  }
733  else
734  return FALSE;
735 }
736 
737 
751  DBusWatch *watch)
752 {
753  return protected_change_watch (connection, watch,
755  NULL, NULL, FALSE);
756 }
757 
767 void
769  DBusWatch *watch)
770 {
771  protected_change_watch (connection, watch,
772  NULL,
774  NULL, FALSE);
775 }
776 
787 void
789  DBusWatch *watch,
790  dbus_bool_t enabled)
791 {
792  _dbus_assert (watch != NULL);
793 
794  protected_change_watch (connection, watch,
795  NULL, NULL,
797  enabled);
798 }
799 
802  DBusTimeout *timeout);
805  DBusTimeout *timeout);
808  DBusTimeout *timeout,
809  dbus_bool_t enabled);
810 
811 static dbus_bool_t
812 protected_change_timeout (DBusConnection *connection,
813  DBusTimeout *timeout,
814  DBusTimeoutAddFunction add_function,
815  DBusTimeoutRemoveFunction remove_function,
816  DBusTimeoutToggleFunction toggle_function,
817  dbus_bool_t enabled)
818 {
819  dbus_bool_t retval;
820 
821  HAVE_LOCK_CHECK (connection);
822 
823  /* The original purpose of protected_change_timeout() was to hold a
824  * ref on the connection while dropping the connection lock, then
825  * calling out to the app. This was a broken hack that did not
826  * work, since the connection was in a hosed state (no TimeoutList
827  * field) while calling out.
828  *
829  * So for now we'll just keep the lock while calling out. This means
830  * apps are not allowed to call DBusConnection methods inside a
831  * timeout function or they will deadlock.
832  *
833  * The "real fix" is to use the _and_unlock() pattern found
834  * elsewhere in the code, to defer calling out to the app until
835  * we're about to drop locks and return flow of control to the app
836  * anyway.
837  *
838  * See http://lists.freedesktop.org/archives/dbus/2007-July/thread.html#8144
839  */
840 
841  if (connection->timeouts)
842  {
843  if (add_function)
844  retval = (* add_function) (connection->timeouts, timeout);
845  else if (remove_function)
846  {
847  retval = TRUE;
848  (* remove_function) (connection->timeouts, timeout);
849  }
850  else
851  {
852  retval = TRUE;
853  (* toggle_function) (connection->timeouts, timeout, enabled);
854  }
855  return retval;
856  }
857  else
858  return FALSE;
859 }
860 
875  DBusTimeout *timeout)
876 {
877  return protected_change_timeout (connection, timeout,
879  NULL, NULL, FALSE);
880 }
881 
891 void
893  DBusTimeout *timeout)
894 {
895  protected_change_timeout (connection, timeout,
896  NULL,
898  NULL, FALSE);
899 }
900 
911 void
913  DBusTimeout *timeout,
914  dbus_bool_t enabled)
915 {
916  protected_change_timeout (connection, timeout,
917  NULL, NULL,
919  enabled);
920 }
921 
922 static dbus_bool_t
923 _dbus_connection_attach_pending_call_unlocked (DBusConnection *connection,
924  DBusPendingCall *pending)
925 {
926  dbus_uint32_t reply_serial;
927  DBusTimeout *timeout;
928 
929  HAVE_LOCK_CHECK (connection);
930 
931  reply_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
932 
933  _dbus_assert (reply_serial != 0);
934 
935  timeout = _dbus_pending_call_get_timeout_unlocked (pending);
936 
937  if (timeout)
938  {
939  if (!_dbus_connection_add_timeout_unlocked (connection, timeout))
940  return FALSE;
941 
943  reply_serial,
944  pending))
945  {
946  _dbus_connection_remove_timeout_unlocked (connection, timeout);
947 
949  HAVE_LOCK_CHECK (connection);
950  return FALSE;
951  }
952 
954  }
955  else
956  {
958  reply_serial,
959  pending))
960  {
961  HAVE_LOCK_CHECK (connection);
962  return FALSE;
963  }
964  }
965 
967 
968  HAVE_LOCK_CHECK (connection);
969 
970  return TRUE;
971 }
972 
973 static void
974 free_pending_call_on_hash_removal (void *data)
975 {
976  DBusPendingCall *pending;
977  DBusConnection *connection;
978 
979  if (data == NULL)
980  return;
981 
982  pending = data;
983 
984  connection = _dbus_pending_call_get_connection_unlocked (pending);
985 
986  HAVE_LOCK_CHECK (connection);
987 
989  {
992 
994  }
995 
996  /* FIXME 1.0? this is sort of dangerous and undesirable to drop the lock
997  * here, but the pending call finalizer could in principle call out to
998  * application code so we pretty much have to... some larger code reorg
999  * might be needed.
1000  */
1001  _dbus_connection_ref_unlocked (connection);
1003  CONNECTION_LOCK (connection);
1004  _dbus_connection_unref_unlocked (connection);
1005 }
1006 
1007 static void
1008 _dbus_connection_detach_pending_call_unlocked (DBusConnection *connection,
1009  DBusPendingCall *pending)
1010 {
1011  /* This ends up unlocking to call the pending call finalizer, which is unexpected to
1012  * say the least.
1013  */
1016 }
1017 
1018 static void
1019 _dbus_connection_detach_pending_call_and_unlock (DBusConnection *connection,
1020  DBusPendingCall *pending)
1021 {
1022  /* The idea here is to avoid finalizing the pending call
1023  * with the lock held, since there's a destroy notifier
1024  * in pending call that goes out to application code.
1025  *
1026  * There's an extra unlock inside the hash table
1027  * "free pending call" function FIXME...
1028  */
1032 
1036 
1038 
1040 }
1041 
1050 void
1052  DBusPendingCall *pending)
1053 {
1054  CONNECTION_LOCK (connection);
1055  _dbus_connection_detach_pending_call_and_unlock (connection, pending);
1056 }
1057 
1067 static dbus_bool_t
1068 _dbus_connection_acquire_io_path (DBusConnection *connection,
1069  int timeout_milliseconds)
1070 {
1071  dbus_bool_t we_acquired;
1072 
1073  HAVE_LOCK_CHECK (connection);
1074 
1075  /* We don't want the connection to vanish */
1076  _dbus_connection_ref_unlocked (connection);
1077 
1078  /* We will only touch io_path_acquired which is protected by our mutex */
1079  CONNECTION_UNLOCK (connection);
1080 
1081  _dbus_verbose ("locking io_path_mutex\n");
1082  _dbus_cmutex_lock (connection->io_path_mutex);
1083 
1084  _dbus_verbose ("start connection->io_path_acquired = %d timeout = %d\n",
1085  connection->io_path_acquired, timeout_milliseconds);
1086 
1087  we_acquired = FALSE;
1088 
1089  if (connection->io_path_acquired)
1090  {
1091  if (timeout_milliseconds != -1)
1092  {
1093  _dbus_verbose ("waiting %d for IO path to be acquirable\n",
1094  timeout_milliseconds);
1095 
1096  if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
1097  connection->io_path_mutex,
1098  timeout_milliseconds))
1099  {
1100  /* We timed out before anyone signaled. */
1101  /* (writing the loop to handle the !timedout case by
1102  * waiting longer if needed is a pain since dbus
1103  * wraps pthread_cond_timedwait to take a relative
1104  * time instead of absolute, something kind of stupid
1105  * on our part. for now it doesn't matter, we will just
1106  * end up back here eventually.)
1107  */
1108  }
1109  }
1110  else
1111  {
1112  while (connection->io_path_acquired)
1113  {
1114  _dbus_verbose ("waiting for IO path to be acquirable\n");
1115  _dbus_condvar_wait (connection->io_path_cond,
1116  connection->io_path_mutex);
1117  }
1118  }
1119  }
1120 
1121  if (!connection->io_path_acquired)
1122  {
1123  we_acquired = TRUE;
1124  connection->io_path_acquired = TRUE;
1125  }
1126 
1127  _dbus_verbose ("end connection->io_path_acquired = %d we_acquired = %d\n",
1128  connection->io_path_acquired, we_acquired);
1129 
1130  _dbus_verbose ("unlocking io_path_mutex\n");
1131  _dbus_cmutex_unlock (connection->io_path_mutex);
1132 
1133  CONNECTION_LOCK (connection);
1134 
1135  HAVE_LOCK_CHECK (connection);
1136 
1137  _dbus_connection_unref_unlocked (connection);
1138 
1139  return we_acquired;
1140 }
1141 
1149 static void
1150 _dbus_connection_release_io_path (DBusConnection *connection)
1151 {
1152  HAVE_LOCK_CHECK (connection);
1153 
1154  _dbus_verbose ("locking io_path_mutex\n");
1155  _dbus_cmutex_lock (connection->io_path_mutex);
1156 
1157  _dbus_assert (connection->io_path_acquired);
1158 
1159  _dbus_verbose ("start connection->io_path_acquired = %d\n",
1160  connection->io_path_acquired);
1161 
1162  connection->io_path_acquired = FALSE;
1163  _dbus_condvar_wake_one (connection->io_path_cond);
1164 
1165  _dbus_verbose ("unlocking io_path_mutex\n");
1166  _dbus_cmutex_unlock (connection->io_path_mutex);
1167 }
1168 
1204 void
1206  DBusPendingCall *pending,
1207  unsigned int flags,
1208  int timeout_milliseconds)
1209 {
1210  _dbus_verbose ("start\n");
1211 
1212  HAVE_LOCK_CHECK (connection);
1213 
1214  if (connection->n_outgoing == 0)
1215  flags &= ~DBUS_ITERATION_DO_WRITING;
1216 
1217  if (_dbus_connection_acquire_io_path (connection,
1218  (flags & DBUS_ITERATION_BLOCK) ? timeout_milliseconds : 0))
1219  {
1220  HAVE_LOCK_CHECK (connection);
1221 
1222  if ( (pending != NULL) && _dbus_pending_call_get_completed_unlocked(pending))
1223  {
1224  _dbus_verbose ("pending call completed while acquiring I/O path");
1225  }
1226  else if ( (pending != NULL) &&
1227  _dbus_connection_peek_for_reply_unlocked (connection,
1229  {
1230  _dbus_verbose ("pending call completed while acquiring I/O path (reply found in queue)");
1231  }
1232  else
1233  {
1235  flags, timeout_milliseconds);
1236  }
1237 
1238  _dbus_connection_release_io_path (connection);
1239  }
1240 
1241  HAVE_LOCK_CHECK (connection);
1242 
1243  _dbus_verbose ("end\n");
1244 }
1245 
1257 {
1258  DBusConnection *connection;
1259  DBusWatchList *watch_list;
1260  DBusTimeoutList *timeout_list;
1261  DBusHashTable *pending_replies;
1262  DBusList *disconnect_link;
1263  DBusMessage *disconnect_message;
1264  DBusCounter *outgoing_counter;
1265  DBusObjectTree *objects;
1266 
1267  watch_list = NULL;
1268  connection = NULL;
1269  pending_replies = NULL;
1270  timeout_list = NULL;
1271  disconnect_link = NULL;
1272  disconnect_message = NULL;
1273  outgoing_counter = NULL;
1274  objects = NULL;
1275 
1276  watch_list = _dbus_watch_list_new ();
1277  if (watch_list == NULL)
1278  goto error;
1279 
1280  timeout_list = _dbus_timeout_list_new ();
1281  if (timeout_list == NULL)
1282  goto error;
1283 
1284  pending_replies =
1286  NULL,
1287  (DBusFreeFunction)free_pending_call_on_hash_removal);
1288  if (pending_replies == NULL)
1289  goto error;
1290 
1291  connection = dbus_new0 (DBusConnection, 1);
1292  if (connection == NULL)
1293  goto error;
1294 
1295  _dbus_rmutex_new_at_location (&connection->mutex);
1296  if (connection->mutex == NULL)
1297  goto error;
1298 
1300  if (connection->io_path_mutex == NULL)
1301  goto error;
1302 
1304  if (connection->dispatch_mutex == NULL)
1305  goto error;
1306 
1308  if (connection->dispatch_cond == NULL)
1309  goto error;
1310 
1312  if (connection->io_path_cond == NULL)
1313  goto error;
1314 
1316  if (connection->slot_mutex == NULL)
1317  goto error;
1318 
1319  disconnect_message = dbus_message_new_signal (DBUS_PATH_LOCAL,
1321  "Disconnected");
1322 
1323  if (disconnect_message == NULL)
1324  goto error;
1325 
1326  disconnect_link = _dbus_list_alloc_link (disconnect_message);
1327  if (disconnect_link == NULL)
1328  goto error;
1329 
1330  outgoing_counter = _dbus_counter_new ();
1331  if (outgoing_counter == NULL)
1332  goto error;
1333 
1334  objects = _dbus_object_tree_new (connection);
1335  if (objects == NULL)
1336  goto error;
1337 
1338  if (_dbus_modify_sigpipe)
1340 
1341  /* initialized to 0: use atomic op to avoid mixing atomic and non-atomic */
1342  _dbus_atomic_inc (&connection->refcount);
1343  connection->transport = transport;
1344  connection->watches = watch_list;
1345  connection->timeouts = timeout_list;
1346  connection->pending_replies = pending_replies;
1347  connection->outgoing_counter = outgoing_counter;
1348  connection->filter_list = NULL;
1349  connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
1350  connection->objects = objects;
1351  connection->exit_on_disconnect = FALSE;
1352  connection->shareable = FALSE;
1353  connection->route_peer_messages = FALSE;
1354  connection->disconnected_message_arrived = FALSE;
1355  connection->disconnected_message_processed = FALSE;
1356 
1357 #ifndef DBUS_DISABLE_CHECKS
1358  connection->generation = _dbus_current_generation;
1359 #endif
1360 
1361  _dbus_data_slot_list_init (&connection->slot_list);
1362 
1363  connection->client_serial = 1;
1364 
1365  connection->disconnect_message_link = disconnect_link;
1366 
1367  CONNECTION_LOCK (connection);
1368 
1369  if (!_dbus_transport_set_connection (transport, connection))
1370  {
1371  CONNECTION_UNLOCK (connection);
1372 
1373  goto error;
1374  }
1375 
1376  _dbus_transport_ref (transport);
1377 
1378  CONNECTION_UNLOCK (connection);
1379 
1380  _dbus_connection_trace_ref (connection, 0, 1, "new_for_transport");
1381  return connection;
1382 
1383  error:
1384  if (disconnect_message != NULL)
1385  dbus_message_unref (disconnect_message);
1386 
1387  if (disconnect_link != NULL)
1388  _dbus_list_free_link (disconnect_link);
1389 
1390  if (connection != NULL)
1391  {
1394  _dbus_rmutex_free_at_location (&connection->mutex);
1398  dbus_free (connection);
1399  }
1400  if (pending_replies)
1401  _dbus_hash_table_unref (pending_replies);
1402 
1403  if (watch_list)
1404  _dbus_watch_list_free (watch_list);
1405 
1406  if (timeout_list)
1407  _dbus_timeout_list_free (timeout_list);
1408 
1409  if (outgoing_counter)
1410  _dbus_counter_unref (outgoing_counter);
1411 
1412  if (objects)
1413  _dbus_object_tree_unref (objects);
1414 
1415  return NULL;
1416 }
1417 
1427 {
1428  dbus_int32_t old_refcount;
1429 
1430  _dbus_assert (connection != NULL);
1432 
1433  HAVE_LOCK_CHECK (connection);
1434 
1435  old_refcount = _dbus_atomic_inc (&connection->refcount);
1436  _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1,
1437  "ref_unlocked");
1438 
1439  return connection;
1440 }
1441 
1448 void
1450 {
1451  dbus_int32_t old_refcount;
1452 
1453  HAVE_LOCK_CHECK (connection);
1454 
1455  _dbus_assert (connection != NULL);
1456 
1457  old_refcount = _dbus_atomic_dec (&connection->refcount);
1458 
1459  _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1,
1460  "unref_unlocked");
1461 
1462  if (old_refcount == 1)
1463  _dbus_connection_last_unref (connection);
1464 }
1465 
1466 static dbus_uint32_t
1467 _dbus_connection_get_next_client_serial (DBusConnection *connection)
1468 {
1469  dbus_uint32_t serial;
1470 
1471  serial = connection->client_serial++;
1472 
1473  if (connection->client_serial == 0)
1474  connection->client_serial = 1;
1475 
1476  return serial;
1477 }
1478 
1494  unsigned int condition,
1495  void *data)
1496 {
1497  DBusConnection *connection;
1498  dbus_bool_t retval;
1499  DBusDispatchStatus status;
1500 
1501  connection = data;
1502 
1503  _dbus_verbose ("start\n");
1504 
1505  CONNECTION_LOCK (connection);
1506 
1507  if (!_dbus_connection_acquire_io_path (connection, 1))
1508  {
1509  /* another thread is handling the message */
1510  CONNECTION_UNLOCK (connection);
1511  return TRUE;
1512  }
1513 
1514  HAVE_LOCK_CHECK (connection);
1515  retval = _dbus_transport_handle_watch (connection->transport,
1516  watch, condition);
1517 
1518  _dbus_connection_release_io_path (connection);
1519 
1520  HAVE_LOCK_CHECK (connection);
1521 
1522  _dbus_verbose ("middle\n");
1523 
1524  status = _dbus_connection_get_dispatch_status_unlocked (connection);
1525 
1526  /* this calls out to user code */
1527  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
1528 
1529  _dbus_verbose ("end\n");
1530 
1531  return retval;
1532 }
1533 
1534 _DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
1535 static DBusHashTable *shared_connections = NULL;
1536 static DBusList *shared_connections_no_guid = NULL;
1537 
1538 static void
1539 close_connection_on_shutdown (DBusConnection *connection)
1540 {
1541  DBusMessage *message;
1542 
1543  dbus_connection_ref (connection);
1545 
1546  /* Churn through to the Disconnected message */
1547  while ((message = dbus_connection_pop_message (connection)))
1548  {
1549  dbus_message_unref (message);
1550  }
1551  dbus_connection_unref (connection);
1552 }
1553 
1554 static void
1555 shared_connections_shutdown (void *data)
1556 {
1557  int n_entries;
1558 
1559  _DBUS_LOCK (shared_connections);
1560 
1561  /* This is a little bit unpleasant... better ideas? */
1562  while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
1563  {
1564  DBusConnection *connection;
1565  DBusHashIter iter;
1566 
1567  _dbus_hash_iter_init (shared_connections, &iter);
1568  _dbus_hash_iter_next (&iter);
1569 
1570  connection = _dbus_hash_iter_get_value (&iter);
1571 
1572  _DBUS_UNLOCK (shared_connections);
1573  close_connection_on_shutdown (connection);
1574  _DBUS_LOCK (shared_connections);
1575 
1576  /* The connection should now be dead and not in our hash ... */
1577  _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
1578  }
1579 
1580  _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) == 0);
1581 
1582  _dbus_hash_table_unref (shared_connections);
1583  shared_connections = NULL;
1584 
1585  if (shared_connections_no_guid != NULL)
1586  {
1587  DBusConnection *connection;
1588  connection = _dbus_list_pop_first (&shared_connections_no_guid);
1589  while (connection != NULL)
1590  {
1591  _DBUS_UNLOCK (shared_connections);
1592  close_connection_on_shutdown (connection);
1593  _DBUS_LOCK (shared_connections);
1594  connection = _dbus_list_pop_first (&shared_connections_no_guid);
1595  }
1596  }
1597 
1598  shared_connections_no_guid = NULL;
1599 
1600  _DBUS_UNLOCK (shared_connections);
1601 }
1602 
1603 static dbus_bool_t
1604 connection_lookup_shared (DBusAddressEntry *entry,
1605  DBusConnection **result)
1606 {
1607  _dbus_verbose ("checking for existing connection\n");
1608 
1609  *result = NULL;
1610 
1611  _DBUS_LOCK (shared_connections);
1612 
1613  if (shared_connections == NULL)
1614  {
1615  _dbus_verbose ("creating shared_connections hash table\n");
1616 
1617  shared_connections = _dbus_hash_table_new (DBUS_HASH_STRING,
1618  dbus_free,
1619  NULL);
1620  if (shared_connections == NULL)
1621  {
1622  _DBUS_UNLOCK (shared_connections);
1623  return FALSE;
1624  }
1625 
1626  if (!_dbus_register_shutdown_func (shared_connections_shutdown, NULL))
1627  {
1628  _dbus_hash_table_unref (shared_connections);
1629  shared_connections = NULL;
1630  _DBUS_UNLOCK (shared_connections);
1631  return FALSE;
1632  }
1633 
1634  _dbus_verbose (" successfully created shared_connections\n");
1635 
1636  _DBUS_UNLOCK (shared_connections);
1637  return TRUE; /* no point looking up in the hash we just made */
1638  }
1639  else
1640  {
1641  const char *guid;
1642 
1643  guid = dbus_address_entry_get_value (entry, "guid");
1644 
1645  if (guid != NULL)
1646  {
1647  DBusConnection *connection;
1648 
1649  connection = _dbus_hash_table_lookup_string (shared_connections,
1650  guid);
1651 
1652  if (connection)
1653  {
1654  /* The DBusConnection can't be finalized without taking
1655  * the shared_connections lock to remove it from the
1656  * hash. So it's safe to ref the connection here.
1657  * However, it may be disconnected if the Disconnected
1658  * message hasn't been processed yet, in which case we
1659  * want to pretend it isn't in the hash and avoid
1660  * returning it.
1661  *
1662  * The idea is to avoid ever returning a disconnected connection
1663  * from dbus_connection_open(). We could just synchronously
1664  * drop our shared ref to the connection on connection disconnect,
1665  * and then assert here that the connection is connected, but
1666  * that causes reentrancy headaches.
1667  */
1668  CONNECTION_LOCK (connection);
1669  if (_dbus_connection_get_is_connected_unlocked (connection))
1670  {
1671  _dbus_connection_ref_unlocked (connection);
1672  *result = connection;
1673  _dbus_verbose ("looked up existing connection to server guid %s\n",
1674  guid);
1675  }
1676  else
1677  {
1678  _dbus_verbose ("looked up existing connection to server guid %s but it was disconnected so ignoring it\n",
1679  guid);
1680  }
1681  CONNECTION_UNLOCK (connection);
1682  }
1683  }
1684 
1685  _DBUS_UNLOCK (shared_connections);
1686  return TRUE;
1687  }
1688 }
1689 
1690 static dbus_bool_t
1691 connection_record_shared_unlocked (DBusConnection *connection,
1692  const char *guid)
1693 {
1694  char *guid_key;
1695  char *guid_in_connection;
1696 
1697  HAVE_LOCK_CHECK (connection);
1698  _dbus_assert (connection->server_guid == NULL);
1699  _dbus_assert (connection->shareable);
1700 
1701  /* get a hard ref on this connection, even if
1702  * we won't in fact store it in the hash, we still
1703  * need to hold a ref on it until it's disconnected.
1704  */
1705  _dbus_connection_ref_unlocked (connection);
1706 
1707  if (guid == NULL)
1708  {
1709  _DBUS_LOCK (shared_connections);
1710 
1711  if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
1712  {
1713  _DBUS_UNLOCK (shared_connections);
1714  return FALSE;
1715  }
1716 
1717  _DBUS_UNLOCK (shared_connections);
1718  return TRUE; /* don't store in the hash */
1719  }
1720 
1721  /* A separate copy of the key is required in the hash table, because
1722  * we don't have a lock on the connection when we are doing a hash
1723  * lookup.
1724  */
1725 
1726  guid_key = _dbus_strdup (guid);
1727  if (guid_key == NULL)
1728  return FALSE;
1729 
1730  guid_in_connection = _dbus_strdup (guid);
1731  if (guid_in_connection == NULL)
1732  {
1733  dbus_free (guid_key);
1734  return FALSE;
1735  }
1736 
1737  _DBUS_LOCK (shared_connections);
1738  _dbus_assert (shared_connections != NULL);
1739 
1740  if (!_dbus_hash_table_insert_string (shared_connections,
1741  guid_key, connection))
1742  {
1743  dbus_free (guid_key);
1744  dbus_free (guid_in_connection);
1745  _DBUS_UNLOCK (shared_connections);
1746  return FALSE;
1747  }
1748 
1749  connection->server_guid = guid_in_connection;
1750 
1751  _dbus_verbose ("stored connection to %s to be shared\n",
1752  connection->server_guid);
1753 
1754  _DBUS_UNLOCK (shared_connections);
1755 
1756  _dbus_assert (connection->server_guid != NULL);
1757 
1758  return TRUE;
1759 }
1760 
1761 static void
1762 connection_forget_shared_unlocked (DBusConnection *connection)
1763 {
1764  HAVE_LOCK_CHECK (connection);
1765 
1766  if (!connection->shareable)
1767  return;
1768 
1769  _DBUS_LOCK (shared_connections);
1770 
1771  if (connection->server_guid != NULL)
1772  {
1773  _dbus_verbose ("dropping connection to %s out of the shared table\n",
1774  connection->server_guid);
1775 
1776  if (!_dbus_hash_table_remove_string (shared_connections,
1777  connection->server_guid))
1778  _dbus_assert_not_reached ("connection was not in the shared table");
1779 
1780  dbus_free (connection->server_guid);
1781  connection->server_guid = NULL;
1782  }
1783  else
1784  {
1785  _dbus_list_remove (&shared_connections_no_guid, connection);
1786  }
1787 
1788  _DBUS_UNLOCK (shared_connections);
1789 
1790  /* remove our reference held on all shareable connections */
1791  _dbus_connection_unref_unlocked (connection);
1792 }
1793 
1794 static DBusConnection*
1795 connection_try_from_address_entry (DBusAddressEntry *entry,
1796  DBusError *error)
1797 {
1798  DBusTransport *transport;
1799  DBusConnection *connection;
1800 
1801  transport = _dbus_transport_open (entry, error);
1802 
1803  if (transport == NULL)
1804  {
1805  _DBUS_ASSERT_ERROR_IS_SET (error);
1806  return NULL;
1807  }
1808 
1809  connection = _dbus_connection_new_for_transport (transport);
1810 
1811  _dbus_transport_unref (transport);
1812 
1813  if (connection == NULL)
1814  {
1815  _DBUS_SET_OOM (error);
1816  return NULL;
1817  }
1818 
1819 #ifndef DBUS_DISABLE_CHECKS
1820  _dbus_assert (!connection->have_connection_lock);
1821 #endif
1822  return connection;
1823 }
1824 
1825 /*
1826  * If the shared parameter is true, then any existing connection will
1827  * be used (and if a new connection is created, it will be available
1828  * for use by others). If the shared parameter is false, a new
1829  * connection will always be created, and the new connection will
1830  * never be returned to other callers.
1831  *
1832  * @param address the address
1833  * @param shared whether the connection is shared or private
1834  * @param error error return
1835  * @returns the connection or #NULL on error
1836  */
1837 static DBusConnection*
1838 _dbus_connection_open_internal (const char *address,
1839  dbus_bool_t shared,
1840  DBusError *error)
1841 {
1842  DBusConnection *connection;
1843  DBusAddressEntry **entries;
1844  DBusError tmp_error = DBUS_ERROR_INIT;
1845  DBusError first_error = DBUS_ERROR_INIT;
1846  int len, i;
1847 
1848  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1849 
1850  _dbus_verbose ("opening %s connection to: %s\n",
1851  shared ? "shared" : "private", address);
1852 
1853  if (!dbus_parse_address (address, &entries, &len, error))
1854  return NULL;
1855 
1856  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1857 
1858  connection = NULL;
1859 
1860  for (i = 0; i < len; i++)
1861  {
1862  if (shared)
1863  {
1864  if (!connection_lookup_shared (entries[i], &connection))
1865  _DBUS_SET_OOM (&tmp_error);
1866  }
1867 
1868  if (connection == NULL)
1869  {
1870  connection = connection_try_from_address_entry (entries[i],
1871  &tmp_error);
1872 
1873  if (connection != NULL && shared)
1874  {
1875  const char *guid;
1876 
1877  connection->shareable = TRUE;
1878 
1879  /* guid may be NULL */
1880  guid = dbus_address_entry_get_value (entries[i], "guid");
1881 
1882  CONNECTION_LOCK (connection);
1883 
1884  if (!connection_record_shared_unlocked (connection, guid))
1885  {
1886  _DBUS_SET_OOM (&tmp_error);
1887  _dbus_connection_close_possibly_shared_and_unlock (connection);
1888  dbus_connection_unref (connection);
1889  connection = NULL;
1890  }
1891  else
1892  CONNECTION_UNLOCK (connection);
1893  }
1894  }
1895 
1896  if (connection)
1897  break;
1898 
1899  _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
1900 
1901  if (i == 0)
1902  dbus_move_error (&tmp_error, &first_error);
1903  else
1904  dbus_error_free (&tmp_error);
1905  }
1906 
1907  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1908  _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
1909 
1910  if (connection == NULL)
1911  {
1912  _DBUS_ASSERT_ERROR_IS_SET (&first_error);
1913  dbus_move_error (&first_error, error);
1914  }
1915  else
1916  dbus_error_free (&first_error);
1917 
1918  dbus_address_entries_free (entries);
1919  return connection;
1920 }
1921 
1930 void
1932 {
1933  _dbus_assert (connection != NULL);
1935 
1936  CONNECTION_LOCK (connection);
1937  _dbus_connection_close_possibly_shared_and_unlock (connection);
1938 }
1939 
1940 static DBusPreallocatedSend*
1941 _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
1942 {
1943  DBusPreallocatedSend *preallocated;
1944 
1945  HAVE_LOCK_CHECK (connection);
1946 
1947  _dbus_assert (connection != NULL);
1948 
1949  preallocated = dbus_new (DBusPreallocatedSend, 1);
1950  if (preallocated == NULL)
1951  return NULL;
1952 
1953  preallocated->queue_link = _dbus_list_alloc_link (NULL);
1954  if (preallocated->queue_link == NULL)
1955  goto failed_0;
1956 
1957  preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
1958  if (preallocated->counter_link == NULL)
1959  goto failed_1;
1960 
1961  _dbus_counter_ref (preallocated->counter_link->data);
1962 
1963  preallocated->connection = connection;
1964 
1965  return preallocated;
1966 
1967  failed_1:
1968  _dbus_list_free_link (preallocated->queue_link);
1969  failed_0:
1970  dbus_free (preallocated);
1971 
1972  return NULL;
1973 }
1974 
1975 /* Called with lock held, does not update dispatch status */
1976 static void
1977 _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *connection,
1978  DBusPreallocatedSend *preallocated,
1979  DBusMessage *message,
1980  dbus_uint32_t *client_serial)
1981 {
1982  dbus_uint32_t serial;
1983 
1984  preallocated->queue_link->data = message;
1986  preallocated->queue_link);
1987 
1988  /* It's OK that we'll never call the notify function, because for the
1989  * outgoing limit, there isn't one */
1991  preallocated->counter_link);
1992 
1993  dbus_free (preallocated);
1994  preallocated = NULL;
1995 
1996  dbus_message_ref (message);
1997 
1998  connection->n_outgoing += 1;
1999 
2000  _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
2001  message,
2003  dbus_message_get_path (message) ?
2004  dbus_message_get_path (message) :
2005  "no path",
2006  dbus_message_get_interface (message) ?
2007  dbus_message_get_interface (message) :
2008  "no interface",
2009  dbus_message_get_member (message) ?
2010  dbus_message_get_member (message) :
2011  "no member",
2012  dbus_message_get_signature (message),
2013  dbus_message_get_destination (message) ?
2014  dbus_message_get_destination (message) :
2015  "null",
2016  connection,
2017  connection->n_outgoing);
2018 
2019  if (dbus_message_get_serial (message) == 0)
2020  {
2021  serial = _dbus_connection_get_next_client_serial (connection);
2022  dbus_message_set_serial (message, serial);
2023  if (client_serial)
2024  *client_serial = serial;
2025  }
2026  else
2027  {
2028  if (client_serial)
2029  *client_serial = dbus_message_get_serial (message);
2030  }
2031 
2032  _dbus_verbose ("Message %p serial is %u\n",
2033  message, dbus_message_get_serial (message));
2034 
2035  dbus_message_lock (message);
2036 
2037  /* Now we need to run an iteration to hopefully just write the messages
2038  * out immediately, and otherwise get them queued up
2039  */
2041  NULL,
2042  DBUS_ITERATION_DO_WRITING,
2043  -1);
2044 
2045  /* If stuff is still queued up, be sure we wake up the main loop */
2046  if (connection->n_outgoing > 0)
2047  _dbus_connection_wakeup_mainloop (connection);
2048 }
2049 
2050 static void
2051 _dbus_connection_send_preallocated_and_unlock (DBusConnection *connection,
2052  DBusPreallocatedSend *preallocated,
2053  DBusMessage *message,
2054  dbus_uint32_t *client_serial)
2055 {
2056  DBusDispatchStatus status;
2057 
2058  HAVE_LOCK_CHECK (connection);
2059 
2060  _dbus_connection_send_preallocated_unlocked_no_update (connection,
2061  preallocated,
2062  message, client_serial);
2063 
2064  _dbus_verbose ("middle\n");
2065  status = _dbus_connection_get_dispatch_status_unlocked (connection);
2066 
2067  /* this calls out to user code */
2068  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2069 }
2070 
2082  DBusMessage *message,
2083  dbus_uint32_t *client_serial)
2084 {
2085  DBusPreallocatedSend *preallocated;
2086 
2087  _dbus_assert (connection != NULL);
2088  _dbus_assert (message != NULL);
2089 
2090  preallocated = _dbus_connection_preallocate_send_unlocked (connection);
2091  if (preallocated == NULL)
2092  {
2093  CONNECTION_UNLOCK (connection);
2094  return FALSE;
2095  }
2096 
2097  _dbus_connection_send_preallocated_and_unlock (connection,
2098  preallocated,
2099  message,
2100  client_serial);
2101  return TRUE;
2102 }
2103 
2128 void
2130 {
2131  dbus_int32_t refcount;
2132 
2133  CONNECTION_LOCK (connection);
2134 
2135  refcount = _dbus_atomic_get (&connection->refcount);
2136  /* The caller should have at least one ref */
2137  _dbus_assert (refcount >= 1);
2138 
2139  if (refcount == 1)
2140  _dbus_connection_close_possibly_shared_and_unlock (connection);
2141  else
2142  CONNECTION_UNLOCK (connection);
2143 }
2144 
2145 
2155 static void
2156 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
2157 {
2158  if (timeout_milliseconds == -1)
2159  _dbus_sleep_milliseconds (1000);
2160  else if (timeout_milliseconds < 100)
2161  ; /* just busy loop */
2162  else if (timeout_milliseconds <= 1000)
2163  _dbus_sleep_milliseconds (timeout_milliseconds / 3);
2164  else
2165  _dbus_sleep_milliseconds (1000);
2166 }
2167 
2168 static DBusMessage *
2169 generate_local_error_message (dbus_uint32_t serial,
2170  char *error_name,
2171  char *error_msg)
2172 {
2173  DBusMessage *message;
2175  if (!message)
2176  goto out;
2177 
2178  if (!dbus_message_set_error_name (message, error_name))
2179  {
2180  dbus_message_unref (message);
2181  message = NULL;
2182  goto out;
2183  }
2184 
2185  dbus_message_set_no_reply (message, TRUE);
2186 
2187  if (!dbus_message_set_reply_serial (message,
2188  serial))
2189  {
2190  dbus_message_unref (message);
2191  message = NULL;
2192  goto out;
2193  }
2194 
2195  if (error_msg != NULL)
2196  {
2197  DBusMessageIter iter;
2198 
2199  dbus_message_iter_init_append (message, &iter);
2200  if (!dbus_message_iter_append_basic (&iter,
2202  &error_msg))
2203  {
2204  dbus_message_unref (message);
2205  message = NULL;
2206  goto out;
2207  }
2208  }
2209 
2210  out:
2211  return message;
2212 }
2213 
2214 /*
2215  * Peek the incoming queue to see if we got reply for a specific serial
2216  */
2217 static dbus_bool_t
2218 _dbus_connection_peek_for_reply_unlocked (DBusConnection *connection,
2219  dbus_uint32_t client_serial)
2220 {
2221  DBusList *link;
2222  HAVE_LOCK_CHECK (connection);
2223 
2224  link = _dbus_list_get_first_link (&connection->incoming_messages);
2225 
2226  while (link != NULL)
2227  {
2228  DBusMessage *reply = link->data;
2229 
2230  if (dbus_message_get_reply_serial (reply) == client_serial)
2231  {
2232  _dbus_verbose ("%s reply to %d found in queue\n", _DBUS_FUNCTION_NAME, client_serial);
2233  return TRUE;
2234  }
2235  link = _dbus_list_get_next_link (&connection->incoming_messages, link);
2236  }
2237 
2238  return FALSE;
2239 }
2240 
2241 /* This is slightly strange since we can pop a message here without
2242  * the dispatch lock.
2243  */
2244 static DBusMessage*
2245 check_for_reply_unlocked (DBusConnection *connection,
2246  dbus_uint32_t client_serial)
2247 {
2248  DBusList *link;
2249 
2250  HAVE_LOCK_CHECK (connection);
2251 
2252  link = _dbus_list_get_first_link (&connection->incoming_messages);
2253 
2254  while (link != NULL)
2255  {
2256  DBusMessage *reply = link->data;
2257 
2258  if (dbus_message_get_reply_serial (reply) == client_serial)
2259  {
2260  _dbus_list_remove_link (&connection->incoming_messages, link);
2261  connection->n_incoming -= 1;
2262  return reply;
2263  }
2264  link = _dbus_list_get_next_link (&connection->incoming_messages, link);
2265  }
2266 
2267  return NULL;
2268 }
2269 
2270 static void
2271 connection_timeout_and_complete_all_pending_calls_unlocked (DBusConnection *connection)
2272 {
2273  /* We can't iterate over the hash in the normal way since we'll be
2274  * dropping the lock for each item. So we restart the
2275  * iter each time as we drain the hash table.
2276  */
2277 
2278  while (_dbus_hash_table_get_n_entries (connection->pending_replies) > 0)
2279  {
2280  DBusPendingCall *pending;
2281  DBusHashIter iter;
2282 
2283  _dbus_hash_iter_init (connection->pending_replies, &iter);
2284  _dbus_hash_iter_next (&iter);
2285 
2286  pending = _dbus_hash_iter_get_value (&iter);
2288 
2290  connection);
2291 
2297 
2299  CONNECTION_LOCK (connection);
2300  }
2301  HAVE_LOCK_CHECK (connection);
2302 }
2303 
2304 static void
2305 complete_pending_call_and_unlock (DBusConnection *connection,
2306  DBusPendingCall *pending,
2307  DBusMessage *message)
2308 {
2309  _dbus_pending_call_set_reply_unlocked (pending, message);
2310  _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */
2311  _dbus_connection_detach_pending_call_and_unlock (connection, pending);
2312 
2313  /* Must be called unlocked since it invokes app callback */
2314  _dbus_pending_call_complete (pending);
2315  dbus_pending_call_unref (pending);
2316 }
2317 
2318 static dbus_bool_t
2319 check_for_reply_and_update_dispatch_unlocked (DBusConnection *connection,
2320  DBusPendingCall *pending)
2321 {
2322  DBusMessage *reply;
2323  DBusDispatchStatus status;
2324 
2325  reply = check_for_reply_unlocked (connection,
2327  if (reply != NULL)
2328  {
2329  _dbus_verbose ("checked for reply\n");
2330 
2331  _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply\n");
2332 
2333  complete_pending_call_and_unlock (connection, pending, reply);
2334  dbus_message_unref (reply);
2335 
2336  CONNECTION_LOCK (connection);
2337  status = _dbus_connection_get_dispatch_status_unlocked (connection);
2338  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2339  dbus_pending_call_unref (pending);
2340 
2341  return TRUE;
2342  }
2343 
2344  return FALSE;
2345 }
2346 
2361 void
2363 {
2364  long start_tv_sec, start_tv_usec;
2365  long tv_sec, tv_usec;
2366  DBusDispatchStatus status;
2367  DBusConnection *connection;
2368  dbus_uint32_t client_serial;
2369  DBusTimeout *timeout;
2370  int timeout_milliseconds = -1, elapsed_milliseconds;
2371 
2372  _dbus_assert (pending != NULL);
2373 
2374  if (dbus_pending_call_get_completed (pending))
2375  return;
2376 
2377  dbus_pending_call_ref (pending); /* necessary because the call could be canceled */
2378 
2379  connection = _dbus_pending_call_get_connection_and_lock (pending);
2380 
2381  /* Flush message queue - note, can affect dispatch status */
2382 
2383  timeout = _dbus_pending_call_get_timeout_unlocked (pending);
2384  if (timeout)
2385  timeout_milliseconds = dbus_timeout_get_interval (timeout);
2386 
2387  _dbus_connection_flush_unlocked (connection, timeout_milliseconds);
2388 
2389  client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
2390 
2391  /* note that timeout_milliseconds is limited to a smallish value
2392  * in _dbus_pending_call_new() so overflows aren't possible
2393  * below
2394  */
2395  timeout = _dbus_pending_call_get_timeout_unlocked (pending);
2396  _dbus_get_monotonic_time (&start_tv_sec, &start_tv_usec);
2397  if (timeout)
2398  {
2399  timeout_milliseconds = dbus_timeout_get_interval (timeout);
2400 
2401  _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block %d milliseconds for reply serial %u from %ld sec %ld usec\n",
2402  timeout_milliseconds,
2403  client_serial,
2404  start_tv_sec, start_tv_usec);
2405  }
2406  else
2407  {
2408  timeout_milliseconds = -1;
2409 
2410  _dbus_verbose ("dbus_connection_send_with_reply_and_block(): will block for reply serial %u\n", client_serial);
2411  }
2412 
2413  /* check to see if we already got the data off the socket */
2414  /* from another blocked pending call */
2415  if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
2416  return;
2417 
2418  /* Now we wait... */
2419  /* always block at least once as we know we don't have the reply yet */
2421  pending,
2422  DBUS_ITERATION_DO_READING |
2423  DBUS_ITERATION_BLOCK,
2424  timeout_milliseconds);
2425 
2426  recheck_status:
2427 
2428  _dbus_verbose ("top of recheck\n");
2429 
2430  HAVE_LOCK_CHECK (connection);
2431 
2432  /* queue messages and get status */
2433 
2434  status = _dbus_connection_get_dispatch_status_unlocked (connection);
2435 
2436  /* the get_completed() is in case a dispatch() while we were blocking
2437  * got the reply instead of us.
2438  */
2440  {
2441  _dbus_verbose ("Pending call completed by dispatch\n");
2442  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2443  dbus_pending_call_unref (pending);
2444  return;
2445  }
2446 
2447  if (status == DBUS_DISPATCH_DATA_REMAINS)
2448  {
2449  if (check_for_reply_and_update_dispatch_unlocked (connection, pending))
2450  return;
2451  }
2452 
2453  _dbus_get_monotonic_time (&tv_sec, &tv_usec);
2454  elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
2455  (tv_usec - start_tv_usec) / 1000;
2456 
2457  if (!_dbus_connection_get_is_connected_unlocked (connection))
2458  {
2459  DBusMessage *error_msg;
2460 
2461  error_msg = generate_local_error_message (client_serial,
2463  "Connection was disconnected before a reply was received");
2464 
2465  /* on OOM error_msg is set to NULL */
2466  complete_pending_call_and_unlock (connection, pending, error_msg);
2467  dbus_pending_call_unref (pending);
2468  return;
2469  }
2470  else if (connection->disconnect_message_link == NULL)
2471  _dbus_verbose ("dbus_connection_send_with_reply_and_block(): disconnected\n");
2472  else if (timeout == NULL)
2473  {
2474  if (status == DBUS_DISPATCH_NEED_MEMORY)
2475  {
2476  /* Try sleeping a bit, as we aren't sure we need to block for reading,
2477  * we may already have a reply in the buffer and just can't process
2478  * it.
2479  */
2480  _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
2481 
2482  _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
2483  }
2484  else
2485  {
2486  /* block again, we don't have the reply buffered yet. */
2488  pending,
2489  DBUS_ITERATION_DO_READING |
2490  DBUS_ITERATION_BLOCK,
2491  timeout_milliseconds - elapsed_milliseconds);
2492  }
2493 
2494  goto recheck_status;
2495  }
2496  else if (tv_sec < start_tv_sec)
2497  _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n");
2498  else if (elapsed_milliseconds < timeout_milliseconds)
2499  {
2500  _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds);
2501 
2502  if (status == DBUS_DISPATCH_NEED_MEMORY)
2503  {
2504  /* Try sleeping a bit, as we aren't sure we need to block for reading,
2505  * we may already have a reply in the buffer and just can't process
2506  * it.
2507  */
2508  _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n");
2509 
2510  _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds);
2511  }
2512  else
2513  {
2514  /* block again, we don't have the reply buffered yet. */
2516  NULL,
2517  DBUS_ITERATION_DO_READING |
2518  DBUS_ITERATION_BLOCK,
2519  timeout_milliseconds - elapsed_milliseconds);
2520  }
2521 
2522  goto recheck_status;
2523  }
2524 
2525  _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %d milliseconds and got no reply\n",
2526  elapsed_milliseconds);
2527 
2529 
2530  /* unlock and call user code */
2531  complete_pending_call_and_unlock (connection, pending, NULL);
2532 
2533  /* update user code on dispatch status */
2534  CONNECTION_LOCK (connection);
2535  status = _dbus_connection_get_dispatch_status_unlocked (connection);
2536  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2537  dbus_pending_call_unref (pending);
2538 }
2539 
2577 dbus_connection_open (const char *address,
2578  DBusError *error)
2579 {
2580  DBusConnection *connection;
2581 
2582  _dbus_return_val_if_fail (address != NULL, NULL);
2583  _dbus_return_val_if_error_is_set (error, NULL);
2584 
2585  connection = _dbus_connection_open_internal (address,
2586  TRUE,
2587  error);
2588 
2589  return connection;
2590 }
2591 
2620 dbus_connection_open_private (const char *address,
2621  DBusError *error)
2622 {
2623  DBusConnection *connection;
2624 
2625  _dbus_return_val_if_fail (address != NULL, NULL);
2626  _dbus_return_val_if_error_is_set (error, NULL);
2627 
2628  connection = _dbus_connection_open_internal (address,
2629  FALSE,
2630  error);
2631 
2632  return connection;
2633 }
2634 
2643 {
2644  dbus_int32_t old_refcount;
2645 
2646  _dbus_return_val_if_fail (connection != NULL, NULL);
2647  _dbus_return_val_if_fail (connection->generation == _dbus_current_generation, NULL);
2648  old_refcount = _dbus_atomic_inc (&connection->refcount);
2649  _dbus_connection_trace_ref (connection, old_refcount, old_refcount + 1,
2650  "ref");
2651 
2652  return connection;
2653 }
2654 
2655 static void
2656 free_outgoing_message (void *element,
2657  void *data)
2658 {
2659  DBusMessage *message = element;
2660  DBusConnection *connection = data;
2661 
2662  _dbus_message_remove_counter (message, connection->outgoing_counter);
2663  dbus_message_unref (message);
2664 }
2665 
2666 /* This is run without the mutex held, but after the last reference
2667  * to the connection has been dropped we should have no thread-related
2668  * problems
2669  */
2670 static void
2671 _dbus_connection_last_unref (DBusConnection *connection)
2672 {
2673  DBusList *link;
2674 
2675  _dbus_verbose ("Finalizing connection %p\n", connection);
2676 
2677  _dbus_assert (_dbus_atomic_get (&connection->refcount) == 0);
2678 
2679  /* You have to disconnect the connection before unref:ing it. Otherwise
2680  * you won't get the disconnected message.
2681  */
2683  _dbus_assert (connection->server_guid == NULL);
2684 
2685  /* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
2687 
2691 
2692  _dbus_watch_list_free (connection->watches);
2693  connection->watches = NULL;
2694 
2695  _dbus_timeout_list_free (connection->timeouts);
2696  connection->timeouts = NULL;
2697 
2698  _dbus_data_slot_list_free (&connection->slot_list);
2699 
2700  link = _dbus_list_get_first_link (&connection->filter_list);
2701  while (link != NULL)
2702  {
2703  DBusMessageFilter *filter = link->data;
2704  DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
2705 
2706  filter->function = NULL;
2707  _dbus_message_filter_unref (filter); /* calls app callback */
2708  link->data = NULL;
2709 
2710  link = next;
2711  }
2712  _dbus_list_clear (&connection->filter_list);
2713 
2714  /* ---- Done with stuff that invokes application callbacks */
2715 
2716  _dbus_object_tree_unref (connection->objects);
2717 
2719  connection->pending_replies = NULL;
2720 
2721  _dbus_list_clear (&connection->filter_list);
2722 
2723  _dbus_list_foreach (&connection->outgoing_messages,
2724  free_outgoing_message,
2725  connection);
2726  _dbus_list_clear (&connection->outgoing_messages);
2727 
2728  _dbus_list_foreach (&connection->incoming_messages,
2730  NULL);
2731  _dbus_list_clear (&connection->incoming_messages);
2732 
2733  _dbus_counter_unref (connection->outgoing_counter);
2734 
2735  _dbus_transport_unref (connection->transport);
2736 
2737  if (connection->disconnect_message_link)
2738  {
2739  DBusMessage *message = connection->disconnect_message_link->data;
2740  dbus_message_unref (message);
2742  }
2743 
2746 
2749 
2751 
2752  _dbus_rmutex_free_at_location (&connection->mutex);
2753 
2754  dbus_free (connection);
2755 }
2756 
2776 void
2778 {
2779  dbus_int32_t old_refcount;
2780 
2781  _dbus_return_if_fail (connection != NULL);
2782  _dbus_return_if_fail (connection->generation == _dbus_current_generation);
2783 
2784  old_refcount = _dbus_atomic_dec (&connection->refcount);
2785 
2786  _dbus_connection_trace_ref (connection, old_refcount, old_refcount - 1,
2787  "unref");
2788 
2789  if (old_refcount == 1)
2790  {
2791 #ifndef DBUS_DISABLE_CHECKS
2792  if (_dbus_transport_get_is_connected (connection->transport))
2793  {
2794  _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",
2795  connection->shareable ?
2796  "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" :
2797  "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
2798  return;
2799  }
2800 #endif
2801  _dbus_connection_last_unref (connection);
2802  }
2803 }
2804 
2805 /*
2806  * Note that the transport can disconnect itself (other end drops us)
2807  * and in that case this function never runs. So this function must
2808  * not do anything more than disconnect the transport and update the
2809  * dispatch status.
2810  *
2811  * If the transport self-disconnects, then we assume someone will
2812  * dispatch the connection to cause the dispatch status update.
2813  */
2814 static void
2815 _dbus_connection_close_possibly_shared_and_unlock (DBusConnection *connection)
2816 {
2817  DBusDispatchStatus status;
2818 
2819  HAVE_LOCK_CHECK (connection);
2820 
2821  _dbus_verbose ("Disconnecting %p\n", connection);
2822 
2823  /* We need to ref because update_dispatch_status_and_unlock will unref
2824  * the connection if it was shared and libdbus was the only remaining
2825  * refcount holder.
2826  */
2827  _dbus_connection_ref_unlocked (connection);
2828 
2829  _dbus_transport_disconnect (connection->transport);
2830 
2831  /* This has the side effect of queuing the disconnect message link
2832  * (unless we don't have enough memory, possibly, so don't assert it).
2833  * After the disconnect message link is queued, dbus_bus_get/dbus_connection_open
2834  * should never again return the newly-disconnected connection.
2835  *
2836  * However, we only unref the shared connection and exit_on_disconnect when
2837  * the disconnect message reaches the head of the message queue,
2838  * NOT when it's first queued.
2839  */
2840  status = _dbus_connection_get_dispatch_status_unlocked (connection);
2841 
2842  /* This calls out to user code */
2843  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
2844 
2845  /* Could also call out to user code */
2846  dbus_connection_unref (connection);
2847 }
2848 
2891 void
2893 {
2894  _dbus_return_if_fail (connection != NULL);
2895  _dbus_return_if_fail (connection->generation == _dbus_current_generation);
2896 
2897  CONNECTION_LOCK (connection);
2898 
2899 #ifndef DBUS_DISABLE_CHECKS
2900  if (connection->shareable)
2901  {
2902  CONNECTION_UNLOCK (connection);
2903 
2904  _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
2905  return;
2906  }
2907 #endif
2908 
2909  _dbus_connection_close_possibly_shared_and_unlock (connection);
2910 }
2911 
2912 static dbus_bool_t
2913 _dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
2914 {
2915  HAVE_LOCK_CHECK (connection);
2916  return _dbus_transport_get_is_connected (connection->transport);
2917 }
2918 
2934 {
2935  dbus_bool_t res;
2936 
2937  _dbus_return_val_if_fail (connection != NULL, FALSE);
2938 
2939  CONNECTION_LOCK (connection);
2940  res = _dbus_connection_get_is_connected_unlocked (connection);
2941  CONNECTION_UNLOCK (connection);
2942 
2943  return res;
2944 }
2945 
2956 {
2957  dbus_bool_t res;
2958 
2959  _dbus_return_val_if_fail (connection != NULL, FALSE);
2960 
2961  CONNECTION_LOCK (connection);
2962  res = _dbus_transport_get_is_authenticated (connection->transport);
2963  CONNECTION_UNLOCK (connection);
2964 
2965  return res;
2966 }
2967 
2990 {
2991  dbus_bool_t res;
2992 
2993  _dbus_return_val_if_fail (connection != NULL, FALSE);
2994 
2995  CONNECTION_LOCK (connection);
2996  res = _dbus_transport_get_is_anonymous (connection->transport);
2997  CONNECTION_UNLOCK (connection);
2998 
2999  return res;
3000 }
3001 
3033 char*
3035 {
3036  char *id;
3037 
3038  _dbus_return_val_if_fail (connection != NULL, NULL);
3039 
3040  CONNECTION_LOCK (connection);
3042  CONNECTION_UNLOCK (connection);
3043 
3044  return id;
3045 }
3046 
3066  int type)
3067 {
3068  _dbus_return_val_if_fail (connection != NULL, FALSE);
3069 
3070  if (!dbus_type_is_valid (type))
3071  return FALSE;
3072 
3073  if (type != DBUS_TYPE_UNIX_FD)
3074  return TRUE;
3075 
3076 #ifdef HAVE_UNIX_FD_PASSING
3077  {
3078  dbus_bool_t b;
3079 
3080  CONNECTION_LOCK(connection);
3082  CONNECTION_UNLOCK(connection);
3083 
3084  return b;
3085  }
3086 #endif
3087 
3088  return FALSE;
3089 }
3090 
3104 void
3106  dbus_bool_t exit_on_disconnect)
3107 {
3108  _dbus_return_if_fail (connection != NULL);
3109 
3110  CONNECTION_LOCK (connection);
3111  connection->exit_on_disconnect = exit_on_disconnect != FALSE;
3112  CONNECTION_UNLOCK (connection);
3113 }
3114 
3126 {
3127  DBusPreallocatedSend *preallocated;
3128 
3129  _dbus_return_val_if_fail (connection != NULL, NULL);
3130 
3131  CONNECTION_LOCK (connection);
3132 
3133  preallocated =
3134  _dbus_connection_preallocate_send_unlocked (connection);
3135 
3136  CONNECTION_UNLOCK (connection);
3137 
3138  return preallocated;
3139 }
3140 
3150 void
3152  DBusPreallocatedSend *preallocated)
3153 {
3154  _dbus_return_if_fail (connection != NULL);
3155  _dbus_return_if_fail (preallocated != NULL);
3156  _dbus_return_if_fail (connection == preallocated->connection);
3157 
3158  _dbus_list_free_link (preallocated->queue_link);
3159  _dbus_counter_unref (preallocated->counter_link->data);
3160  _dbus_list_free_link (preallocated->counter_link);
3161  dbus_free (preallocated);
3162 }
3163 
3176 void
3178  DBusPreallocatedSend *preallocated,
3179  DBusMessage *message,
3180  dbus_uint32_t *client_serial)
3181 {
3182  _dbus_return_if_fail (connection != NULL);
3183  _dbus_return_if_fail (preallocated != NULL);
3184  _dbus_return_if_fail (message != NULL);
3185  _dbus_return_if_fail (preallocated->connection == connection);
3186  _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL ||
3187  dbus_message_get_member (message) != NULL);
3188  _dbus_return_if_fail (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL ||
3189  (dbus_message_get_interface (message) != NULL &&
3190  dbus_message_get_member (message) != NULL));
3191 
3192  CONNECTION_LOCK (connection);
3193 
3194 #ifdef HAVE_UNIX_FD_PASSING
3195 
3196  if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
3197  message->n_unix_fds > 0)
3198  {
3199  /* Refuse to send fds on a connection that cannot handle
3200  them. Unfortunately we cannot return a proper error here, so
3201  the best we can is just return. */
3202  CONNECTION_UNLOCK (connection);
3203  return;
3204  }
3205 
3206 #endif
3207 
3208  _dbus_connection_send_preallocated_and_unlock (connection,
3209  preallocated,
3210  message, client_serial);
3211 }
3212 
3213 static dbus_bool_t
3214 _dbus_connection_send_unlocked_no_update (DBusConnection *connection,
3215  DBusMessage *message,
3216  dbus_uint32_t *client_serial)
3217 {
3218  DBusPreallocatedSend *preallocated;
3219 
3220  _dbus_assert (connection != NULL);
3221  _dbus_assert (message != NULL);
3222 
3223  preallocated = _dbus_connection_preallocate_send_unlocked (connection);
3224  if (preallocated == NULL)
3225  return FALSE;
3226 
3227  _dbus_connection_send_preallocated_unlocked_no_update (connection,
3228  preallocated,
3229  message,
3230  client_serial);
3231  return TRUE;
3232 }
3233 
3263  DBusMessage *message,
3264  dbus_uint32_t *serial)
3265 {
3266  _dbus_return_val_if_fail (connection != NULL, FALSE);
3267  _dbus_return_val_if_fail (message != NULL, FALSE);
3268 
3269  CONNECTION_LOCK (connection);
3270 
3271 #ifdef HAVE_UNIX_FD_PASSING
3272 
3273  if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
3274  message->n_unix_fds > 0)
3275  {
3276  /* Refuse to send fds on a connection that cannot handle
3277  them. Unfortunately we cannot return a proper error here, so
3278  the best we can is just return. */
3279  CONNECTION_UNLOCK (connection);
3280  return FALSE;
3281  }
3282 
3283 #endif
3284 
3285  return _dbus_connection_send_and_unlock (connection,
3286  message,
3287  serial);
3288 }
3289 
3290 static dbus_bool_t
3291 reply_handler_timeout (void *data)
3292 {
3293  DBusConnection *connection;
3294  DBusDispatchStatus status;
3295  DBusPendingCall *pending = data;
3296 
3297  connection = _dbus_pending_call_get_connection_and_lock (pending);
3298  _dbus_connection_ref_unlocked (connection);
3299 
3301  connection);
3305 
3306  _dbus_verbose ("middle\n");
3307  status = _dbus_connection_get_dispatch_status_unlocked (connection);
3308 
3309  /* Unlocks, and calls out to user code */
3310  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3311  dbus_connection_unref (connection);
3312 
3313  return TRUE;
3314 }
3315 
3360  DBusMessage *message,
3361  DBusPendingCall **pending_return,
3362  int timeout_milliseconds)
3363 {
3364  DBusPendingCall *pending;
3365  dbus_int32_t serial = -1;
3366  DBusDispatchStatus status;
3367 
3368  _dbus_return_val_if_fail (connection != NULL, FALSE);
3369  _dbus_return_val_if_fail (message != NULL, FALSE);
3370  _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
3371 
3372  if (pending_return)
3373  *pending_return = NULL;
3374 
3375  CONNECTION_LOCK (connection);
3376 
3377 #ifdef HAVE_UNIX_FD_PASSING
3378 
3379  if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
3380  message->n_unix_fds > 0)
3381  {
3382  /* Refuse to send fds on a connection that cannot handle
3383  them. Unfortunately we cannot return a proper error here, so
3384  the best we can do is return TRUE but leave *pending_return
3385  as NULL. */
3386  CONNECTION_UNLOCK (connection);
3387  return TRUE;
3388  }
3389 
3390 #endif
3391 
3392  if (!_dbus_connection_get_is_connected_unlocked (connection))
3393  {
3394  CONNECTION_UNLOCK (connection);
3395 
3396  return TRUE;
3397  }
3398 
3399  pending = _dbus_pending_call_new_unlocked (connection,
3400  timeout_milliseconds,
3401  reply_handler_timeout);
3402 
3403  if (pending == NULL)
3404  {
3405  CONNECTION_UNLOCK (connection);
3406  return FALSE;
3407  }
3408 
3409  /* Assign a serial to the message */
3410  serial = dbus_message_get_serial (message);
3411  if (serial == 0)
3412  {
3413  serial = _dbus_connection_get_next_client_serial (connection);
3414  dbus_message_set_serial (message, serial);
3415  }
3416 
3417  if (!_dbus_pending_call_set_timeout_error_unlocked (pending, message, serial))
3418  goto error;
3419 
3420  /* Insert the serial in the pending replies hash;
3421  * hash takes a refcount on DBusPendingCall.
3422  * Also, add the timeout.
3423  */
3424  if (!_dbus_connection_attach_pending_call_unlocked (connection,
3425  pending))
3426  goto error;
3427 
3428  if (!_dbus_connection_send_unlocked_no_update (connection, message, NULL))
3429  {
3430  _dbus_connection_detach_pending_call_and_unlock (connection,
3431  pending);
3432  goto error_unlocked;
3433  }
3434 
3435  if (pending_return)
3436  *pending_return = pending; /* hand off refcount */
3437  else
3438  {
3439  _dbus_connection_detach_pending_call_unlocked (connection, pending);
3440  /* we still have a ref to the pending call in this case, we unref
3441  * after unlocking, below
3442  */
3443  }
3444 
3445  status = _dbus_connection_get_dispatch_status_unlocked (connection);
3446 
3447  /* this calls out to user code */
3448  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3449 
3450  if (pending_return == NULL)
3451  dbus_pending_call_unref (pending);
3452 
3453  return TRUE;
3454 
3455  error:
3456  CONNECTION_UNLOCK (connection);
3457  error_unlocked:
3458  dbus_pending_call_unref (pending);
3459  return FALSE;
3460 }
3461 
3494 DBusMessage*
3496  DBusMessage *message,
3497  int timeout_milliseconds,
3498  DBusError *error)
3499 {
3500  DBusMessage *reply;
3501  DBusPendingCall *pending;
3502 
3503  _dbus_return_val_if_fail (connection != NULL, NULL);
3504  _dbus_return_val_if_fail (message != NULL, NULL);
3505  _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
3506  _dbus_return_val_if_error_is_set (error, NULL);
3507 
3508 #ifdef HAVE_UNIX_FD_PASSING
3509 
3510  CONNECTION_LOCK (connection);
3511  if (!_dbus_transport_can_pass_unix_fd(connection->transport) &&
3512  message->n_unix_fds > 0)
3513  {
3514  CONNECTION_UNLOCK (connection);
3515  dbus_set_error(error, DBUS_ERROR_FAILED, "Cannot send file descriptors on this connection.");
3516  return NULL;
3517  }
3518  CONNECTION_UNLOCK (connection);
3519 
3520 #endif
3521 
3522  if (!dbus_connection_send_with_reply (connection, message,
3523  &pending, timeout_milliseconds))
3524  {
3525  _DBUS_SET_OOM (error);
3526  return NULL;
3527  }
3528 
3529  if (pending == NULL)
3530  {
3531  dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Connection is closed");
3532  return NULL;
3533  }
3534 
3535  dbus_pending_call_block (pending);
3536 
3537  reply = dbus_pending_call_steal_reply (pending);
3538  dbus_pending_call_unref (pending);
3539 
3540  /* call_complete_and_unlock() called from pending_call_block() should
3541  * always fill this in.
3542  */
3543  _dbus_assert (reply != NULL);
3544 
3545  if (dbus_set_error_from_message (error, reply))
3546  {
3547  dbus_message_unref (reply);
3548  return NULL;
3549  }
3550  else
3551  return reply;
3552 }
3553 
3562 static DBusDispatchStatus
3563 _dbus_connection_flush_unlocked (DBusConnection *connection, int timeout_milliseconds)
3564 {
3565  /* We have to specify DBUS_ITERATION_DO_READING here because
3566  * otherwise we could have two apps deadlock if they are both doing
3567  * a flush(), and the kernel buffers fill up. This could change the
3568  * dispatch status.
3569  */
3570  DBusDispatchStatus status;
3571  long start_tv_sec, start_tv_usec;
3572  long tv_sec, tv_usec;
3573  int elapsed_milliseconds = 0;
3574 
3575  HAVE_LOCK_CHECK (connection);
3576 
3577  _dbus_get_monotonic_time (&start_tv_sec, &start_tv_usec);
3578 
3579  while (connection->n_outgoing > 0 &&
3580  _dbus_connection_get_is_connected_unlocked (connection))
3581  {
3582  _dbus_verbose ("doing iteration in\n");
3583 
3584  if (timeout_milliseconds >= 0)
3585  {
3586  _dbus_get_monotonic_time (&tv_sec, &tv_usec);
3587  elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
3588  (tv_usec - start_tv_usec) / 1000;
3589 
3590  if (elapsed_milliseconds >= timeout_milliseconds)
3591  break;
3592  }
3593 
3594  HAVE_LOCK_CHECK (connection);
3596  NULL,
3597  DBUS_ITERATION_DO_READING |
3598  DBUS_ITERATION_DO_WRITING |
3599  DBUS_ITERATION_BLOCK,
3600  timeout_milliseconds - elapsed_milliseconds);
3601  }
3602 
3603  HAVE_LOCK_CHECK (connection);
3604  _dbus_verbose ("middle\n");
3605  status = _dbus_connection_get_dispatch_status_unlocked (connection);
3606 
3607  HAVE_LOCK_CHECK (connection);
3608  return status;
3609 }
3610 
3616 void
3618 {
3619  /* We have to specify DBUS_ITERATION_DO_READING here because
3620  * otherwise we could have two apps deadlock if they are both doing
3621  * a flush(), and the kernel buffers fill up. This could change the
3622  * dispatch status.
3623  */
3624  DBusDispatchStatus status;
3625 
3626  _dbus_return_if_fail (connection != NULL);
3627 
3628  CONNECTION_LOCK (connection);
3629 
3630  status = _dbus_connection_flush_unlocked (connection, -1);
3631 
3632  HAVE_LOCK_CHECK (connection);
3633  /* Unlocks and calls out to user code */
3634  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3635 
3636  _dbus_verbose ("end\n");
3637 }
3638 
3649 static dbus_bool_t
3650 _dbus_connection_read_write_dispatch (DBusConnection *connection,
3651  int timeout_milliseconds,
3652  dbus_bool_t dispatch)
3653 {
3654  DBusDispatchStatus dstatus;
3655  dbus_bool_t progress_possible;
3656 
3657  /* Need to grab a ref here in case we're a private connection and
3658  * the user drops the last ref in a handler we call; see bug
3659  * https://bugs.freedesktop.org/show_bug.cgi?id=15635
3660  */
3661  dbus_connection_ref (connection);
3662  dstatus = dbus_connection_get_dispatch_status (connection);
3663 
3664  if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS)
3665  {
3666  _dbus_verbose ("doing dispatch\n");
3667  dbus_connection_dispatch (connection);
3668  CONNECTION_LOCK (connection);
3669  }
3670  else if (dstatus == DBUS_DISPATCH_NEED_MEMORY)
3671  {
3672  _dbus_verbose ("pausing for memory\n");
3673  _dbus_memory_pause_based_on_timeout (timeout_milliseconds);
3674  CONNECTION_LOCK (connection);
3675  }
3676  else
3677  {
3678  CONNECTION_LOCK (connection);
3679  if (_dbus_connection_get_is_connected_unlocked (connection))
3680  {
3681  _dbus_verbose ("doing iteration\n");
3683  NULL,
3684  DBUS_ITERATION_DO_READING |
3685  DBUS_ITERATION_DO_WRITING |
3686  DBUS_ITERATION_BLOCK,
3687  timeout_milliseconds);
3688  }
3689  }
3690 
3691  HAVE_LOCK_CHECK (connection);
3692  /* If we can dispatch, we can make progress until the Disconnected message
3693  * has been processed; if we can only read/write, we can make progress
3694  * as long as the transport is open.
3695  */
3696  if (dispatch)
3697  progress_possible = connection->n_incoming != 0 ||
3698  connection->disconnect_message_link != NULL;
3699  else
3700  progress_possible = _dbus_connection_get_is_connected_unlocked (connection);
3701 
3702  CONNECTION_UNLOCK (connection);
3703 
3704  dbus_connection_unref (connection);
3705 
3706  return progress_possible; /* TRUE if we can make more progress */
3707 }
3708 
3709 
3746  int timeout_milliseconds)
3747 {
3748  _dbus_return_val_if_fail (connection != NULL, FALSE);
3749  _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
3750  return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, TRUE);
3751 }
3752 
3776 dbus_bool_t
3778  int timeout_milliseconds)
3779 {
3780  _dbus_return_val_if_fail (connection != NULL, FALSE);
3781  _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
3782  return _dbus_connection_read_write_dispatch(connection, timeout_milliseconds, FALSE);
3783 }
3784 
3785 /* We need to call this anytime we pop the head of the queue, and then
3786  * update_dispatch_status_and_unlock needs to be called afterward
3787  * which will "process" the disconnected message and set
3788  * disconnected_message_processed.
3789  */
3790 static void
3791 check_disconnected_message_arrived_unlocked (DBusConnection *connection,
3792  DBusMessage *head_of_queue)
3793 {
3794  HAVE_LOCK_CHECK (connection);
3795 
3796  /* checking that the link is NULL is an optimization to avoid the is_signal call */
3797  if (connection->disconnect_message_link == NULL &&
3798  dbus_message_is_signal (head_of_queue,
3800  "Disconnected"))
3801  {
3802  connection->disconnected_message_arrived = TRUE;
3803  }
3804 }
3805 
3825 DBusMessage*
3827 {
3828  DBusDispatchStatus status;
3829  DBusMessage *message;
3830 
3831  _dbus_return_val_if_fail (connection != NULL, NULL);
3832 
3833  _dbus_verbose ("start\n");
3834 
3835  /* this is called for the side effect that it queues
3836  * up any messages from the transport
3837  */
3838  status = dbus_connection_get_dispatch_status (connection);
3839  if (status != DBUS_DISPATCH_DATA_REMAINS)
3840  return NULL;
3841 
3842  CONNECTION_LOCK (connection);
3843 
3844  _dbus_connection_acquire_dispatch (connection);
3845 
3846  /* While a message is outstanding, the dispatch lock is held */
3847  _dbus_assert (connection->message_borrowed == NULL);
3848 
3849  connection->message_borrowed = _dbus_list_get_first (&connection->incoming_messages);
3850 
3851  message = connection->message_borrowed;
3852 
3853  check_disconnected_message_arrived_unlocked (connection, message);
3854 
3855  /* Note that we KEEP the dispatch lock until the message is returned */
3856  if (message == NULL)
3857  _dbus_connection_release_dispatch (connection);
3858 
3859  CONNECTION_UNLOCK (connection);
3860 
3861  _dbus_message_trace_ref (message, -1, -1, "dbus_connection_borrow_message");
3862 
3863  /* We don't update dispatch status until it's returned or stolen */
3864 
3865  return message;
3866 }
3867 
3876 void
3878  DBusMessage *message)
3879 {
3880  DBusDispatchStatus status;
3881 
3882  _dbus_return_if_fail (connection != NULL);
3883  _dbus_return_if_fail (message != NULL);
3884  _dbus_return_if_fail (message == connection->message_borrowed);
3885  _dbus_return_if_fail (connection->dispatch_acquired);
3886 
3887  CONNECTION_LOCK (connection);
3888 
3889  _dbus_assert (message == connection->message_borrowed);
3890 
3891  connection->message_borrowed = NULL;
3892 
3893  _dbus_connection_release_dispatch (connection);
3894 
3895  status = _dbus_connection_get_dispatch_status_unlocked (connection);
3896  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3897 
3898  _dbus_message_trace_ref (message, -1, -1, "dbus_connection_return_message");
3899 }
3900 
3910 void
3912  DBusMessage *message)
3913 {
3914  DBusMessage *pop_message;
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  pop_message = _dbus_list_pop_first (&connection->incoming_messages);
3927  _dbus_assert (message == pop_message);
3928  (void) pop_message; /* unused unless asserting */
3929 
3930  connection->n_incoming -= 1;
3931 
3932  _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
3933  message, connection->n_incoming);
3934 
3935  connection->message_borrowed = NULL;
3936 
3937  _dbus_connection_release_dispatch (connection);
3938 
3939  status = _dbus_connection_get_dispatch_status_unlocked (connection);
3940  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
3941  _dbus_message_trace_ref (message, -1, -1,
3942  "dbus_connection_steal_borrowed_message");
3943 }
3944 
3945 /* See dbus_connection_pop_message, but requires the caller to own
3946  * the lock before calling. May drop the lock while running.
3947  */
3948 static DBusList*
3949 _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
3950 {
3951  HAVE_LOCK_CHECK (connection);
3952 
3953  _dbus_assert (connection->message_borrowed == NULL);
3954 
3955  if (connection->n_incoming > 0)
3956  {
3957  DBusList *link;
3958 
3959  link = _dbus_list_pop_first_link (&connection->incoming_messages);
3960  connection->n_incoming -= 1;
3961 
3962  _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
3963  link->data,
3965  dbus_message_get_path (link->data) ?
3966  dbus_message_get_path (link->data) :
3967  "no path",
3970  "no interface",
3971  dbus_message_get_member (link->data) ?
3972  dbus_message_get_member (link->data) :
3973  "no member",
3975  connection, connection->n_incoming);
3976 
3977  _dbus_message_trace_ref (link->data, -1, -1,
3978  "_dbus_connection_pop_message_link_unlocked");
3979 
3980  check_disconnected_message_arrived_unlocked (connection, link->data);
3981 
3982  return link;
3983  }
3984  else
3985  return NULL;
3986 }
3987 
3988 /* See dbus_connection_pop_message, but requires the caller to own
3989  * the lock before calling. May drop the lock while running.
3990  */
3991 static DBusMessage*
3992 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
3993 {
3994  DBusList *link;
3995 
3996  HAVE_LOCK_CHECK (connection);
3997 
3998  link = _dbus_connection_pop_message_link_unlocked (connection);
3999 
4000  if (link != NULL)
4001  {
4002  DBusMessage *message;
4003 
4004  message = link->data;
4005 
4006  _dbus_list_free_link (link);
4007 
4008  return message;
4009  }
4010  else
4011  return NULL;
4012 }
4013 
4014 static void
4015 _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
4016  DBusList *message_link)
4017 {
4018  HAVE_LOCK_CHECK (connection);
4019 
4020  _dbus_assert (message_link != NULL);
4021  /* You can't borrow a message while a link is outstanding */
4022  _dbus_assert (connection->message_borrowed == NULL);
4023  /* We had to have the dispatch lock across the pop/putback */
4024  _dbus_assert (connection->dispatch_acquired);
4025 
4027  message_link);
4028  connection->n_incoming += 1;
4029 
4030  _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n",
4031  message_link->data,
4033  dbus_message_get_interface (message_link->data) ?
4034  dbus_message_get_interface (message_link->data) :
4035  "no interface",
4036  dbus_message_get_member (message_link->data) ?
4037  dbus_message_get_member (message_link->data) :
4038  "no member",
4039  dbus_message_get_signature (message_link->data),
4040  connection, connection->n_incoming);
4041 
4042  _dbus_message_trace_ref (message_link->data, -1, -1,
4043  "_dbus_connection_putback_message_link_unlocked");
4044 }
4045 
4065 DBusMessage*
4067 {
4068  DBusMessage *message;
4069  DBusDispatchStatus status;
4070 
4071  _dbus_verbose ("start\n");
4072 
4073  /* this is called for the side effect that it queues
4074  * up any messages from the transport
4075  */
4076  status = dbus_connection_get_dispatch_status (connection);
4077  if (status != DBUS_DISPATCH_DATA_REMAINS)
4078  return NULL;
4079 
4080  CONNECTION_LOCK (connection);
4081  _dbus_connection_acquire_dispatch (connection);
4082  HAVE_LOCK_CHECK (connection);
4083 
4084  message = _dbus_connection_pop_message_unlocked (connection);
4085 
4086  _dbus_verbose ("Returning popped message %p\n", message);
4087 
4088  _dbus_connection_release_dispatch (connection);
4089 
4090  status = _dbus_connection_get_dispatch_status_unlocked (connection);
4091  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
4092 
4093  return message;
4094 }
4095 
4103 static void
4104 _dbus_connection_acquire_dispatch (DBusConnection *connection)
4105 {
4106  HAVE_LOCK_CHECK (connection);
4107 
4108  _dbus_connection_ref_unlocked (connection);
4109  CONNECTION_UNLOCK (connection);
4110 
4111  _dbus_verbose ("locking dispatch_mutex\n");
4112  _dbus_cmutex_lock (connection->dispatch_mutex);
4113 
4114  while (connection->dispatch_acquired)
4115  {
4116  _dbus_verbose ("waiting for dispatch to be acquirable\n");
4117  _dbus_condvar_wait (connection->dispatch_cond,
4118  connection->dispatch_mutex);
4119  }
4120 
4121  _dbus_assert (!connection->dispatch_acquired);
4122 
4123  connection->dispatch_acquired = TRUE;
4124 
4125  _dbus_verbose ("unlocking dispatch_mutex\n");
4126  _dbus_cmutex_unlock (connection->dispatch_mutex);
4127 
4128  CONNECTION_LOCK (connection);
4129  _dbus_connection_unref_unlocked (connection);
4130 }
4131 
4139 static void
4140 _dbus_connection_release_dispatch (DBusConnection *connection)
4141 {
4142  HAVE_LOCK_CHECK (connection);
4143 
4144  _dbus_verbose ("locking dispatch_mutex\n");
4145  _dbus_cmutex_lock (connection->dispatch_mutex);
4146 
4147  _dbus_assert (connection->dispatch_acquired);
4148 
4149  connection->dispatch_acquired = FALSE;
4150  _dbus_condvar_wake_one (connection->dispatch_cond);
4151 
4152  _dbus_verbose ("unlocking dispatch_mutex\n");
4153  _dbus_cmutex_unlock (connection->dispatch_mutex);
4154 }
4155 
4156 static void
4157 _dbus_connection_failed_pop (DBusConnection *connection,
4158  DBusList *message_link)
4159 {
4161  message_link);
4162  connection->n_incoming += 1;
4163 }
4164 
4165 /* Note this may be called multiple times since we don't track whether we already did it */
4166 static void
4167 notify_disconnected_unlocked (DBusConnection *connection)
4168 {
4169  HAVE_LOCK_CHECK (connection);
4170 
4171  /* Set the weakref in dbus-bus.c to NULL, so nobody will get a disconnected
4172  * connection from dbus_bus_get(). We make the same guarantee for
4173  * dbus_connection_open() but in a different way since we don't want to
4174  * unref right here; we instead check for connectedness before returning
4175  * the connection from the hash.
4176  */
4178 
4179  /* Dump the outgoing queue, we aren't going to be able to
4180  * send it now, and we'd like accessors like
4181  * dbus_connection_get_outgoing_size() to be accurate.
4182  */
4183  if (connection->n_outgoing > 0)
4184  {
4185  DBusList *link;
4186 
4187  _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n",
4188  connection->n_outgoing);
4189 
4190  while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
4191  {
4192  _dbus_connection_message_sent_unlocked (connection, link->data);
4193  }
4194  }
4195 }
4196 
4197 /* Note this may be called multiple times since we don't track whether we already did it */
4198 static DBusDispatchStatus
4199 notify_disconnected_and_dispatch_complete_unlocked (DBusConnection *connection)
4200 {
4201  HAVE_LOCK_CHECK (connection);
4202 
4203  if (connection->disconnect_message_link != NULL)
4204  {
4205  _dbus_verbose ("Sending disconnect message\n");
4206 
4207  /* If we have pending calls, queue their timeouts - we want the Disconnected
4208  * to be the last message, after these timeouts.
4209  */
4210  connection_timeout_and_complete_all_pending_calls_unlocked (connection);
4211 
4212  /* We haven't sent the disconnect message already,
4213  * and all real messages have been queued up.
4214  */
4216  connection->disconnect_message_link);
4217  connection->disconnect_message_link = NULL;
4218 
4220  }
4221 
4222  return DBUS_DISPATCH_COMPLETE;
4223 }
4224 
4225 static DBusDispatchStatus
4226 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
4227 {
4228  HAVE_LOCK_CHECK (connection);
4229 
4230  if (connection->n_incoming > 0)
4232  else if (!_dbus_transport_queue_messages (connection->transport))
4234  else
4235  {
4236  DBusDispatchStatus status;
4237  dbus_bool_t is_connected;
4238 
4239  status = _dbus_transport_get_dispatch_status (connection->transport);
4240  is_connected = _dbus_transport_get_is_connected (connection->transport);
4241 
4242  _dbus_verbose ("dispatch status = %s is_connected = %d\n",
4243  DISPATCH_STATUS_NAME (status), is_connected);
4244 
4245  if (!is_connected)
4246  {
4247  /* It's possible this would be better done by having an explicit
4248  * notification from _dbus_transport_disconnect() that would
4249  * synchronously do this, instead of waiting for the next dispatch
4250  * status check. However, probably not good to change until it causes
4251  * a problem.
4252  */
4253  notify_disconnected_unlocked (connection);
4254 
4255  /* I'm not sure this is needed; the idea is that we want to
4256  * queue the Disconnected only after we've read all the
4257  * messages, but if we're disconnected maybe we are guaranteed
4258  * to have read them all ?
4259  */
4260  if (status == DBUS_DISPATCH_COMPLETE)
4261  status = notify_disconnected_and_dispatch_complete_unlocked (connection);
4262  }
4263 
4264  if (status != DBUS_DISPATCH_COMPLETE)
4265  return status;
4266  else if (connection->n_incoming > 0)
4268  else
4269  return DBUS_DISPATCH_COMPLETE;
4270  }
4271 }
4272 
4273 static void
4274 _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
4275  DBusDispatchStatus new_status)
4276 {
4277  dbus_bool_t changed;
4278  DBusDispatchStatusFunction function;
4279  void *data;
4280 
4281  HAVE_LOCK_CHECK (connection);
4282 
4283  _dbus_connection_ref_unlocked (connection);
4284 
4285  changed = new_status != connection->last_dispatch_status;
4286 
4287  connection->last_dispatch_status = new_status;
4288 
4289  function = connection->dispatch_status_function;
4290  data = connection->dispatch_status_data;
4291 
4292  if (connection->disconnected_message_arrived &&
4293  !connection->disconnected_message_processed)
4294  {
4295  connection->disconnected_message_processed = TRUE;
4296 
4297  /* this does an unref, but we have a ref
4298  * so we should not run the finalizer here
4299  * inside the lock.
4300  */
4301  connection_forget_shared_unlocked (connection);
4302 
4303  if (connection->exit_on_disconnect)
4304  {
4305  CONNECTION_UNLOCK (connection);
4306 
4307  _dbus_verbose ("Exiting on Disconnected signal\n");
4308  _dbus_exit (1);
4309  _dbus_assert_not_reached ("Call to exit() returned");
4310  }
4311  }
4312 
4313  /* We drop the lock */
4314  CONNECTION_UNLOCK (connection);
4315 
4316  if (changed && function)
4317  {
4318  _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
4319  connection, new_status,
4320  DISPATCH_STATUS_NAME (new_status));
4321  (* function) (connection, new_status, data);
4322  }
4323 
4324  dbus_connection_unref (connection);
4325 }
4326 
4354 {
4355  DBusDispatchStatus status;
4356 
4357  _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
4358 
4359  _dbus_verbose ("start\n");
4360 
4361  CONNECTION_LOCK (connection);
4362 
4363  status = _dbus_connection_get_dispatch_status_unlocked (connection);
4364 
4365  CONNECTION_UNLOCK (connection);
4366 
4367  return status;
4368 }
4369 
4373 static DBusHandlerResult
4374 _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
4375  DBusMessage *message)
4376 {
4377  dbus_bool_t sent = FALSE;
4378  DBusMessage *ret = NULL;
4379  DBusList *expire_link;
4380 
4381  if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
4382  {
4383  /* This means we're letting the bus route this message */
4385  }
4386 
4388  {
4390  }
4391 
4392  /* Preallocate a linked-list link, so that if we need to dispose of a
4393  * message, we can attach it to the expired list */
4394  expire_link = _dbus_list_alloc_link (NULL);
4395 
4396  if (!expire_link)
4398 
4399  if (dbus_message_is_method_call (message,
4401  "Ping"))
4402  {
4403  ret = dbus_message_new_method_return (message);
4404  if (ret == NULL)
4405  goto out;
4406 
4407  sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
4408  }
4409  else if (dbus_message_is_method_call (message,
4411  "GetMachineId"))
4412  {
4413  DBusString uuid;
4414 
4415  ret = dbus_message_new_method_return (message);
4416  if (ret == NULL)
4417  goto out;
4418 
4419  _dbus_string_init (&uuid);
4421  {
4422  const char *v_STRING = _dbus_string_get_const_data (&uuid);
4423  if (dbus_message_append_args (ret,
4424  DBUS_TYPE_STRING, &v_STRING,
4426  {
4427  sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
4428  }
4429  }
4430  _dbus_string_free (&uuid);
4431  }
4432  else
4433  {
4434  /* We need to bounce anything else with this interface, otherwise apps
4435  * could start extending the interface and when we added extensions
4436  * here to DBusConnection we'd break those apps.
4437  */
4438  ret = dbus_message_new_error (message,
4440  "Unknown method invoked on org.freedesktop.DBus.Peer interface");
4441  if (ret == NULL)
4442  goto out;
4443 
4444  sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
4445  }
4446 
4447 out:
4448  if (ret == NULL)
4449  {
4450  _dbus_list_free_link (expire_link);
4451  }
4452  else
4453  {
4454  /* It'll be safe to unref the reply when we unlock */
4455  expire_link->data = ret;
4456  _dbus_list_prepend_link (&connection->expired_messages, expire_link);
4457  }
4458 
4459  if (!sent)
4461 
4463 }
4464 
4471 static DBusHandlerResult
4472 _dbus_connection_run_builtin_filters_unlocked_no_update (DBusConnection *connection,
4473  DBusMessage *message)
4474 {
4475  /* We just run one filter for now but have the option to run more
4476  if the spec calls for it in the future */
4477 
4478  return _dbus_connection_peer_filter_unlocked_no_update (connection, message);
4479 }
4480 
4525 {
4526  DBusMessage *message;
4527  DBusList *link, *filter_list_copy, *message_link;
4528  DBusHandlerResult result;
4529  DBusPendingCall *pending;
4530  dbus_int32_t reply_serial;
4531  DBusDispatchStatus status;
4532  dbus_bool_t found_object;
4533 
4534  _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
4535 
4536  _dbus_verbose ("\n");
4537 
4538  CONNECTION_LOCK (connection);
4539  status = _dbus_connection_get_dispatch_status_unlocked (connection);
4540  if (status != DBUS_DISPATCH_DATA_REMAINS)
4541  {
4542  /* unlocks and calls out to user code */
4543  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
4544  return status;
4545  }
4546 
4547  /* We need to ref the connection since the callback could potentially
4548  * drop the last ref to it
4549  */
4550  _dbus_connection_ref_unlocked (connection);
4551 
4552  _dbus_connection_acquire_dispatch (connection);
4553  HAVE_LOCK_CHECK (connection);
4554 
4555  message_link = _dbus_connection_pop_message_link_unlocked (connection);
4556  if (message_link == NULL)
4557  {
4558  /* another thread dispatched our stuff */
4559 
4560  _dbus_verbose ("another thread dispatched message (during acquire_dispatch above)\n");
4561 
4562  _dbus_connection_release_dispatch (connection);
4563 
4564  status = _dbus_connection_get_dispatch_status_unlocked (connection);
4565 
4566  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
4567 
4568  dbus_connection_unref (connection);
4569 
4570  return status;
4571  }
4572 
4573  message = message_link->data;
4574 
4575  _dbus_verbose (" dispatching message %p (%s %s %s '%s')\n",
4576  message,
4578  dbus_message_get_interface (message) ?
4579  dbus_message_get_interface (message) :
4580  "no interface",
4581  dbus_message_get_member (message) ?
4582  dbus_message_get_member (message) :
4583  "no member",
4584  dbus_message_get_signature (message));
4585 
4587 
4588  /* Pending call handling must be first, because if you do
4589  * dbus_connection_send_with_reply_and_block() or
4590  * dbus_pending_call_block() then no handlers/filters will be run on
4591  * the reply. We want consistent semantics in the case where we
4592  * dbus_connection_dispatch() the reply.
4593  */
4594 
4595  reply_serial = dbus_message_get_reply_serial (message);
4596  pending = _dbus_hash_table_lookup_int (connection->pending_replies,
4597  reply_serial);
4598  if (pending)
4599  {
4600  _dbus_verbose ("Dispatching a pending reply\n");
4601  complete_pending_call_and_unlock (connection, pending, message);
4602  pending = NULL; /* it's probably unref'd */
4603 
4604  CONNECTION_LOCK (connection);
4605  _dbus_verbose ("pending call completed in dispatch\n");
4606  result = DBUS_HANDLER_RESULT_HANDLED;
4607  goto out;
4608  }
4609 
4610  result = _dbus_connection_run_builtin_filters_unlocked_no_update (connection, message);
4612  goto out;
4613 
4614  if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
4615  {
4616  _dbus_connection_release_dispatch (connection);
4617  HAVE_LOCK_CHECK (connection);
4618 
4619  _dbus_connection_failed_pop (connection, message_link);
4620 
4621  /* unlocks and calls user code */
4622  _dbus_connection_update_dispatch_status_and_unlock (connection,
4624  dbus_connection_unref (connection);
4625 
4627  }
4628 
4629  _dbus_list_foreach (&filter_list_copy,
4630  (DBusForeachFunction)_dbus_message_filter_ref,
4631  NULL);
4632 
4633  /* We're still protected from dispatch() reentrancy here
4634  * since we acquired the dispatcher
4635  */
4636  CONNECTION_UNLOCK (connection);
4637 
4638  link = _dbus_list_get_first_link (&filter_list_copy);
4639  while (link != NULL)
4640  {
4641  DBusMessageFilter *filter = link->data;
4642  DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
4643 
4644  if (filter->function == NULL)
4645  {
4646  _dbus_verbose (" filter was removed in a callback function\n");
4647  link = next;
4648  continue;
4649  }
4650 
4651  _dbus_verbose (" running filter on message %p\n", message);
4652  result = (* filter->function) (connection, message, filter->user_data);
4653 
4655  break;
4656 
4657  link = next;
4658  }
4659 
4660  _dbus_list_foreach (&filter_list_copy,
4661  (DBusForeachFunction)_dbus_message_filter_unref,
4662  NULL);
4663  _dbus_list_clear (&filter_list_copy);
4664 
4665  CONNECTION_LOCK (connection);
4666 
4667  if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
4668  {
4669  _dbus_verbose ("No memory\n");
4670  goto out;
4671  }
4672  else if (result == DBUS_HANDLER_RESULT_HANDLED)
4673  {
4674  _dbus_verbose ("filter handled message in dispatch\n");
4675  goto out;
4676  }
4677 
4678  /* We're still protected from dispatch() reentrancy here
4679  * since we acquired the dispatcher
4680  */
4681  _dbus_verbose (" running object path dispatch on message %p (%s %s %s '%s')\n",
4682  message,
4684  dbus_message_get_interface (message) ?
4685  dbus_message_get_interface (message) :
4686  "no interface",
4687  dbus_message_get_member (message) ?
4688  dbus_message_get_member (message) :
4689  "no member",
4690  dbus_message_get_signature (message));
4691 
4692  HAVE_LOCK_CHECK (connection);
4693  result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
4694  message,
4695  &found_object);
4696 
4697  CONNECTION_LOCK (connection);
4698 
4700  {
4701  _dbus_verbose ("object tree handled message in dispatch\n");
4702  goto out;
4703  }
4704 
4706  {
4707  DBusMessage *reply;
4708  DBusString str;
4709  DBusPreallocatedSend *preallocated;
4710  DBusList *expire_link;
4711 
4712  _dbus_verbose (" sending error %s\n",
4714 
4715  if (!_dbus_string_init (&str))
4716  {
4718  _dbus_verbose ("no memory for error string in dispatch\n");
4719  goto out;
4720  }
4721 
4722  if (!_dbus_string_append_printf (&str,
4723  "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist\n",
4724  dbus_message_get_member (message),
4725  dbus_message_get_signature (message),
4726  dbus_message_get_interface (message)))
4727  {
4728  _dbus_string_free (&str);
4730  _dbus_verbose ("no memory for error string in dispatch\n");
4731  goto out;
4732  }
4733 
4734  reply = dbus_message_new_error (message,
4737  _dbus_string_free (&str);
4738 
4739  if (reply == NULL)
4740  {
4742  _dbus_verbose ("no memory for error reply in dispatch\n");
4743  goto out;
4744  }
4745 
4746  expire_link = _dbus_list_alloc_link (reply);
4747 
4748  if (expire_link == NULL)
4749  {
4750  dbus_message_unref (reply);
4752  _dbus_verbose ("no memory for error send in dispatch\n");
4753  goto out;
4754  }
4755 
4756  preallocated = _dbus_connection_preallocate_send_unlocked (connection);
4757 
4758  if (preallocated == NULL)
4759  {
4760  _dbus_list_free_link (expire_link);
4761  /* It's OK that this is finalized, because it hasn't been seen by
4762  * anything that could attach user callbacks */
4763  dbus_message_unref (reply);
4765  _dbus_verbose ("no memory for error send in dispatch\n");
4766  goto out;
4767  }
4768 
4769  _dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
4770  reply, NULL);
4771  /* reply will be freed when we release the lock */
4772  _dbus_list_prepend_link (&connection->expired_messages, expire_link);
4773 
4774  result = DBUS_HANDLER_RESULT_HANDLED;
4775  }
4776 
4777  _dbus_verbose (" done dispatching %p (%s %s %s '%s') on connection %p\n", message,
4779  dbus_message_get_interface (message) ?
4780  dbus_message_get_interface (message) :
4781  "no interface",
4782  dbus_message_get_member (message) ?
4783  dbus_message_get_member (message) :
4784  "no member",
4785  dbus_message_get_signature (message),
4786  connection);
4787 
4788  out:
4789  if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
4790  {
4791  _dbus_verbose ("out of memory\n");
4792 
4793  /* Put message back, and we'll start over.
4794  * Yes this means handlers must be idempotent if they
4795  * don't return HANDLED; c'est la vie.
4796  */
4797  _dbus_connection_putback_message_link_unlocked (connection,
4798  message_link);
4799  /* now we don't want to free them */
4800  message_link = NULL;
4801  message = NULL;
4802  }
4803  else
4804  {
4805  _dbus_verbose (" ... done dispatching\n");
4806  }
4807 
4808  _dbus_connection_release_dispatch (connection);
4809  HAVE_LOCK_CHECK (connection);
4810 
4811  if (message != NULL)
4812  {
4813  /* We don't want this message to count in maximum message limits when
4814  * computing the dispatch status, below. We have to drop the lock
4815  * temporarily, because finalizing a message can trigger callbacks.
4816  *
4817  * We have a reference to the connection, and we don't use any cached
4818  * pointers to the connection's internals below this point, so it should
4819  * be safe to drop the lock and take it back. */
4820  CONNECTION_UNLOCK (connection);
4821  dbus_message_unref (message);
4822  CONNECTION_LOCK (connection);
4823  }
4824 
4825  if (message_link != NULL)
4826  _dbus_list_free_link (message_link);
4827 
4828  _dbus_verbose ("before final status update\n");
4829  status = _dbus_connection_get_dispatch_status_unlocked (connection);
4830 
4831  /* unlocks and calls user code */
4832  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
4833 
4834  dbus_connection_unref (connection);
4835 
4836  return status;
4837 }
4838 
4902  DBusAddWatchFunction add_function,
4903  DBusRemoveWatchFunction remove_function,
4904  DBusWatchToggledFunction toggled_function,
4905  void *data,
4906  DBusFreeFunction free_data_function)
4907 {
4908  dbus_bool_t retval;
4909 
4910  _dbus_return_val_if_fail (connection != NULL, FALSE);
4911 
4912  CONNECTION_LOCK (connection);
4913 
4914  retval = _dbus_watch_list_set_functions (connection->watches,
4915  add_function, remove_function,
4916  toggled_function,
4917  data, free_data_function);
4918 
4919  CONNECTION_UNLOCK (connection);
4920 
4921  return retval;
4922 }
4923 
4965  DBusAddTimeoutFunction add_function,
4966  DBusRemoveTimeoutFunction remove_function,
4967  DBusTimeoutToggledFunction toggled_function,
4968  void *data,
4969  DBusFreeFunction free_data_function)
4970 {
4971  dbus_bool_t retval;
4972 
4973  _dbus_return_val_if_fail (connection != NULL, FALSE);
4974 
4975  CONNECTION_LOCK (connection);
4976 
4977  retval = _dbus_timeout_list_set_functions (connection->timeouts,
4978  add_function, remove_function,
4979  toggled_function,
4980  data, free_data_function);
4981 
4982  CONNECTION_UNLOCK (connection);
4983 
4984  return retval;
4985 }
4986 
5001 void
5003  DBusWakeupMainFunction wakeup_main_function,
5004  void *data,
5005  DBusFreeFunction free_data_function)
5006 {
5007  void *old_data;
5008  DBusFreeFunction old_free_data;
5009 
5010  _dbus_return_if_fail (connection != NULL);
5011 
5012  CONNECTION_LOCK (connection);
5013  old_data = connection->wakeup_main_data;
5014  old_free_data = connection->free_wakeup_main_data;
5015 
5016  connection->wakeup_main_function = wakeup_main_function;
5017  connection->wakeup_main_data = data;
5018  connection->free_wakeup_main_data = free_data_function;
5019 
5020  CONNECTION_UNLOCK (connection);
5021 
5022  /* Callback outside the lock */
5023  if (old_free_data)
5024  (*old_free_data) (old_data);
5025 }
5026 
5047 void
5049  DBusDispatchStatusFunction function,
5050  void *data,
5051  DBusFreeFunction free_data_function)
5052 {
5053  void *old_data;
5054  DBusFreeFunction old_free_data;
5055 
5056  _dbus_return_if_fail (connection != NULL);
5057 
5058  CONNECTION_LOCK (connection);
5059  old_data = connection->dispatch_status_data;
5060  old_free_data = connection->free_dispatch_status_data;
5061 
5062  connection->dispatch_status_function = function;
5063  connection->dispatch_status_data = data;
5064  connection->free_dispatch_status_data = free_data_function;
5065 
5066  CONNECTION_UNLOCK (connection);
5067 
5068  /* Callback outside the lock */
5069  if (old_free_data)
5070  (*old_free_data) (old_data);
5071 }
5072 
5094  int *fd)
5095 {
5096  _dbus_return_val_if_fail (connection != NULL, FALSE);
5097  _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
5098 
5099 #ifdef DBUS_WIN
5100  /* FIXME do this on a lower level */
5101  return FALSE;
5102 #endif
5103 
5104  return dbus_connection_get_socket(connection, fd);
5105 }
5106 
5124  int *fd)
5125 {
5126  dbus_bool_t retval;
5127 
5128  _dbus_return_val_if_fail (connection != NULL, FALSE);
5129  _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
5130 
5131  CONNECTION_LOCK (connection);
5132 
5133  retval = _dbus_transport_get_socket_fd (connection->transport,
5134  fd);
5135 
5136  CONNECTION_UNLOCK (connection);
5137 
5138  return retval;
5139 }
5140 
5141 
5166  unsigned long *uid)
5167 {
5168  dbus_bool_t result;
5169 
5170  _dbus_return_val_if_fail (connection != NULL, FALSE);
5171  _dbus_return_val_if_fail (uid != NULL, FALSE);
5172 
5173  CONNECTION_LOCK (connection);
5174 
5176  result = FALSE;
5177  else
5178  result = _dbus_transport_get_unix_user (connection->transport,
5179  uid);
5180 
5181 #ifdef DBUS_WIN
5182  _dbus_assert (!result);
5183 #endif
5184 
5185  CONNECTION_UNLOCK (connection);
5186 
5187  return result;
5188 }
5189 
5202  unsigned long *pid)
5203 {
5204  dbus_bool_t result;
5205 
5206  _dbus_return_val_if_fail (connection != NULL, FALSE);
5207  _dbus_return_val_if_fail (pid != NULL, FALSE);
5208 
5209  CONNECTION_LOCK (connection);
5210 
5212  result = FALSE;
5213  else
5214  result = _dbus_transport_get_unix_process_id (connection->transport,
5215  pid);
5216 
5217  CONNECTION_UNLOCK (connection);
5218 
5219  return result;
5220 }
5221 
5234  void **data,
5235  dbus_int32_t *data_size)
5236 {
5237  dbus_bool_t result;
5238 
5239  _dbus_return_val_if_fail (connection != NULL, FALSE);
5240  _dbus_return_val_if_fail (data != NULL, FALSE);
5241  _dbus_return_val_if_fail (data_size != NULL, FALSE);
5242 
5243  CONNECTION_LOCK (connection);
5244 
5246  result = FALSE;
5247  else
5249  data,
5250  data_size);
5251  CONNECTION_UNLOCK (connection);
5252 
5253  return result;
5254 }
5255 
5278 void
5280  DBusAllowUnixUserFunction function,
5281  void *data,
5282  DBusFreeFunction free_data_function)
5283 {
5284  void *old_data = NULL;
5285  DBusFreeFunction old_free_function = NULL;
5286 
5287  _dbus_return_if_fail (connection != NULL);
5288 
5289  CONNECTION_LOCK (connection);
5291  function, data, free_data_function,
5292  &old_data, &old_free_function);
5293  CONNECTION_UNLOCK (connection);
5294 
5295  if (old_free_function != NULL)
5296  (* old_free_function) (old_data);
5297 }
5298 
5332  char **windows_sid_p)
5333 {
5334  dbus_bool_t result;
5335 
5336  _dbus_return_val_if_fail (connection != NULL, FALSE);
5337  _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
5338 
5339  CONNECTION_LOCK (connection);
5340 
5342  result = FALSE;
5343  else
5344  result = _dbus_transport_get_windows_user (connection->transport,
5345  windows_sid_p);
5346 
5347 #ifdef DBUS_UNIX
5348  _dbus_assert (!result);
5349 #endif
5350 
5351  CONNECTION_UNLOCK (connection);
5352 
5353  return result;
5354 }
5355 
5377 void
5380  void *data,
5381  DBusFreeFunction free_data_function)
5382 {
5383  void *old_data = NULL;
5384  DBusFreeFunction old_free_function = NULL;
5385 
5386  _dbus_return_if_fail (connection != NULL);
5387 
5388  CONNECTION_LOCK (connection);
5390  function, data, free_data_function,
5391  &old_data, &old_free_function);
5392  CONNECTION_UNLOCK (connection);
5393 
5394  if (old_free_function != NULL)
5395  (* old_free_function) (old_data);
5396 }
5397 
5424 void
5426  dbus_bool_t value)
5427 {
5428  _dbus_return_if_fail (connection != NULL);
5429 
5430  CONNECTION_LOCK (connection);
5431  _dbus_transport_set_allow_anonymous (connection->transport, value);
5432  CONNECTION_UNLOCK (connection);
5433 }
5434 
5452 void
5454  dbus_bool_t value)
5455 {
5456  _dbus_return_if_fail (connection != NULL);
5457 
5458  CONNECTION_LOCK (connection);
5459  connection->route_peer_messages = TRUE;
5460  CONNECTION_UNLOCK (connection);
5461 }
5462 
5486  DBusHandleMessageFunction function,
5487  void *user_data,
5488  DBusFreeFunction free_data_function)
5489 {
5490  DBusMessageFilter *filter;
5491 
5492  _dbus_return_val_if_fail (connection != NULL, FALSE);
5493  _dbus_return_val_if_fail (function != NULL, FALSE);
5494 
5495  filter = dbus_new0 (DBusMessageFilter, 1);
5496  if (filter == NULL)
5497  return FALSE;
5498 
5499  _dbus_atomic_inc (&filter->refcount);
5500 
5501  CONNECTION_LOCK (connection);
5502 
5503  if (!_dbus_list_append (&connection->filter_list,
5504  filter))
5505  {
5506  _dbus_message_filter_unref (filter);
5507  CONNECTION_UNLOCK (connection);
5508  return FALSE;
5509  }
5510 
5511  /* Fill in filter after all memory allocated,
5512  * so we don't run the free_user_data_function
5513  * if the add_filter() fails
5514  */
5515 
5516  filter->function = function;
5517  filter->user_data = user_data;
5518  filter->free_user_data_function = free_data_function;
5519 
5520  CONNECTION_UNLOCK (connection);
5521  return TRUE;
5522 }
5523 
5536 void
5538  DBusHandleMessageFunction function,
5539  void *user_data)
5540 {
5541  DBusList *link;
5542  DBusMessageFilter *filter;
5543 
5544  _dbus_return_if_fail (connection != NULL);
5545  _dbus_return_if_fail (function != NULL);
5546 
5547  CONNECTION_LOCK (connection);
5548 
5549  filter = NULL;
5550 
5551  link = _dbus_list_get_last_link (&connection->filter_list);
5552  while (link != NULL)
5553  {
5554  filter = link->data;
5555 
5556  if (filter->function == function &&
5557  filter->user_data == user_data)
5558  {
5559  _dbus_list_remove_link (&connection->filter_list, link);
5560  filter->function = NULL;
5561 
5562  break;
5563  }
5564 
5565  link = _dbus_list_get_prev_link (&connection->filter_list, link);
5566  filter = NULL;
5567  }
5568 
5569  CONNECTION_UNLOCK (connection);
5570 
5571 #ifndef DBUS_DISABLE_CHECKS
5572  if (filter == NULL)
5573  {
5574  _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
5575  function, user_data);
5576  return;
5577  }
5578 #endif
5579 
5580  /* Call application code */
5581  if (filter->free_user_data_function)
5582  (* filter->free_user_data_function) (filter->user_data);
5583 
5584  filter->free_user_data_function = NULL;
5585  filter->user_data = NULL;
5586 
5587  _dbus_message_filter_unref (filter);
5588 }
5589 
5605 static dbus_bool_t
5606 _dbus_connection_register_object_path (DBusConnection *connection,
5607  dbus_bool_t fallback,
5608  const char *path,
5609  const DBusObjectPathVTable *vtable,
5610  void *user_data,
5611  DBusError *error)
5612 {
5613  char **decomposed_path;
5614  dbus_bool_t retval;
5615 
5616  if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
5617  return FALSE;
5618 
5619  CONNECTION_LOCK (connection);
5620 
5621  retval = _dbus_object_tree_register (connection->objects,
5622  fallback,
5623  (const char **) decomposed_path, vtable,
5624  user_data, error);
5625 
5626  CONNECTION_UNLOCK (connection);
5627 
5628  dbus_free_string_array (decomposed_path);
5629 
5630  return retval;
5631 }
5632 
5647  const char *path,
5648  const DBusObjectPathVTable *vtable,
5649  void *user_data,
5650  DBusError *error)
5651 {
5652  _dbus_return_val_if_fail (connection != NULL, FALSE);
5653  _dbus_return_val_if_fail (path != NULL, FALSE);
5654  _dbus_return_val_if_fail (path[0] == '/', FALSE);
5655  _dbus_return_val_if_fail (vtable != NULL, FALSE);
5656 
5657  return _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, error);
5658 }
5659 
5677  const char *path,
5678  const DBusObjectPathVTable *vtable,
5679  void *user_data)
5680 {
5681  dbus_bool_t retval;
5682  DBusError error = DBUS_ERROR_INIT;
5683 
5684  _dbus_return_val_if_fail (connection != NULL, FALSE);
5685  _dbus_return_val_if_fail (path != NULL, FALSE);
5686  _dbus_return_val_if_fail (path[0] == '/', FALSE);
5687  _dbus_return_val_if_fail (vtable != NULL, FALSE);
5688 
5689  retval = _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, &error);
5690 
5692  {
5693  _dbus_warn ("%s\n", error.message);
5694  dbus_error_free (&error);
5695  return FALSE;
5696  }
5697 
5698  return retval;
5699 }
5700 
5717  const char *path,
5718  const DBusObjectPathVTable *vtable,
5719  void *user_data,
5720  DBusError *error)
5721 {
5722  _dbus_return_val_if_fail (connection != NULL, FALSE);
5723  _dbus_return_val_if_fail (path != NULL, FALSE);
5724  _dbus_return_val_if_fail (path[0] == '/', FALSE);
5725  _dbus_return_val_if_fail (vtable != NULL, FALSE);
5726 
5727  return _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, error);
5728 }
5729 
5749  const char *path,
5750  const DBusObjectPathVTable *vtable,
5751  void *user_data)
5752 {
5753  dbus_bool_t retval;
5754  DBusError error = DBUS_ERROR_INIT;
5755 
5756  _dbus_return_val_if_fail (connection != NULL, FALSE);
5757  _dbus_return_val_if_fail (path != NULL, FALSE);
5758  _dbus_return_val_if_fail (path[0] == '/', FALSE);
5759  _dbus_return_val_if_fail (vtable != NULL, FALSE);
5760 
5761  retval = _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, &error);
5762 
5764  {
5765  _dbus_warn ("%s\n", error.message);
5766  dbus_error_free (&error);
5767  return FALSE;
5768  }
5769 
5770  return retval;
5771 }
5772 
5784  const char *path)
5785 {
5786  char **decomposed_path;
5787 
5788  _dbus_return_val_if_fail (connection != NULL, FALSE);
5789  _dbus_return_val_if_fail (path != NULL, FALSE);
5790  _dbus_return_val_if_fail (path[0] == '/', FALSE);
5791 
5792  if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
5793  return FALSE;
5794 
5795  CONNECTION_LOCK (connection);
5796 
5797  _dbus_object_tree_unregister_and_unlock (connection->objects, (const char **) decomposed_path);
5798 
5799  dbus_free_string_array (decomposed_path);
5800 
5801  return TRUE;
5802 }
5803 
5816  const char *path,
5817  void **data_p)
5818 {
5819  char **decomposed_path;
5820 
5821  _dbus_return_val_if_fail (connection != NULL, FALSE);
5822  _dbus_return_val_if_fail (path != NULL, FALSE);
5823  _dbus_return_val_if_fail (data_p != NULL, FALSE);
5824 
5825  *data_p = NULL;
5826 
5827  if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
5828  return FALSE;
5829 
5830  CONNECTION_LOCK (connection);
5831 
5832  *data_p = _dbus_object_tree_get_user_data_unlocked (connection->objects, (const char**) decomposed_path);
5833 
5834  CONNECTION_UNLOCK (connection);
5835 
5836  dbus_free_string_array (decomposed_path);
5837 
5838  return TRUE;
5839 }
5840 
5853  const char *parent_path,
5854  char ***child_entries)
5855 {
5856  char **decomposed_path;
5857  dbus_bool_t retval;
5858  _dbus_return_val_if_fail (connection != NULL, FALSE);
5859  _dbus_return_val_if_fail (parent_path != NULL, FALSE);
5860  _dbus_return_val_if_fail (parent_path[0] == '/', FALSE);
5861  _dbus_return_val_if_fail (child_entries != NULL, FALSE);
5862 
5863  if (!_dbus_decompose_path (parent_path, strlen (parent_path), &decomposed_path, NULL))
5864  return FALSE;
5865 
5866  CONNECTION_LOCK (connection);
5867 
5869  (const char **) decomposed_path,
5870  child_entries);
5871  dbus_free_string_array (decomposed_path);
5872 
5873  return retval;
5874 }
5875 
5876 static DBusDataSlotAllocator slot_allocator;
5877 _DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
5878 
5895 {
5896  return _dbus_data_slot_allocator_alloc (&slot_allocator,
5897  &_DBUS_LOCK_NAME (connection_slots),
5898  slot_p);
5899 }
5900 
5912 void
5914 {
5915  _dbus_return_if_fail (*slot_p >= 0);
5916 
5917  _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
5918 }
5919 
5944  dbus_int32_t slot,
5945  void *data,
5946  DBusFreeFunction free_data_func)
5947 {
5948  DBusFreeFunction old_free_func;
5949  void *old_data;
5950  dbus_bool_t retval;
5951 
5952  _dbus_return_val_if_fail (connection != NULL, FALSE);
5953  _dbus_return_val_if_fail (slot >= 0, FALSE);
5954 
5955  SLOTS_LOCK (connection);
5956 
5957  retval = _dbus_data_slot_list_set (&slot_allocator,
5958  &connection->slot_list,
5959  slot, data, free_data_func,
5960  &old_free_func, &old_data);
5961 
5962  SLOTS_UNLOCK (connection);
5963 
5964  if (retval)
5965  {
5966  /* Do the actual free outside the connection lock */
5967  if (old_free_func)
5968  (* old_free_func) (old_data);
5969  }
5970 
5971  return retval;
5972 }
5973 
5991 void*
5993  dbus_int32_t slot)
5994 {
5995  void *res;
5996 
5997  _dbus_return_val_if_fail (connection != NULL, NULL);
5998  _dbus_return_val_if_fail (slot >= 0, NULL);
5999 
6000  SLOTS_LOCK (connection);
6001 
6002  res = _dbus_data_slot_list_get (&slot_allocator,
6003  &connection->slot_list,
6004  slot);
6005 
6006  SLOTS_UNLOCK (connection);
6007 
6008  return res;
6009 }
6010 
6017 void
6019 {
6020  _dbus_modify_sigpipe = will_modify_sigpipe != FALSE;
6021 }
6022 
6031 void
6033  long size)
6034 {
6035  _dbus_return_if_fail (connection != NULL);
6036 
6037  CONNECTION_LOCK (connection);
6039  size);
6040  CONNECTION_UNLOCK (connection);
6041 }
6042 
6049 long
6051 {
6052  long res;
6053 
6054  _dbus_return_val_if_fail (connection != NULL, 0);
6055 
6056  CONNECTION_LOCK (connection);
6057  res = _dbus_transport_get_max_message_size (connection->transport);
6058  CONNECTION_UNLOCK (connection);
6059  return res;
6060 }
6061 
6070 void
6072  long n)
6073 {
6074  _dbus_return_if_fail (connection != NULL);
6075 
6076  CONNECTION_LOCK (connection);
6078  n);
6079  CONNECTION_UNLOCK (connection);
6080 }
6081 
6088 long
6090 {
6091  long res;
6092 
6093  _dbus_return_val_if_fail (connection != NULL, 0);
6094 
6095  CONNECTION_LOCK (connection);
6097  CONNECTION_UNLOCK (connection);
6098  return res;
6099 }
6100 
6126 void
6128  long size)
6129 {
6130  _dbus_return_if_fail (connection != NULL);
6131 
6132  CONNECTION_LOCK (connection);
6134  size);
6135  CONNECTION_UNLOCK (connection);
6136 }
6137 
6144 long
6146 {
6147  long res;
6148 
6149  _dbus_return_val_if_fail (connection != NULL, 0);
6150 
6151  CONNECTION_LOCK (connection);
6153  CONNECTION_UNLOCK (connection);
6154  return res;
6155 }
6156 
6168 void
6170  long n)
6171 {
6172  _dbus_return_if_fail (connection != NULL);
6173 
6174  CONNECTION_LOCK (connection);
6176  n);
6177  CONNECTION_UNLOCK (connection);
6178 }
6179 
6186 long
6188 {
6189  long res;
6190 
6191  _dbus_return_val_if_fail (connection != NULL, 0);
6192 
6193  CONNECTION_LOCK (connection);
6195  CONNECTION_UNLOCK (connection);
6196  return res;
6197 }
6198 
6209 long
6211 {
6212  long res;
6213 
6214  _dbus_return_val_if_fail (connection != NULL, 0);
6215 
6216  CONNECTION_LOCK (connection);
6217  res = _dbus_counter_get_size_value (connection->outgoing_counter);
6218  CONNECTION_UNLOCK (connection);
6219  return res;
6220 }
6221 
6222 #ifdef DBUS_ENABLE_STATS
6223 void
6224 _dbus_connection_get_stats (DBusConnection *connection,
6225  dbus_uint32_t *in_messages,
6226  dbus_uint32_t *in_bytes,
6227  dbus_uint32_t *in_fds,
6228  dbus_uint32_t *in_peak_bytes,
6229  dbus_uint32_t *in_peak_fds,
6230  dbus_uint32_t *out_messages,
6231  dbus_uint32_t *out_bytes,
6232  dbus_uint32_t *out_fds,
6233  dbus_uint32_t *out_peak_bytes,
6234  dbus_uint32_t *out_peak_fds)
6235 {
6236  CONNECTION_LOCK (connection);
6237 
6238  if (in_messages != NULL)
6239  *in_messages = connection->n_incoming;
6240 
6241  _dbus_transport_get_stats (connection->transport,
6242  in_bytes, in_fds, in_peak_bytes, in_peak_fds);
6243 
6244  if (out_messages != NULL)
6245  *out_messages = connection->n_outgoing;
6246 
6247  if (out_bytes != NULL)
6248  *out_bytes = _dbus_counter_get_size_value (connection->outgoing_counter);
6249 
6250  if (out_fds != NULL)
6251  *out_fds = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
6252 
6253  if (out_peak_bytes != NULL)
6254  *out_peak_bytes = _dbus_counter_get_peak_size_value (connection->outgoing_counter);
6255 
6256  if (out_peak_fds != NULL)
6257  *out_peak_fds = _dbus_counter_get_peak_unix_fd_value (connection->outgoing_counter);
6258 
6259  CONNECTION_UNLOCK (connection);
6260 }
6261 #endif /* DBUS_ENABLE_STATS */
6262 
6270 long
6272 {
6273  long res;
6274 
6275  _dbus_return_val_if_fail (connection != NULL, 0);
6276 
6277  CONNECTION_LOCK (connection);
6279  CONNECTION_UNLOCK (connection);
6280  return res;
6281 }
6282 
6283 #ifdef DBUS_BUILD_TESTS
6284 
6290 const char*
6291 _dbus_connection_get_address (DBusConnection *connection)
6292 {
6293  return _dbus_transport_get_address (connection->transport);
6294 }
6295 #endif
6296 
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
unsigned int dbus_uint32_t
A 32-bit unsigned integer on all platforms.
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...
An atomic integer safe to increment or decrement from multiple threads.
Definition: dbus-sysdeps.h:229
void _dbus_pending_call_complete(DBusPendingCall *pending)
Calls notifier function for the pending call and sets the call to completed.
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...
DBusMessage * dbus_message_ref(DBusMessage *message)
Increments the reference count of a DBusMessage.
DBusList * filter_list
List of filters.
void _dbus_transport_set_max_received_unix_fds(DBusTransport *transport, long n)
See dbus_connection_set_max_received_unix_fds().
Internals of DBusTimeout.
Definition: dbus-timeout.c:40
void * user_data
User data for the function.
void dbus_message_lock(DBusMessage *message)
Locks a message.
Definition: dbus-message.c:383
void * _dbus_list_get_last(DBusList **list)
Gets the last data in the list.
Definition: dbus-list.c:585
void _dbus_connection_toggle_watch_unlocked(DBusConnection *connection, DBusWatch *watch, dbus_bool_t enabled)
Toggles a watch and notifies app via connection&#39;s DBusWatchToggledFunction if available.
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_list_prepend(DBusList **list, void *data)
Prepends a value to the list.
Definition: dbus-list.c:281
void(* DBusTimeoutToggledFunction)(DBusTimeout *timeout, void *data)
Called when dbus_timeout_get_enabled() may return a different value than it did before.
int _dbus_hash_table_get_n_entries(DBusHashTable *table)
Gets the number of hash entries in a hash table.
Definition: dbus-hash.c:1397
DBusDispatchStatus
Indicates the status of incoming data on a DBusConnection.
const char * message
public error message field
Definition: dbus-errors.h:51
const char * _dbus_transport_get_address(DBusTransport *transport)
Gets the address of a transport.
dbus_int32_t _dbus_atomic_get(DBusAtomic *atomic)
Atomically get the value of an integer.
DBusFreeFunction free_wakeup_main_data
free wakeup_main_data
Implementation of DBusWatch.
Definition: dbus-watch.c:40
#define NULL
A null pointer, defined appropriately for C or C++.
void(* DBusFreeFunction)(void *memory)
The type of a function which frees a block of memory.
Definition: dbus-memory.h:64
dbus_bool_t _dbus_connection_add_timeout_unlocked(DBusConnection *connection, DBusTimeout *timeout)
Adds a timeout using the connection&#39;s DBusAddTimeoutFunction if available.
DBusList * queue_link
Preallocated link in the queue.
unsigned int have_connection_lock
Used to check locking.
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, the other end of the connection may (but is not required to) optimize by not sending method return or error replies.
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:239
void(* DBusRemoveWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus no longer needs a watch to be monitored by the main loop.
void _dbus_connection_queue_synthesized_message_link(DBusConnection *connection, DBusList *link)
Adds a link + message to the incoming message queue.
DBusConnection * _dbus_pending_call_get_connection_unlocked(DBusPendingCall *pending)
Gets the connection associated with this pending call.
void _dbus_object_tree_free_all_unlocked(DBusObjectTree *tree)
Free all the handlers in the tree.
More memory is needed to continue.
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:701
dbus_uint32_t dbus_message_get_serial(DBusMessage *message)
Returns the serial of a message or 0 if none has been specified.
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:304
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...
DBusWatchList * _dbus_watch_list_new(void)
Creates a new watch list.
Definition: dbus-watch.c:232
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, or for a timeout.
Definition: dbus-threads.c:323
DBusList * _dbus_list_get_last_link(DBusList **list)
Gets the last link in the list.
Definition: dbus-list.c:569
dbus_bool_t dbus_connection_get_windows_user(DBusConnection *connection, char **windows_sid_p)
Gets the Windows user SID of the connection if known.
void _dbus_connection_lock(DBusConnection *connection)
Acquires the connection lock.
DBusMessage * dbus_pending_call_steal_reply(DBusPendingCall *pending)
Gets the reply, or returns NULL if none has been received yet.
#define dbus_new(type, count)
Safe macro for using dbus_malloc().
Definition: dbus-memory.h:58
DBusList * disconnect_message_link
Preallocated list node for queueing the disconnection message.
dbus_bool_t(* DBusWatchAddFunction)(DBusWatchList *list, DBusWatch *watch)
Function to be called in protected_change_watch() with refcount held.
void(* DBusDispatchStatusFunction)(DBusConnection *connection, DBusDispatchStatus new_status, void *data)
Called when the return value of dbus_connection_get_dispatch_status() may have changed.
void dbus_connection_set_max_message_size(DBusConnection *connection, long size)
Specifies the maximum size message this connection is allowed to receive.
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.
void _dbus_list_remove_link(DBusList **list, DBusList *link)
Removes a link from the list.
Definition: dbus-list.c:516
void _dbus_timeout_list_free(DBusTimeoutList *timeout_list)
Frees a DBusTimeoutList.
Definition: dbus-timeout.c:211
long dbus_connection_get_outgoing_size(DBusConnection *connection)
Gets the approximate size in bytes of all messages in the outgoing message queue. ...
DBusConnection * dbus_connection_ref(DBusConnection *connection)
Increments the reference count of a DBusConnection.
dbus_bool_t dbus_connection_can_send_type(DBusConnection *connection, int type)
Tests whether a certain type can be send via the connection.
DBusMessage * message_borrowed
Filled in if the first incoming message has been borrowed; dispatch_acquired will be set by the borro...
#define DBUS_TYPE_STRING
Type code marking a UTF-8 encoded, nul-terminated Unicode string.
DBusTimeoutList * _dbus_timeout_list_new(void)
Creates a new timeout list.
Definition: dbus-timeout.c:194
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
dbus_bool_t dbus_connection_read_write(DBusConnection *connection, int timeout_milliseconds)
This function is intended for use with applications that don&#39;t want to write a main loop and deal wit...
unsigned int shareable
TRUE if libdbus owns a reference to the connection and can return it from dbus_connection_open() more...
dbus_bool_t dbus_message_has_interface(DBusMessage *message, const char *interface)
Checks if the message has an interface.
void _dbus_list_append_link(DBusList **list, DBusList *link)
Appends a link to the list.
Definition: dbus-list.c:304
Internals of DBusCounter.
#define DBUS_ERROR_INIT
Expands to a suitable initializer for a DBusError on the stack.
Definition: dbus-errors.h:62
void * data
Data stored at this element.
Definition: dbus-list.h:38
DBusFreeFunction free_dispatch_status_data
free dispatch_status_data
DBusMessage * dbus_message_new(int message_type)
Constructs a new message of the given message type.
DBusFreeFunction free_user_data_function
Function to free the user data.
DBusList * incoming_messages
Queue of messages we have received, end of the list received most recently.
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:375
void _dbus_warn_check_failed(const char *format,...)
Prints a &quot;critical&quot; warning to stderr when an assertion fails; differs from _dbus_warn primarily in t...
dbus_bool_t _dbus_transport_get_unix_process_id(DBusTransport *transport, unsigned long *pid)
See dbus_connection_get_unix_process_id().
const char * dbus_message_get_signature(DBusMessage *message)
Gets the type signature of the message, i.e.
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&#39;s DBusWatchToggledFunction if appro...
Definition: dbus-watch.c:435
dbus_bool_t _dbus_transport_queue_messages(DBusTransport *transport)
Processes data we&#39;ve read while handling a watch, potentially converting some of it to messages and q...
Message has not had any effect - see if other handlers want it.
Definition: dbus-shared.h:69
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().
void dbus_message_iter_init_append(DBusMessage *message, DBusMessageIter *iter)
Initializes a DBusMessageIter for appending arguments to the end of a message.
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_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...
void dbus_error_free(DBusError *error)
Frees an error that&#39;s been set (or just initialized), then reinitializes the error as in dbus_error_i...
Definition: dbus-errors.c:211
void dbus_connection_set_route_peer_messages(DBusConnection *connection, dbus_bool_t value)
Normally DBusConnection automatically handles all messages to the org.freedesktop.DBus.Peer interface.
void _dbus_object_tree_unregister_and_unlock(DBusObjectTree *tree, const char **path)
Unregisters an object subtree that was registered with the same path.
#define DBUS_INTERFACE_PEER
The interface supported by most dbus peers.
Definition: dbus-shared.h:94
void _dbus_connection_close_if_only_one_ref(DBusConnection *connection)
Used internally to handle the semantics of dbus_server_set_new_connection_function().
#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:100
void dbus_connection_return_message(DBusConnection *connection, DBusMessage *message)
Used to return a message after peeking at it using dbus_connection_borrow_message().
DBusAtomic refcount
Reference count.
DBusCounter * _dbus_counter_ref(DBusCounter *counter)
Increments refcount of the counter.
void dbus_address_entries_free(DBusAddressEntry **entries)
Frees a NULL-terminated array of address entries.
Definition: dbus-address.c:189
dbus_bool_t _dbus_transport_get_windows_user(DBusTransport *transport, char **windows_sid_p)
See dbus_connection_get_windows_user().
Implementation details of DBusPendingCall - all fields are private.
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:70
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.
Implementation details of DBusConnection.
void(* DBusWakeupMainFunction)(void *data)
Called when the main loop&#39;s thread should be notified that there&#39;s now work to do.
void dbus_connection_remove_filter(DBusConnection *connection, DBusHandleMessageFunction function, void *user_data)
Removes a previously-added message filter.
struct DBusMutex DBusMutex
An opaque mutex type provided by the DBusThreadFunctions implementation installed by dbus_threads_ini...
Definition: dbus-threads.h:41
#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:91
DBusCounter * outgoing_counter
Counts size of outgoing messages.
#define DBUS_MESSAGE_TYPE_ERROR
Message type of an error reply message, see dbus_message_get_type()
DBusList * _dbus_list_alloc_link(void *data)
Allocates a linked list node.
Definition: dbus-list.c:231
dbus_bool_t dbus_connection_get_unix_user(DBusConnection *connection, unsigned long *uid)
Gets the UNIX user ID of the connection if known.
void(* DBusTimeoutToggleFunction)(DBusTimeoutList *list, DBusTimeout *timeout, dbus_bool_t enabled)
Function to be called in protected_change_timeout() with refcount held.
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.
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...
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:175
dbus_bool_t _dbus_hash_table_remove_int(DBusHashTable *table, int key)
Removes the hash entry for the given key.
Definition: dbus-hash.c:1151
long _dbus_transport_get_max_message_size(DBusTransport *transport)
See dbus_connection_get_max_message_size().
dbus_bool_t _dbus_list_remove(DBusList **list, void *data)
Removes a value from the list.
Definition: dbus-list.c:404
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...
DBusDispatchStatusFunction dispatch_status_function
Function on dispatch status changes.
void(* DBusWatchRemoveFunction)(DBusWatchList *list, DBusWatch *watch)
Function to be called in protected_change_watch() with refcount held.
DBusHandlerResult
Results that a message handler can return.
Definition: dbus-shared.h:66
Hash keys are strings.
Definition: dbus-hash.h:69
dbus_bool_t _dbus_data_slot_allocator_alloc(DBusDataSlotAllocator *allocator, DBusRMutex **mutex_loc, dbus_int32_t *slot_id_p)
Allocates an integer ID to be used for storing data in a DBusDataSlotList.
Definition: dbus-dataslot.c:69
DBusMessage * _dbus_connection_get_message_to_send(DBusConnection *connection)
Gets the next outgoing message.
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:361
DBusList * _dbus_list_pop_first_link(DBusList **list)
Removes the first link in the list and returns it.
Definition: dbus-list.c:617
Hash iterator object.
Definition: dbus-hash.h:49
DBusMessageIter struct; contains no public fields.
Definition: dbus-message.h:51
void dbus_connection_steal_borrowed_message(DBusConnection *connection, DBusMessage *message)
Used to keep a message after peeking at it using dbus_connection_borrow_message().
void * _dbus_list_get_first(DBusList **list)
Gets the first data in the list.
Definition: dbus-list.c:601
dbus_bool_t _dbus_pending_call_get_completed_unlocked(DBusPendingCall *pending)
Checks whether the pending call has received a reply yet, or not.
#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:90
void dbus_connection_free_data_slot(dbus_int32_t *slot_p)
Deallocates a global ID for connection data slots.
#define DBUS_ERROR_UNKNOWN_METHOD
Method name you invoked isn&#39;t known by the object you invoked it on.
const char * dbus_message_get_destination(DBusMessage *message)
Gets the destination of a message or NULL if there is none set.
Internal struct representing a message filter function.
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, and decremented by the size/unix fds of this message when this message if finalized.
Definition: dbus-message.c:279
#define DBUS_PATH_LOCAL
The object path used in local/in-process-generated messages.
Definition: dbus-shared.h:82
dbus_bool_t _dbus_list_copy(DBusList **list, DBusList **dest)
Copies a list.
Definition: dbus-list.c:686
void _dbus_connection_block_pending_call(DBusPendingCall *pending)
Blocks until a pending call times out or gets a reply.
dbus_bool_t _dbus_get_local_machine_uuid_encoded(DBusString *uuid_str)
Gets the hex-encoded UUID of the machine this function is executed on.
DBusWatchList * watches
Stores active watches.
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:1074
DBusRMutex * mutex
Lock on the entire DBusConnection.
dbus_bool_t _dbus_transport_get_is_connected(DBusTransport *transport)
Returns TRUE if the transport has not been disconnected.
dbus_bool_t dbus_message_set_error_name(DBusMessage *message, const char *error_name)
Sets the name of the error (DBUS_MESSAGE_TYPE_ERROR).
There is more data to potentially convert to messages.
void _dbus_get_monotonic_time(long *tv_sec, long *tv_usec)
Get current time, as in gettimeofday().
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.
DBusConnection * dbus_connection_open_private(const char *address, DBusError *error)
Opens a new, dedicated connection to a remote address.
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
DBusAtomic refcount
Reference count.
const char * dbus_message_get_member(DBusMessage *message)
Gets the interface member being invoked (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted (DBUS_MESSAGE_TYPE...
DBusPreallocatedSend * dbus_connection_preallocate_send(DBusConnection *connection)
Preallocates resources needed to send a message, allowing the message to be sent without the possibil...
Virtual table that must be implemented to handle a portion of the object path hierarchy.
dbus_bool_t(* DBusAddWatchFunction)(DBusWatch *watch, void *data)
Called when libdbus needs a new watch to be monitored by the main loop.
Internals of DBusMessage.
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.
dbus_bool_t dbus_pending_call_get_completed(DBusPendingCall *pending)
Checks whether the pending call has received a reply yet, or not.
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:244
long _dbus_transport_get_max_received_unix_fds(DBusTransport *transport)
See dbus_connection_set_max_received_unix_fds().
DBusHandlerResult(* DBusHandleMessageFunction)(DBusConnection *connection, DBusMessage *message, void *user_data)
Called when a message needs to be handled.
Hash keys are integers.
Definition: dbus-hash.h:70
void _dbus_rmutex_unlock(DBusRMutex *mutex)
Unlocks a mutex.
Definition: dbus-threads.c:197
#define DBUS_ERROR_OBJECT_PATH_IN_USE
There&#39;s already an object with the requested object path.
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
Definition: dbus-memory.h:59
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:310
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().
void _dbus_connection_remove_watch_unlocked(DBusConnection *connection, DBusWatch *watch)
Removes a watch using the connection&#39;s DBusRemoveWatchFunction if available.
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_pending_call_is_timeout_added_unlocked(DBusPendingCall *pending)
Checks to see if a timeout has been added.
DBusHashTable * _dbus_hash_table_new(DBusHashType type, DBusFreeFunction key_free_function, DBusFreeFunction value_free_function)
Constructs a new hash table.
Definition: dbus-hash.c:285
void * dispatch_status_data
Application data for dispatch_status_function.
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
dbus_bool_t _dbus_connection_has_messages_to_send_unlocked(DBusConnection *connection)
Checks whether there are messages in the outgoing message queue.
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.
DBusTransport * transport
Object that sends/receives messages over network.
DBusDispatchStatus dbus_connection_dispatch(DBusConnection *connection)
Processes any incoming data.
dbus_bool_t dbus_connection_send(DBusConnection *connection, DBusMessage *message, dbus_uint32_t *serial)
Adds a message to the outgoing message queue.
DBusDispatchStatus dbus_connection_get_dispatch_status(DBusConnection *connection)
Gets the current state of the incoming message queue.
All currently available data has been processed.
void * dbus_connection_get_data(DBusConnection *connection, dbus_int32_t slot)
Retrieves data previously set with dbus_connection_set_data().
DBusTimeoutList * timeouts
Stores active timeouts.
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.
long dbus_connection_get_max_message_size(DBusConnection *connection)
Gets the value set by dbus_connection_set_max_message_size().
DBusHashTable * pending_replies
Hash of message serials to DBusPendingCall.
Internals of DBusObjectTree.
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
void _dbus_counter_unref(DBusCounter *counter)
Decrements refcount of the counter and possibly finalizes the counter.
dbus_bool_t(* DBusAddTimeoutFunction)(DBusTimeout *timeout, void *data)
Called when libdbus needs a new timeout to be monitored by the main loop.
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:351
dbus_bool_t _dbus_list_append(DBusList **list, void *data)
Appends a value to the list.
Definition: dbus-list.c:259
dbus_bool_t _dbus_decompose_path(const char *data, int len, char ***path, int *path_len)
Decompose an object path.
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_is_authenticated(DBusConnection *connection)
Gets whether the connection was authenticated.
void dbus_connection_close(DBusConnection *connection)
Closes a private connection, so no further data can be sent or received.
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.
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_transport_get_is_authenticated(DBusTransport *transport)
Returns TRUE if we have been authenticated.
dbus_bool_t io_path_acquired
Someone has transport io path (can use the transport to read/write messages)
void _dbus_list_foreach(DBusList **list, DBusForeachFunction function, void *data)
Calls the given function for each element in the list.
Definition: dbus-list.c:748
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:1111
Internals of DBusAddressEntry.
Definition: dbus-address.c:43
DBusList * outgoing_messages
Queue of messages we need to send, send the end of the list first.
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_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...
DBusObjectTree * objects
Object path handlers registered with this connection.
long dbus_connection_get_outgoing_unix_fds(DBusConnection *connection)
Gets the approximate number of uni fds of all messages in the outgoing message queue.
dbus_uint32_t client_serial
Client serial.
long dbus_connection_get_max_received_size(DBusConnection *connection)
Gets the value set by dbus_connection_set_max_received_size().
DBusCMutex * io_path_mutex
Protects io_path_acquired.
#define DBUS_MESSAGE_TYPE_METHOD_CALL
Message type of a method call message, see dbus_message_get_type()
DBusConnection * dbus_connection_open(const char *address, DBusError *error)
Gets a connection to a remote address.
void _dbus_connection_unref_unlocked(DBusConnection *connection)
Decrements the reference count of a DBusConnection.
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.
int _dbus_current_generation
_dbus_current_generation is used to track each time that dbus_shutdown() is called, so we can reinit things after it&#39;s been called.
Definition: dbus-memory.c:781
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 ...
Object representing an exception.
Definition: dbus-errors.h:48
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...
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:401
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:543
void _dbus_disable_sigpipe(void)
signal (SIGPIPE, SIG_IGN);
dbus_bool_t _dbus_transport_get_is_anonymous(DBusTransport *transport)
See dbus_connection_get_is_anonymous().
void * _dbus_list_pop_first(DBusList **list)
Removes the first value in the list and returns it.
Definition: dbus-list.c:638
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...
dbus_bool_t dbus_message_append_args(DBusMessage *message, int first_arg_type,...)
Appends fields to a message given a variable argument list.
#define DBUS_ERROR_UNKNOWN_OBJECT
Object you invoked a method on isn&#39;t known.
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:1214
dbus_bool_t dbus_connection_get_is_anonymous(DBusConnection *connection)
Gets whether the connection is not authenticated as a specific user.
#define DBUS_MESSAGE_TYPE_SIGNAL
Message type of a signal message, see dbus_message_get_type()
dbus_bool_t _dbus_connection_add_watch_unlocked(DBusConnection *connection, DBusWatch *watch)
Adds a watch using the connection&#39;s DBusAddWatchFunction if available.
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
dbus_uint32_t dbus_message_get_reply_serial(DBusMessage *message)
Returns the serial that the message is a reply to or 0 if none.
long dbus_connection_get_max_message_unix_fds(DBusConnection *connection)
Gets the value set by dbus_connection_set_max_message_unix_fds().
DBusWakeupMainFunction wakeup_main_function
Function to wake up the mainloop.
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...
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
void _dbus_cmutex_unlock(DBusCMutex *mutex)
Unlocks a mutex.
Definition: dbus-threads.c:209
DBusDataSlotList slot_list
Data stored by allocated integer ID.
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:1248
DBusPendingCall * dbus_pending_call_ref(DBusPendingCall *pending)
Increments the reference count on a pending call.
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_timeout_list_toggle_timeout(DBusTimeoutList *timeout_list, DBusTimeout *timeout, dbus_bool_t enabled)
Sets a timeout to the given enabled state, invoking the application&#39;s DBusTimeoutToggledFunction if a...
Definition: dbus-timeout.c:362
dbus_uint32_t _dbus_pending_call_get_reply_serial_unlocked(DBusPendingCall *pending)
Gets the reply&#39;s serial number.
void(* DBusWatchToggleFunction)(DBusWatchList *list, DBusWatch *watch, dbus_bool_t enabled)
Function to be called in protected_change_watch() with refcount held.
DBusTransport * _dbus_transport_open(DBusAddressEntry *entry, DBusError *error)
Try to open a new transport for the given address entry.
DBusConnection * _dbus_connection_new_for_transport(DBusTransport *transport)
Creates a new connection for the given transport.
#define _DBUS_UNLOCK(name)
Unlocks a global lock.
unsigned int disconnected_message_arrived
We popped or are dispatching the disconnected message.
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
Definition: dbus-string.c:242
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 ...
unsigned int disconnected_message_processed
We did our default handling of the disconnected message, such as closing the connection.
dbus_bool_t _dbus_transport_get_unix_user(DBusTransport *transport, unsigned long *uid)
See dbus_connection_get_unix_user().
void * _dbus_data_slot_list_get(DBusDataSlotAllocator *allocator, DBusDataSlotList *list, int slot)
Retrieves data previously set with _dbus_data_slot_list_set_data().
#define CONNECTION_UNLOCK(connection)
shorter and more visible way to write _dbus_connection_unlock()
unsigned int route_peer_messages
If TRUE, if org.freedesktop.DBus.Peer messages have a bus name, don&#39;t handle them automatically...
#define TRUE
Expands to &quot;1&quot;.
void _dbus_data_slot_list_init(DBusDataSlotList *list)
Initializes a slot list.
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
Data structure that stores the actual user data set at a given slot.
Definition: dbus-dataslot.h:67
DBusCondVar * io_path_cond
Notify when io_path_acquired is available.
dbus_bool_t dbus_message_is_method_call(DBusMessage *message, const char *interface, const char *method)
Checks whether the message is a method call with the given interface and member fields.
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:1123
void _dbus_condvar_new_at_location(DBusCondVar **location_p)
This does the same thing as _dbus_condvar_new.
Definition: dbus-threads.c:244
DBusDispatchStatus last_dispatch_status
The last dispatch status we reported to the application.
unsigned int exit_on_disconnect
If TRUE, exit after handling disconnect signal.
dbus_bool_t _dbus_transport_set_connection(DBusTransport *transport, DBusConnection *connection)
Sets the connection using this transport.
#define DBUS_ERROR_FAILED
A generic error; &quot;something went wrong&quot; - see the error message for more.
void _dbus_list_free_link(DBusList *link)
Frees a linked list node allocated with _dbus_list_alloc_link.
Definition: dbus-list.c:243
void dbus_move_error(DBusError *src, DBusError *dest)
Moves an error src into dest, freeing src and overwriting dest.
Definition: dbus-errors.c:279
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...
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.
dbus_bool_t dbus_set_error_from_message(DBusError *error, DBusMessage *message)
Sets a DBusError based on the contents of the given message.
void(* DBusTimeoutRemoveFunction)(DBusTimeoutList *list, DBusTimeout *timeout)
Function to be called in protected_change_timeout() with refcount held.
void _dbus_condvar_wake_one(DBusCondVar *cond)
If there are threads waiting on the condition variable, wake up exactly one.
Definition: dbus-threads.c:340
#define DBUS_TYPE_UNIX_FD
Type code marking a unix file descriptor.
void dbus_pending_call_unref(DBusPendingCall *pending)
Decrements the reference count on a pending call, freeing it if the count reaches 0...
Object representing a transport such as a socket.
DBusMessage * dbus_message_new_signal(const char *path, const char *interface, const char *name)
Constructs a new message representing a signal emission.
DBusWatchList implementation details.
Definition: dbus-watch.c:214
#define _DBUS_DEFINE_GLOBAL_LOCK(name)
Defines a global lock variable with the given name.
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...
int n_incoming
Length of incoming queue.
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.
void _dbus_hash_iter_remove_entry(DBusHashIter *iter)
Removes the current entry from the hash table.
Definition: dbus-hash.c:592
DBusMessage * dbus_connection_pop_message(DBusConnection *connection)
Returns the first-received message from the incoming message queue, removing it from the queue...
An allocator that tracks a set of slot IDs.
Definition: dbus-dataslot.h:55
#define DBUS_TYPE_INVALID
Type code that is never equal to a legitimate type code.
Definition: dbus-protocol.h:60
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).
void _dbus_pending_call_queue_timeout_error_unlocked(DBusPendingCall *pending, DBusConnection *connection)
If the pending call hasn&#39;t been timed out, add its timeout error reply to the connection&#39;s incoming m...
Internals of DBusPreallocatedSend.
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_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...
DBusList * counter_link
Preallocated link in the resource counter.
DBusObjectTree * _dbus_object_tree_new(DBusConnection *connection)
Creates a new object tree, representing a mapping from paths to handler vtables.
void dbus_pending_call_block(DBusPendingCall *pending)
Block until the pending call is completed.
void _dbus_timeout_list_remove_timeout(DBusTimeoutList *timeout_list, DBusTimeout *timeout)
Removes a timeout from the timeout list, invoking the application&#39;s DBusRemoveTimeoutFunction if appr...
Definition: dbus-timeout.c:340
int n_outgoing
Length of outgoing queue.
DBusCMutex * dispatch_mutex
Protects dispatch_acquired.
DBusPendingCall * _dbus_pending_call_new_unlocked(DBusConnection *connection, int timeout_milliseconds, DBusTimeoutHandler timeout_handler)
Creates a new pending reply object.
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:277
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, by timing out the pending call.
void _dbus_exit(int code)
Exit the process, returning the given value.
A node in a linked list.
Definition: dbus-list.h:34
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 _dbus_list_unlink(DBusList **list, DBusList *link)
Removes the given link from the list, but doesn&#39;t free it.
Definition: dbus-list.c:488
void dbus_free_string_array(char **str_array)
Frees a NULL-terminated array of strings.
Definition: dbus-memory.c:749
DBusTransport * _dbus_transport_ref(DBusTransport *transport)
Increments the reference count for the transport.
DBusCondVar * dispatch_cond
Notify when dispatch_acquired is available.
void _dbus_connection_remove_timeout_unlocked(DBusConnection *connection, DBusTimeout *timeout)
Removes a timeout using the connection&#39;s DBusRemoveTimeoutFunction if available.
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.
void _dbus_rmutex_free_at_location(DBusRMutex **location_p)
Frees a DBusRMutex or removes it from the uninitialized mutex list; does nothing if passed a NULL poi...
Definition: dbus-threads.c:125
void _dbus_transport_do_iteration(DBusTransport *transport, unsigned int flags, int timeout_milliseconds)
Performs a single poll()/select() on the transport&#39;s file descriptors and then reads/writes data as a...
long _dbus_transport_get_max_received_size(DBusTransport *transport)
See dbus_connection_get_max_received_size().
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.
long _dbus_transport_get_max_message_unix_fds(DBusTransport *transport)
See dbus_connection_get_max_message_unix_fds().
dbus_bool_t dbus_message_is_signal(DBusMessage *message, const char *interface, const char *signal_name)
Checks whether the message is a signal with the given interface and member fields.
#define DBUS_ERROR_DISCONNECTED
The connection is disconnected and you&#39;re trying to use it.
DBusCounter * _dbus_counter_new(void)
Creates a new DBusCounter.
void _dbus_cmutex_lock(DBusCMutex *mutex)
Locks a mutex.
Definition: dbus-threads.c:185
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...
void _dbus_transport_set_allow_anonymous(DBusTransport *transport, dbus_bool_t value)
See dbus_connection_set_allow_anonymous()
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...
DBusHandleMessageFunction function
Function to call to filter.
void _dbus_hash_iter_init(DBusHashTable *table, DBusHashIter *iter)
Initializes a hash table iterator.
Definition: dbus-hash.c:517
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...
void * _dbus_hash_iter_get_value(DBusHashIter *iter)
Gets the value of the current entry.
Definition: dbus-hash.c:613
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.
dbus_bool_t dbus_message_iter_append_basic(DBusMessageIter *iter, int type, const void *value)
Appends a basic-typed value to the message.
void _dbus_transport_set_max_received_size(DBusTransport *transport, long size)
See dbus_connection_set_max_received_size().
void(* DBusForeachFunction)(void *element, void *data)
Used to iterate over each item in a collection, such as a DBusList.
DBusList * expired_messages
Messages that will be released when we next unlock.
DBusList * _dbus_list_get_first_link(DBusList **list)
Gets the first link in the list.
Definition: dbus-list.c:556
#define FALSE
Expands to &quot;0&quot;.
int dbus_message_get_type(DBusMessage *message)
Gets the type of a message.
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 dbus_connection_get_unix_fd(DBusConnection *connection, int *fd)
Get the UNIX file descriptor of the connection, if any.
void _dbus_list_prepend_link(DBusList **list, DBusList *link)
Prepends a link to the list.
Definition: dbus-list.c:322
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:810
#define _DBUS_LOCK(name)
Locks a global lock.
dbus_bool_t dbus_parse_address(const char *address, DBusAddressEntry ***entry, int *array_len, DBusError *error)
Parses an address string of the form:
Definition: dbus-address.c:363
#define _DBUS_LOCK_NAME(name)
Expands to name of a global lock variable.
dbus_bool_t _dbus_transport_can_pass_unix_fd(DBusTransport *transport)
Returns TRUE if the transport supports sending unix fds.
void _dbus_cmutex_free_at_location(DBusCMutex **location_p)
Frees a DBusCMutex and removes it from the uninitialized mutex list; does nothing if passed a NULL po...
Definition: dbus-threads.c:149
void(* DBusWatchToggledFunction)(DBusWatch *watch, void *data)
Called when dbus_watch_get_enabled() may return a different value than it did before.
char * server_guid
GUID of server if we are in shared_connections, NULL if server GUID is unknown or connection is priva...
dbus_bool_t dbus_connection_get_is_connected(DBusConnection *connection)
Gets whether the connection is currently open.
void dbus_connection_send_preallocated(DBusConnection *connection, DBusPreallocatedSend *preallocated, DBusMessage *message, dbus_uint32_t *client_serial)
Sends a message using preallocated resources.
void dbus_connection_unref(DBusConnection *connection)
Decrements the reference count of a DBusConnection, and finalizes it if the count reaches zero...
Internals of DBusHashTable.
Definition: dbus-hash.c:168
void _dbus_object_tree_unref(DBusObjectTree *tree)
Decrement the reference count.
void _dbus_watch_list_free(DBusWatchList *watch_list)
Frees a DBusWatchList.
Definition: dbus-watch.c:249
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...
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_transport_get_socket_fd(DBusTransport *transport, int *fd_p)
Get the socket file descriptor, if any.
DBusConnection * _dbus_connection_ref_unlocked(DBusConnection *connection)
Increments the reference count of a DBusConnection.
Message has had its effect - no need to run more handlers.
Definition: dbus-shared.h:68
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 ...
int dbus_int32_t
A 32-bit signed integer on all platforms.
char * _dbus_strdup(const char *str)
Duplicates a string.
#define CONNECTION_LOCK(connection)
Internals of DBusPendingCall.
dbus_bool_t dispatch_acquired
Someone has dispatch path (can drain incoming queue)
void _dbus_transport_disconnect(DBusTransport *transport)
Closes our end of the connection to a remote application.
DBusTimeout * _dbus_pending_call_get_timeout_unlocked(DBusPendingCall *pending)
Retrives the timeout.
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().
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_unregister_object_path(DBusConnection *connection, const char *path)
Unregisters the handler registered with exactly the given path.
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:1049
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_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(* DBusRemoveTimeoutFunction)(DBusTimeout *timeout, void *data)
Called when libdbus no longer needs a timeout to be monitored by the main loop.
void _dbus_connection_unlock(DBusConnection *connection)
Releases the connection lock.
const char * _dbus_string_get_const_data(const DBusString *str)
Gets the raw character buffer from a const string.
Definition: dbus-string.c:446
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_transport_set_max_message_size(DBusTransport *transport, long size)
See dbus_connection_set_max_message_size().
void dbus_message_unref(DBusMessage *message)
Decrements the reference count of a DBusMessage, freeing the message if the count reaches 0...
void * wakeup_main_data
Application data for wakeup_main_function.
Need more memory in order to return DBUS_HANDLER_RESULT_HANDLED or DBUS_HANDLER_RESULT_NOT_YET_HANDLE...
Definition: dbus-shared.h:70
void dbus_connection_flush(DBusConnection *connection)
Blocks until the outgoing message queue is empty.
void _dbus_condvar_free_at_location(DBusCondVar **location_p)
Frees a conditional variable and removes it from the uninitialized_condvar_list; does nothing if pass...
Definition: dbus-threads.c:279
dbus_bool_t dbus_connection_has_messages_to_send(DBusConnection *connection)
Checks whether there are messages in the outgoing message queue.
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:103
void _dbus_sleep_milliseconds(int milliseconds)
Sleeps the given number of milliseconds.
void _dbus_pending_call_unref_and_unlock(DBusPendingCall *pending)
Decrements the reference count on a pending call, freeing it if the count reaches 0...
DBusDispatchStatus _dbus_transport_get_dispatch_status(DBusTransport *transport)
Reports our current dispatch status (whether there&#39;s buffered data to be queued as messages...
void _dbus_pending_call_set_timeout_added_unlocked(DBusPendingCall *pending, dbus_bool_t is_added)
Sets wether the timeout has been added.
DBusConnection * connection
Connection we&#39;d send the message to.
DBusConnection * _dbus_pending_call_get_connection_and_lock(DBusPendingCall *pending)
Gets the connection associated with this pending call.
void _dbus_connection_toggle_timeout_unlocked(DBusConnection *connection, DBusTimeout *timeout, dbus_bool_t enabled)
Toggles a timeout and notifies app via connection&#39;s DBusTimeoutToggledFunction if available...
dbus_bool_t dbus_type_is_valid(int typecode)
Return TRUE if the argument is a valid typecode.
void _dbus_transport_set_max_message_unix_fds(DBusTransport *transport, long n)
See dbus_connection_set_max_message_unix_fds().
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_get_socket(DBusConnection *connection, int *fd)
Gets the underlying Windows or UNIX socket file descriptor of the connection, if any.
void dbus_connection_free_preallocated_send(DBusConnection *connection, DBusPreallocatedSend *preallocated)
Frees preallocated message-sending resources from dbus_connection_preallocate_send().
void dbus_message_set_serial(DBusMessage *message, dbus_uint32_t serial)
Sets the serial number of a message.
Definition: dbus-message.c:253
DBusTimeoutList implementation details.
Definition: dbus-timeout.c:176
DBusMessage * dbus_message_new_method_return(DBusMessage *method_call)
Constructs a message that is a reply to a method call.
DBusRMutex * slot_mutex
Lock on slot_list so overall connection lock need not be taken.
void _dbus_transport_unref(DBusTransport *transport)
Decrements the reference count for the transport.
int generation
_dbus_current_generation that should correspond to this connection
void _dbus_watch_list_remove_watch(DBusWatchList *watch_list, DBusWatch *watch)
Removes a watch from the watch list, invoking the application&#39;s DBusRemoveWatchFunction if appropriat...
Definition: dbus-watch.c:408
long _dbus_counter_get_unix_fd_value(DBusCounter *counter)
Gets the current value of the unix fd counter.
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_list_clear(DBusList **list)
Frees all links in the list and sets the list head to NULL.
Definition: dbus-list.c:531
dbus_bool_t(* DBusTimeoutAddFunction)(DBusTimeoutList *list, DBusTimeout *timeout)
Function to be called in protected_change_timeout() with refcount held.
DBUS_EXPORT int dbus_timeout_get_interval(DBusTimeout *timeout)
Gets the timeout interval.
Definition: dbus-timeout.c:416
dbus_bool_t dbus_connection_read_write_dispatch(DBusConnection *connection, int timeout_milliseconds)
This function is intended for use with applications that don&#39;t want to write a main loop and deal wit...
long _dbus_counter_get_size_value(DBusCounter *counter)
Gets the current value of the size counter.
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.