dbus-marshal-validate: Check brackets in signature nest correctly
[platform/upstream/dbus.git] / dbus / dbus-connection.c
index ac0b2c0..e010579 100644 (file)
  * @{
  */
 
-#ifdef DBUS_ENABLE_VERBOSE_MODE
 static void
 _dbus_connection_trace_ref (DBusConnection *connection,
     int old_refcount,
     int new_refcount,
     const char *why)
 {
+#ifdef DBUS_ENABLE_VERBOSE_MODE
   static int enabled = -1;
 
   _dbus_trace_ref ("DBusConnection", connection, old_refcount, new_refcount,
       why, "DBUS_CONNECTION_TRACE", &enabled);
-}
-#else
-#define _dbus_connection_trace_ref(c,o,n,w) \
-  do \
-  {\
-    (void) (o); \
-    (void) (n); \
-  } while (0)
 #endif
+}
 
 /**
  * Internal struct representing a message filter function 
@@ -318,7 +311,8 @@ struct DBusConnection
    */
   dbus_bool_t dispatch_acquired; /**< Someone has dispatch path (can drain incoming queue) */
   dbus_bool_t io_path_acquired;  /**< Someone has transport io path (can use the transport to read/write messages) */
-  
+
+  unsigned int dispatch_disabled : 1;  /**< if true, then dispatching incoming messages is stopped until enabled again */
   unsigned int shareable : 1; /**< #TRUE if libdbus owns a reference to the connection and can return it from dbus_connection_open() more than once */
   
   unsigned int exit_on_disconnect : 1; /**< If #TRUE, exit after handling disconnect signal */
@@ -336,8 +330,8 @@ struct DBusConnection
 #ifndef DBUS_DISABLE_CHECKS
   unsigned int have_connection_lock : 1; /**< Used to check locking */
 #endif
-  
-#ifndef DBUS_DISABLE_CHECKS
+
+#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
   int generation; /**< _dbus_current_generation that should correspond to this connection */
 #endif 
 };
@@ -446,7 +440,40 @@ _dbus_connection_wakeup_mainloop (DBusConnection *connection)
     (*connection->wakeup_main_function) (connection->wakeup_main_data);
 }
 
-#ifdef DBUS_BUILD_TESTS
+static void
+_dbus_connection_set_dispatch(DBusConnection *connection,
+                              dbus_bool_t disabled)
+{
+  CONNECTION_LOCK (connection);
+  if (connection->dispatch_disabled != disabled)
+    {
+      DBusDispatchStatus status;
+
+      connection->dispatch_disabled = disabled;
+      status = _dbus_connection_get_dispatch_status_unlocked (connection);
+      _dbus_connection_update_dispatch_status_and_unlock (connection, status);
+    }
+  else
+    {
+      CONNECTION_UNLOCK (connection);
+    }
+}
+
+
+void
+_dbus_connection_enable_dispatch (DBusConnection *connection)
+{
+  _dbus_connection_set_dispatch (connection, FALSE);
+}
+
+void
+ _dbus_connection_disable_dispatch (DBusConnection *connection)
+{
+  _dbus_connection_set_dispatch (connection, TRUE);
+}
+
+
+#ifdef DBUS_ENABLE_EMBEDDED_TESTS
 /**
  * Gets the locks so we can examine them
  *
@@ -490,9 +517,9 @@ _dbus_connection_queue_received_message_link (DBusConnection  *connection,
   DBusPendingCall *pending;
   dbus_uint32_t reply_serial;
   DBusMessage *message;
-  
-  _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
-  
+
+  _dbus_assert (_dbus_transport_peek_is_authenticated (connection->transport));
+
   _dbus_list_append_link (&connection->incoming_messages,
                           link);
   message = link->data;
@@ -552,8 +579,21 @@ void
 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
                                                 DBusList *link)
 {
+  DBusMessage *msg, *rmsg;
+
   HAVE_LOCK_CHECK (connection);
-  
+
+  msg = (DBusMessage *)link->data;
+
+  rmsg = msg;
+  if (_dbus_transport_assure_protocol_version (connection->transport, &rmsg))
+    {
+      /* If the message is converted, then we don't need the old format anymore */
+      _dbus_list_free_link(link);
+      link = _dbus_list_alloc_link (rmsg);
+      dbus_message_unref (msg);
+    }
+
   _dbus_list_append_link (&connection->incoming_messages, link);
 
   connection->n_incoming += 1;
@@ -1354,7 +1394,7 @@ _dbus_connection_new_for_transport (DBusTransport *transport)
   connection->disconnected_message_arrived = FALSE;
   connection->disconnected_message_processed = FALSE;
   
-#ifndef DBUS_DISABLE_CHECKS
+#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
   connection->generation = _dbus_current_generation;
 #endif
   
@@ -1531,7 +1571,7 @@ _dbus_connection_handle_watch (DBusWatch                   *watch,
   return retval;
 }
 
-_DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
+/* Protected by _DBUS_LOCK (shared_connections) */
 static DBusHashTable *shared_connections = NULL;
 static DBusList *shared_connections_no_guid = NULL;
 
@@ -1555,9 +1595,14 @@ static void
 shared_connections_shutdown (void *data)
 {
   int n_entries;
-  
-  _DBUS_LOCK (shared_connections);
-  
+
+  if (!_DBUS_LOCK (shared_connections))
+    {
+      /* We'd have initialized locks before adding anything, so there
+       * can't be anything there. */
+      return;
+    }
+
   /* This is a little bit unpleasant... better ideas? */
   while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
     {
@@ -1571,7 +1616,8 @@ shared_connections_shutdown (void *data)
 
       _DBUS_UNLOCK (shared_connections);
       close_connection_on_shutdown (connection);
-      _DBUS_LOCK (shared_connections);
+      if (!_DBUS_LOCK (shared_connections))
+        _dbus_assert_not_reached ("global locks were already initialized");
 
       /* The connection should now be dead and not in our hash ... */
       _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
@@ -1590,7 +1636,8 @@ shared_connections_shutdown (void *data)
         {
           _DBUS_UNLOCK (shared_connections);
           close_connection_on_shutdown (connection);
-          _DBUS_LOCK (shared_connections);
+          if (!_DBUS_LOCK (shared_connections))
+            _dbus_assert_not_reached ("global locks were already initialized");
           connection = _dbus_list_pop_first (&shared_connections_no_guid);
         }
     }
@@ -1607,8 +1654,13 @@ connection_lookup_shared (DBusAddressEntry  *entry,
   _dbus_verbose ("checking for existing connection\n");
   
   *result = NULL;
-  
-  _DBUS_LOCK (shared_connections);
+
+  if (!_DBUS_LOCK (shared_connections))
+    {
+      /* If it was shared, we'd have initialized global locks when we put
+       * it in shared_connections. */
+      return FALSE;
+    }
 
   if (shared_connections == NULL)
     {
@@ -1706,7 +1758,8 @@ connection_record_shared_unlocked (DBusConnection *connection,
 
   if (guid == NULL)
     {
-      _DBUS_LOCK (shared_connections);
+      if (!_DBUS_LOCK (shared_connections))
+        return FALSE;
 
       if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
         {
@@ -1733,8 +1786,14 @@ connection_record_shared_unlocked (DBusConnection *connection,
       dbus_free (guid_key);
       return FALSE;
     }
-  
-  _DBUS_LOCK (shared_connections);
+
+  if (!_DBUS_LOCK (shared_connections))
+    {
+      dbus_free (guid_in_connection);
+      dbus_free (guid_key);
+      return FALSE;
+    }
+
   _dbus_assert (shared_connections != NULL);
   
   if (!_dbus_hash_table_insert_string (shared_connections,
@@ -1765,9 +1824,14 @@ connection_forget_shared_unlocked (DBusConnection *connection)
 
   if (!connection->shareable)
     return;
-  
-  _DBUS_LOCK (shared_connections);
-      
+
+  if (!_DBUS_LOCK (shared_connections))
+    {
+      /* If it was shared, we'd have initialized global locks when we put
+       * it in the table; so it can't be there. */
+      return;
+    }
+
   if (connection->server_guid != NULL)
     {
       _dbus_verbose ("dropping connection to %s out of the shared table\n",
@@ -1981,6 +2045,34 @@ _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection       *con
 {
   dbus_uint32_t serial;
 
+  /* Finish preparing the message */
+  if (dbus_message_get_serial (message) == 0)
+    {
+      serial = _dbus_connection_get_next_client_serial (connection);
+      dbus_message_set_serial (message, serial);
+      if (client_serial)
+        *client_serial = serial;
+    }
+  else
+    {
+      if (client_serial)
+        *client_serial = dbus_message_get_serial (message);
+    }
+
+  _dbus_verbose ("Message %p serial is %u\n",
+                 message, dbus_message_get_serial (message));
+
+  dbus_message_lock (message);
+
+  /* This converts message if neccessary */
+  if (!_dbus_transport_assure_protocol_version (connection->transport, &message))
+    {
+      /* Only non-converted messages must be refed.
+       * Converted messages are local anyway.
+       */
+      dbus_message_ref (message);
+    }
+
   preallocated->queue_link->data = message;
   _dbus_list_prepend_link (&connection->outgoing_messages,
                            preallocated->queue_link);
@@ -1993,8 +2085,6 @@ _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection       *con
   dbus_free (preallocated);
   preallocated = NULL;
   
-  dbus_message_ref (message);
-  
   connection->n_outgoing += 1;
 
   _dbus_verbose ("Message %p (%s %s %s %s '%s') for %s added to outgoing queue %p, %d pending to send\n",
@@ -2016,24 +2106,6 @@ _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection       *con
                  connection,
                  connection->n_outgoing);
 
-  if (dbus_message_get_serial (message) == 0)
-    {
-      serial = _dbus_connection_get_next_client_serial (connection);
-      dbus_message_set_serial (message, serial);
-      if (client_serial)
-        *client_serial = serial;
-    }
-  else
-    {
-      if (client_serial)
-        *client_serial = dbus_message_get_serial (message);
-    }
-
-  _dbus_verbose ("Message %p serial is %u\n",
-                 message, dbus_message_get_serial (message));
-  
-  dbus_message_lock (message);
-
   /* Now we need to run an iteration to hopefully just write the messages
    * out immediately, and otherwise get them queued up
    */
@@ -2150,7 +2222,7 @@ _dbus_connection_close_if_only_one_ref (DBusConnection *connection)
  * relatively long time for memory, if they were only willing to block
  * briefly then we retry for memory at a rapid rate.
  *
- * @timeout_milliseconds the timeout requested for blocking
+ * @param timeout_milliseconds the timeout requested for blocking
  */
 static void
 _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
@@ -2165,52 +2237,6 @@ _dbus_memory_pause_based_on_timeout (int timeout_milliseconds)
     _dbus_sleep_milliseconds (1000);
 }
 
-static DBusMessage *
-generate_local_error_message (dbus_uint32_t serial, 
-                              char *error_name, 
-                              char *error_msg)
-{
-  DBusMessage *message;
-  message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
-  if (!message)
-    goto out;
-
-  if (!dbus_message_set_error_name (message, error_name))
-    {
-      dbus_message_unref (message);
-      message = NULL;
-      goto out; 
-    }
-
-  dbus_message_set_no_reply (message, TRUE); 
-
-  if (!dbus_message_set_reply_serial (message,
-                                      serial))
-    {
-      dbus_message_unref (message);
-      message = NULL;
-      goto out;
-    }
-
-  if (error_msg != NULL)
-    {
-      DBusMessageIter iter;
-
-      dbus_message_iter_init_append (message, &iter);
-      if (!dbus_message_iter_append_basic (&iter,
-                                           DBUS_TYPE_STRING,
-                                           &error_msg))
-        {
-          dbus_message_unref (message);
-          message = NULL;
-         goto out;
-        }
-    }
-
- out:
-  return message;
-}
-
 /*
  * Peek the incoming queue to see if we got reply for a specific serial
  */
@@ -2308,10 +2334,11 @@ complete_pending_call_and_unlock (DBusConnection  *connection,
 {
   _dbus_pending_call_set_reply_unlocked (pending, message);
   _dbus_pending_call_ref_unlocked (pending); /* in case there's no app with a ref held */
+  _dbus_pending_call_start_completion_unlocked(pending);
   _dbus_connection_detach_pending_call_and_unlock (connection, pending);
+
   /* Must be called unlocked since it invokes app callback */
-  _dbus_pending_call_complete (pending);
+  _dbus_pending_call_finish_completion (pending);
   dbus_pending_call_unref (pending);
 }
 
@@ -2388,7 +2415,7 @@ _dbus_connection_block_pending_call (DBusPendingCall *pending)
    * below
    */
   timeout = _dbus_pending_call_get_timeout_unlocked (pending);
-  _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
+  _dbus_get_monotonic_time (&start_tv_sec, &start_tv_usec);
   if (timeout)
     {
       timeout_milliseconds = dbus_timeout_get_interval (timeout);
@@ -2445,7 +2472,7 @@ _dbus_connection_block_pending_call (DBusPendingCall *pending)
         return;
     }
   
-  _dbus_get_current_time (&tv_sec, &tv_usec);
+  _dbus_get_monotonic_time (&tv_sec, &tv_usec);
   elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
          (tv_usec - start_tv_usec) / 1000;
   
@@ -2453,12 +2480,14 @@ _dbus_connection_block_pending_call (DBusPendingCall *pending)
     {
       DBusMessage *error_msg;
 
-      error_msg = generate_local_error_message (client_serial,
-                                                DBUS_ERROR_DISCONNECTED, 
-                                                "Connection was disconnected before a reply was received"); 
+      error_msg = _dbus_generate_local_error_message (client_serial,
+                                                      DBUS_ERROR_DISCONNECTED,
+                                                      "Connection was disconnected before a reply was received");
 
       /* on OOM error_msg is set to NULL */
       complete_pending_call_and_unlock (connection, pending, error_msg);
+      if (error_msg != NULL)
+        dbus_message_unref (error_msg);
       dbus_pending_call_unref (pending);
       return;
     }
@@ -2508,7 +2537,7 @@ _dbus_connection_block_pending_call (DBusPendingCall *pending)
         {          
           /* block again, we don't have the reply buffered yet. */
           _dbus_connection_do_iteration_unlocked (connection,
-                                                  NULL,
+                                                  pending,
                                                   DBUS_ITERATION_DO_READING |
                                                   DBUS_ITERATION_BLOCK,
                                                   timeout_milliseconds - elapsed_milliseconds);
@@ -2532,6 +2561,33 @@ _dbus_connection_block_pending_call (DBusPendingCall *pending)
   dbus_pending_call_unref (pending);
 }
 
+/**
+ * Return how many file descriptors are pending in the loader
+ *
+ * @param connection the connection
+ */
+int
+_dbus_connection_get_pending_fds_count (DBusConnection *connection)
+{
+  return _dbus_transport_get_pending_fds_count (connection->transport);
+}
+
+/**
+ * Register a function to be called whenever the number of pending file
+ * descriptors in the loader change.
+ *
+ * @param connection the connection
+ * @param callback the callback
+ */
+void
+_dbus_connection_set_pending_fds_function (DBusConnection *connection,
+                                           DBusPendingFdsChangeFunction callback,
+                                           void *data)
+{
+  _dbus_transport_set_pending_fds_function (connection->transport,
+                                            callback, data);
+}
+
 /** @} */
 
 /**
@@ -2683,6 +2739,7 @@ _dbus_connection_last_unref (DBusConnection *connection)
   dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
   dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
   dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
+  dbus_connection_set_windows_user_function (connection, NULL, NULL, NULL);
   
   _dbus_watch_list_free (connection->watches);
   connection->watches = NULL;
@@ -2713,8 +2770,6 @@ _dbus_connection_last_unref (DBusConnection *connection)
   _dbus_hash_table_unref (connection->pending_replies);
   connection->pending_replies = NULL;
   
-  _dbus_list_clear (&connection->filter_list);
-  
   _dbus_list_foreach (&connection->outgoing_messages,
                       free_outgoing_message,
                      connection);
@@ -2745,7 +2800,7 @@ _dbus_connection_last_unref (DBusConnection *connection)
   _dbus_rmutex_free_at_location (&connection->slot_mutex);
 
   _dbus_rmutex_free_at_location (&connection->mutex);
-  
+
   dbus_free (connection);
 }
 
@@ -2788,8 +2843,8 @@ dbus_connection_unref (DBusConnection *connection)
         {
           _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",
                                    connection->shareable ?
-                                   "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection.\n" : 
-                                    "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.\n");
+                                   "Most likely, the application called unref() too many times and removed a reference belonging to libdbus, since this is a shared connection." :
+                                    "Most likely, the application was supposed to call dbus_connection_close(), since this is a private connection.");
           return;
         }
 #endif
@@ -2896,7 +2951,7 @@ dbus_connection_close (DBusConnection *connection)
     {
       CONNECTION_UNLOCK (connection);
 
-      _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.\n");
+      _dbus_warn_check_failed ("Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application.");
       return;
     }
 #endif
@@ -2952,9 +3007,9 @@ dbus_connection_get_is_authenticated (DBusConnection *connection)
   dbus_bool_t res;
 
   _dbus_return_val_if_fail (connection != NULL, FALSE);
-  
+
   CONNECTION_LOCK (connection);
-  res = _dbus_transport_get_is_authenticated (connection->transport);
+  res = _dbus_transport_try_to_authenticate (connection->transport);
   CONNECTION_UNLOCK (connection);
   
   return res;
@@ -3014,7 +3069,7 @@ dbus_connection_get_is_anonymous (DBusConnection *connection)
  * dbus_bus_get_id() instead (which is just a convenience wrapper
  * around the org.freedesktop.DBus.GetId method invoked on the bus).
  *
- * You can also get a machine ID; see dbus_get_local_machine_id() to
+ * You can also get a machine ID; see dbus_try_get_local_machine_id() to
  * get the machine you are on.  There isn't a convenience wrapper, but
  * you can invoke org.freedesktop.DBus.Peer.GetMachineId on any peer
  * to get the machine ID on the other end.
@@ -3391,6 +3446,7 @@ dbus_connection_send_with_reply (DBusConnection     *connection,
       return TRUE;
     }
 
+  _dbus_message_set_timeout_ms(message, timeout_milliseconds);
   pending = _dbus_pending_call_new_unlocked (connection,
                                              timeout_milliseconds,
                                              reply_handler_timeout);
@@ -3500,6 +3556,22 @@ dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
   _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, NULL);
   _dbus_return_val_if_error_is_set (error, NULL);
 
+  if (_dbus_transport_can_send_sync_call (connection->transport))
+    {
+      dbus_int32_t serial;
+
+      /* set serial */
+      serial = dbus_message_get_serial (message);
+      if (serial == 0)
+        {
+          serial = _dbus_connection_get_next_client_serial (connection);
+          dbus_message_set_serial (message, serial);
+        }
+
+      reply = _dbus_transport_send_sync_call (connection->transport, message);
+      goto out;
+    }
+
 #ifdef HAVE_UNIX_FD_PASSING
 
   CONNECTION_LOCK (connection);
@@ -3535,9 +3607,11 @@ dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
   /* call_complete_and_unlock() called from pending_call_block() should
    * always fill this in.
    */
+
+out:
   _dbus_assert (reply != NULL);
   
-   if (dbus_set_error_from_message (error, reply))
+  if (dbus_set_error_from_message (error, reply))
     {
       dbus_message_unref (reply);
       return NULL;
@@ -3938,7 +4012,7 @@ _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
       link = _dbus_list_pop_first_link (&connection->incoming_messages);
       connection->n_incoming -= 1;
 
-      _dbus_verbose ("Message %p (%s %s %s %s '%s') removed from incoming queue %p, %d incoming\n",
+      _dbus_verbose ("Message %p (%s %s %s %s sig:'%s' serial:%u) removed from incoming queue %p, %d incoming\n",
                      link->data,
                      dbus_message_type_to_string (dbus_message_get_type (link->data)),
                      dbus_message_get_path (link->data) ?
@@ -3951,6 +4025,7 @@ _dbus_connection_pop_message_link_unlocked (DBusConnection *connection)
                      dbus_message_get_member (link->data) :
                      "no member",
                      dbus_message_get_signature (link->data),
+                     dbus_message_get_serial (link->data),
                      connection, connection->n_incoming);
 
       _dbus_message_trace_ref (link->data, -1, -1,
@@ -4022,6 +4097,82 @@ _dbus_connection_putback_message_link_unlocked (DBusConnection *connection,
       "_dbus_connection_putback_message_link_unlocked");
 }
 
+dbus_bool_t
+_dbus_connection_putback_message (DBusConnection *connection,
+                                  DBusMessage    *after_message,
+                                  DBusMessage    *message,
+                                  DBusError      *error)
+{
+  DBusDispatchStatus status;
+  DBusList *message_link = _dbus_list_alloc_link (message);
+  DBusList *after_link;
+  if (message_link == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      return FALSE;
+    }
+  dbus_message_ref (message);
+
+  CONNECTION_LOCK (connection);
+  _dbus_connection_acquire_dispatch (connection);
+  HAVE_LOCK_CHECK (connection);
+
+  after_link = _dbus_list_find_first(&connection->incoming_messages, after_message);
+  _dbus_list_insert_after_link (&connection->incoming_messages, after_link, message_link);
+  connection->n_incoming += 1;
+
+  _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n",
+                 message_link->data,
+                 dbus_message_type_to_string (dbus_message_get_type (message_link->data)),
+                 dbus_message_get_interface (message_link->data) ?
+                 dbus_message_get_interface (message_link->data) :
+                 "no interface",
+                 dbus_message_get_member (message_link->data) ?
+                 dbus_message_get_member (message_link->data) :
+                 "no member",
+                 dbus_message_get_signature (message_link->data),
+                 connection, connection->n_incoming);
+
+  _dbus_message_trace_ref (message_link->data, -1, -1,
+      "_dbus_connection_putback_message");
+
+  _dbus_connection_release_dispatch (connection);
+
+  status = _dbus_connection_get_dispatch_status_unlocked (connection);
+  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
+
+  return TRUE;
+}
+
+dbus_bool_t
+_dbus_connection_remove_message (DBusConnection *connection,
+                                 DBusMessage *message)
+{
+  DBusDispatchStatus status;
+  dbus_bool_t removed;
+
+  CONNECTION_LOCK (connection);
+  _dbus_connection_acquire_dispatch (connection);
+  HAVE_LOCK_CHECK (connection);
+
+  removed = _dbus_list_remove(&connection->incoming_messages, message);
+
+  if (removed)
+    {
+      connection->n_incoming -= 1;
+      dbus_message_unref(message);
+      _dbus_verbose ("Message %p removed from incoming queue\n", message);
+    }
+  else
+      _dbus_verbose ("Message %p not found in the incoming queue\n", message);
+
+  _dbus_connection_release_dispatch (connection);
+
+  status = _dbus_connection_get_dispatch_status_unlocked (connection);
+  _dbus_connection_update_dispatch_status_and_unlock (connection, status);
+  return removed;
+}
+
 /**
  * Returns the first-received message from the incoming message queue,
  * removing it from the queue. The caller owns a reference to the
@@ -4205,8 +4356,9 @@ static DBusDispatchStatus
 _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
 {
   HAVE_LOCK_CHECK (connection);
-  
-  if (connection->n_incoming > 0)
+  if (connection->dispatch_disabled)
+    return DBUS_DISPATCH_COMPLETE;
+  else if (connection->n_incoming > 0)
     return DBUS_DISPATCH_DATA_REMAINS;
   else if (!_dbus_transport_queue_messages (connection->transport))
     return DBUS_DISPATCH_NEED_MEMORY;
@@ -4390,15 +4542,24 @@ _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
                                         "GetMachineId"))
     {
       DBusString uuid;
-      
-      ret = dbus_message_new_method_return (message);
-      if (ret == NULL)
+      DBusError error = DBUS_ERROR_INIT;
+
+      if (!_dbus_string_init (&uuid))
         goto out;
 
-      _dbus_string_init (&uuid);
-      if (_dbus_get_local_machine_uuid_encoded (&uuid))
+      if (_dbus_get_local_machine_uuid_encoded (&uuid, &error))
         {
-          const char *v_STRING = _dbus_string_get_const_data (&uuid);
+          const char *v_STRING;
+
+          ret = dbus_message_new_method_return (message);
+
+          if (ret == NULL)
+            {
+              _dbus_string_free (&uuid);
+              goto out;
+            }
+
+          v_STRING = _dbus_string_get_const_data (&uuid);
           if (dbus_message_append_args (ret,
                                         DBUS_TYPE_STRING, &v_STRING,
                                         DBUS_TYPE_INVALID))
@@ -4406,6 +4567,25 @@ _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
               sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
             }
         }
+      else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+        {
+          dbus_error_free (&error);
+          _dbus_string_free (&uuid);
+          goto out;
+        }
+      else
+        {
+          ret = dbus_message_new_error (message, error.name, error.message);
+          dbus_error_free (&error);
+          _dbus_string_free (&uuid);
+
+          if (ret == NULL)
+            goto out;
+
+          sent = _dbus_connection_send_unlocked_no_update (connection, ret,
+                                                           NULL);
+        }
+
       _dbus_string_free (&uuid);
     }
   else
@@ -4643,6 +4823,8 @@ dbus_connection_dispatch (DBusConnection *connection)
   
   CONNECTION_LOCK (connection);
 
+  if (result == DBUS_HANDLER_RESULT_LATER)
+      goto out;
   if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
     {
       _dbus_verbose ("No memory\n");
@@ -4765,9 +4947,11 @@ dbus_connection_dispatch (DBusConnection *connection)
                  connection);
   
  out:
-  if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
+  if (result == DBUS_HANDLER_RESULT_LATER ||
+      result == DBUS_HANDLER_RESULT_NEED_MEMORY)
     {
-      _dbus_verbose ("out of memory\n");
+      if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
+        _dbus_verbose ("out of memory\n");
       
       /* Put message back, and we'll start over.
        * Yes this means handlers must be idempotent if they
@@ -5103,20 +5287,41 @@ dbus_connection_get_socket(DBusConnection              *connection,
                            int                         *fd)
 {
   dbus_bool_t retval;
+  DBusSocket s = DBUS_SOCKET_INIT;
 
   _dbus_return_val_if_fail (connection != NULL, FALSE);
   _dbus_return_val_if_fail (connection->transport != NULL, FALSE);
   
   CONNECTION_LOCK (connection);
   
-  retval = _dbus_transport_get_socket_fd (connection->transport,
-                                          fd);
+  retval = _dbus_transport_get_socket_fd (connection->transport, &s);
+
+  if (retval)
+    {
+      *fd = _dbus_socket_get_int (s);
+    }
 
   CONNECTION_UNLOCK (connection);
 
   return retval;
 }
 
+/**
+ *
+ * Getter for number of messages in incoming queue.
+ * Useful for sending reply to self (see kdbus_do_iteration)
+ */
+int
+_dbus_connection_get_n_incoming (DBusConnection *connection)
+{
+  return connection->n_incoming;
+}
+
+dbus_bool_t
+_dbus_connection_is_overflowed (DBusConnection *connection)
+{
+  return _dbus_transport_get_overflowed (connection->transport);
+}
 
 /**
  * Gets the UNIX user ID of the connection if known.  Returns #TRUE if
@@ -5148,10 +5353,10 @@ dbus_connection_get_unix_user (DBusConnection *connection,
 
   _dbus_return_val_if_fail (connection != NULL, FALSE);
   _dbus_return_val_if_fail (uid != NULL, FALSE);
-  
+
   CONNECTION_LOCK (connection);
 
-  if (!_dbus_transport_get_is_authenticated (connection->transport))
+  if (!_dbus_transport_try_to_authenticate (connection->transport))
     result = FALSE;
   else
     result = _dbus_transport_get_unix_user (connection->transport,
@@ -5184,10 +5389,10 @@ dbus_connection_get_unix_process_id (DBusConnection *connection,
 
   _dbus_return_val_if_fail (connection != NULL, FALSE);
   _dbus_return_val_if_fail (pid != NULL, FALSE);
-  
+
   CONNECTION_LOCK (connection);
 
-  if (!_dbus_transport_get_is_authenticated (connection->transport))
+  if (!_dbus_transport_try_to_authenticate (connection->transport))
     result = FALSE;
   else
     result = _dbus_transport_get_unix_process_id (connection->transport,
@@ -5205,7 +5410,8 @@ dbus_connection_get_unix_process_id (DBusConnection *connection,
  * connection.
  *
  * @param connection the connection
- * @param data return location for audit data 
+ * @param data return location for audit data
+ * @param data_size return location for length of audit data
  * @returns #TRUE if audit data is filled in with a valid ucred pointer
  */
 dbus_bool_t
@@ -5218,10 +5424,10 @@ dbus_connection_get_adt_audit_session_data (DBusConnection *connection,
   _dbus_return_val_if_fail (connection != NULL, FALSE);
   _dbus_return_val_if_fail (data != NULL, FALSE);
   _dbus_return_val_if_fail (data_size != NULL, FALSE);
-  
+
   CONNECTION_LOCK (connection);
 
-  if (!_dbus_transport_get_is_authenticated (connection->transport))
+  if (!_dbus_transport_try_to_authenticate (connection->transport))
     result = FALSE;
   else
     result = _dbus_transport_get_adt_audit_session_data (connection->transport,
@@ -5275,6 +5481,32 @@ dbus_connection_set_unix_user_function (DBusConnection             *connection,
     (* old_free_function) (old_data);
 }
 
+/* Same calling convention as dbus_connection_get_windows_user */
+dbus_bool_t
+_dbus_connection_get_linux_security_label (DBusConnection  *connection,
+                                           char           **label_p)
+{
+  dbus_bool_t result;
+
+  _dbus_assert (connection != NULL);
+  _dbus_assert (label_p != NULL);
+
+  CONNECTION_LOCK (connection);
+
+  if (!_dbus_transport_try_to_authenticate (connection->transport))
+    result = FALSE;
+  else
+    result = _dbus_transport_get_linux_security_label (connection->transport,
+                                                       label_p);
+#ifndef __linux__
+  _dbus_assert (!result);
+#endif
+
+  CONNECTION_UNLOCK (connection);
+
+  return result;
+}
+
 /**
  * Gets the Windows user SID of the connection if known.  Returns
  * #TRUE if the ID is filled in.  Always returns #FALSE on non-Windows
@@ -5314,10 +5546,10 @@ dbus_connection_get_windows_user (DBusConnection             *connection,
 
   _dbus_return_val_if_fail (connection != NULL, FALSE);
   _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE);
-  
+
   CONNECTION_LOCK (connection);
 
-  if (!_dbus_transport_get_is_authenticated (connection->transport))
+  if (!_dbus_transport_try_to_authenticate (connection->transport))
     result = FALSE;
   else
     result = _dbus_transport_get_windows_user (connection->transport,
@@ -5435,7 +5667,7 @@ dbus_connection_set_route_peer_messages (DBusConnection             *connection,
   _dbus_return_if_fail (connection != NULL);
   
   CONNECTION_LOCK (connection);
-  connection->route_peer_messages = TRUE;
+  connection->route_peer_messages = value;
   CONNECTION_UNLOCK (connection);
 }
 
@@ -5550,7 +5782,7 @@ dbus_connection_remove_filter (DBusConnection            *connection,
 #ifndef DBUS_DISABLE_CHECKS
   if (filter == NULL)
     {
-      _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
+      _dbus_warn_check_failed ("Attempt to remove filter function %p user data %p, but no such filter has been added",
                                function, user_data);
       return;
     }
@@ -5669,7 +5901,7 @@ dbus_connection_register_object_path (DBusConnection              *connection,
 
   if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
     {
-      _dbus_warn ("%s\n", error.message);
+      _dbus_warn ("%s", error.message);
       dbus_error_free (&error);
       return FALSE;
     }
@@ -5741,7 +5973,7 @@ dbus_connection_register_fallback (DBusConnection              *connection,
 
   if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
     {
-      _dbus_warn ("%s\n", error.message);
+      _dbus_warn ("%s", error.message);
       dbus_error_free (&error);
       return FALSE;
     }
@@ -5852,8 +6084,8 @@ dbus_connection_list_registered (DBusConnection              *connection,
   return retval;
 }
 
-static DBusDataSlotAllocator slot_allocator;
-_DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
+static DBusDataSlotAllocator slot_allocator =
+  _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (connection_slots));
 
 /**
  * Allocates an integer ID to be used for storing application-specific
@@ -5873,7 +6105,6 @@ dbus_bool_t
 dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
 {
   return _dbus_data_slot_allocator_alloc (&slot_allocator,
-                                          &_DBUS_LOCK_NAME (connection_slots),
                                           slot_p);
 }
 
@@ -5974,7 +6205,8 @@ dbus_connection_get_data (DBusConnection   *connection,
   void *res;
 
   _dbus_return_val_if_fail (connection != NULL, NULL);
-  
+  _dbus_return_val_if_fail (slot >= 0, NULL);
+
   SLOTS_LOCK (connection);
 
   res = _dbus_data_slot_list_get (&slot_allocator,
@@ -6043,7 +6275,7 @@ dbus_connection_get_max_message_size (DBusConnection *connection)
  * result in disconnecting the connection.
  *
  * @param connection a #DBusConnection
- * @param size maximum message unix fds the connection can receive
+ * @param n maximum message unix fds the connection can receive
  */
 void
 dbus_connection_set_max_message_unix_fds (DBusConnection *connection,
@@ -6141,7 +6373,7 @@ dbus_connection_get_max_received_size (DBusConnection *connection)
  * The semantics are analogous to those of dbus_connection_set_max_received_size().
  *
  * @param connection the connection
- * @param size the maximum size in bytes of all outstanding messages
+ * @param n the maximum size in bytes of all outstanding messages
  */
 void
 dbus_connection_set_max_received_unix_fds (DBusConnection *connection,
@@ -6258,7 +6490,7 @@ dbus_connection_get_outgoing_unix_fds (DBusConnection *connection)
   return res;
 }
 
-#ifdef DBUS_BUILD_TESTS
+#ifdef DBUS_ENABLE_EMBEDDED_TESTS
 /**
  * Returns the address of the transport object of this connection
  *