2003-04-25 Havoc Pennington <hp@redhat.com>
authorHavoc Pennington <hp@redhat.com>
Fri, 25 Apr 2003 23:50:34 +0000 (23:50 +0000)
committerHavoc Pennington <hp@redhat.com>
Fri, 25 Apr 2003 23:50:34 +0000 (23:50 +0000)
        test suite is slightly hosed at the moment, will fix soon

* bus/connection.c (bus_connections_expire_incomplete): fix to
properly disable the timeout when required
(bus_connection_set_name): check whether we can remove incomplete
connections timeout after we complete each connection.

* dbus/dbus-mainloop.c (check_timeout): fix this up a bit,
probably still broken.

* bus/services.c (bus_registry_acquire_service): implement max
number of services owned, and honor allow/deny rules on which
services a connection can own.

* bus/connection.c (bus_connection_get_policy): report errors here

* bus/activation.c: implement limit on number of pending
activations

13 files changed:
ChangeLog
bus/activation.c
bus/bus.c
bus/bus.h
bus/config-parser.c
bus/connection.c
bus/connection.h
bus/driver.c
bus/services.c
dbus/dbus-mainloop.c
dbus/dbus-timeout.c
doc/config-file.txt
test/data/valid-config-files/basic.conf

index 4448c57..8ed52f0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,26 @@
 2003-04-25  Havoc Pennington  <hp@redhat.com>
 
+        test suite is slightly hosed at the moment, will fix soon
+       
+       * bus/connection.c (bus_connections_expire_incomplete): fix to
+       properly disable the timeout when required
+       (bus_connection_set_name): check whether we can remove incomplete
+       connections timeout after we complete each connection.
+
+       * dbus/dbus-mainloop.c (check_timeout): fix this up a bit,
+       probably still broken.
+
+       * bus/services.c (bus_registry_acquire_service): implement max
+       number of services owned, and honor allow/deny rules on which 
+       services a connection can own.
+
+       * bus/connection.c (bus_connection_get_policy): report errors here
+
+       * bus/activation.c: implement limit on number of pending
+       activations
+
+2003-04-25  Havoc Pennington  <hp@redhat.com>
+
        * dbus/dbus-transport.c (_dbus_transport_get_unix_user): fix bug
        where we used >= 0 instead of != DBUS_UID_UNSET.
 
index a569e1a..c50f1f2 100644 (file)
@@ -45,6 +45,10 @@ struct BusActivation
   DBusHashTable *pending_activations;
   char *server_address;
   BusContext *context;
+  int n_pending_activations; /**< This is in fact the number of BusPendingActivationEntry,
+                              * i.e. number of pending activation requests, not pending
+                              * activations per se
+                              */
 };
 
 typedef struct
@@ -67,6 +71,7 @@ typedef struct
   BusActivation *activation;
   char *service_name;
   DBusList *entries;
+  int n_entries;
   DBusBabysitter *babysitter;
   DBusTimeout *timeout;
   unsigned int timeout_added : 1;
@@ -150,6 +155,11 @@ bus_pending_activation_unref (BusPendingActivation *pending_activation)
       link = _dbus_list_get_next_link (&pending_activation->entries, link);
     }
   _dbus_list_clear (&pending_activation->entries);
+
+  pending_activation->activation->n_pending_activations -=
+    pending_activation->n_entries;
+
+  _dbus_assert (pending_activation->activation->n_pending_activations >= 0);
   
   dbus_free (pending_activation);
 }
@@ -394,6 +404,7 @@ bus_activation_new (BusContext        *context,
   
   activation->refcount = 1;
   activation->context = context;
+  activation->n_pending_activations = 0;
   
   if (!_dbus_string_copy_data (address, &activation->server_address))
     {
@@ -838,6 +849,15 @@ bus_activation_activate_service (BusActivation  *activation,
   dbus_bool_t retval;
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  if (activation->n_pending_activations >=
+      bus_context_get_max_pending_activations (activation->context))
+    {
+      dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
+                     "The maximum number of pending activations has been reached, activation of %s failed",
+                     service_name);
+      return FALSE;
+    }
   
   entry = _dbus_hash_table_lookup_string (activation->entries, service_name);
 
@@ -902,9 +922,6 @@ bus_activation_activate_service (BusActivation  *activation,
   pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name);
   if (pending_activation)
     {
-      /* FIXME security - a client could keep sending activations over and
-       * over, growing this queue.
-       */
       if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry))
        {
           _dbus_verbose ("Failed to append a new entry to pending activation\n");
@@ -913,6 +930,9 @@ bus_activation_activate_service (BusActivation  *activation,
          bus_pending_activation_entry_free (pending_activation_entry);
          return FALSE;
        }
+
+      pending_activation->n_entries += 1;
+      pending_activation->activation->n_pending_activations += 1;
     }
   else
     {
@@ -980,6 +1000,9 @@ bus_activation_activate_service (BusActivation  *activation,
          bus_pending_activation_entry_free (pending_activation_entry);   
          return FALSE;
        }
+
+      pending_activation->n_entries += 1;
+      pending_activation->activation->n_pending_activations += 1;
       
       if (!_dbus_hash_table_insert_string (activation->pending_activations,
                                           pending_activation->service_name,
index 7bb4bf9..dc0cb56 100644 (file)
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -825,6 +825,18 @@ bus_context_get_max_connections_per_user (BusContext *context)
   return context->limits.max_connections_per_user;
 }
 
+int
+bus_context_get_max_pending_activations (BusContext *context)
+{
+  return context->limits.max_pending_activations;
+}
+
+int
+bus_context_get_max_services_per_connection (BusContext *context)
+{
+  return context->limits.max_services_per_connection;
+}
+
 dbus_bool_t
 bus_context_check_security_policy (BusContext     *context,
                                    DBusConnection *sender,
@@ -840,7 +852,13 @@ bus_context_check_security_policy (BusContext     *context,
   if (sender != NULL)
     {
       _dbus_assert (dbus_connection_get_is_authenticated (sender));
-      sender_policy = bus_connection_get_policy (sender);
+      sender_policy = bus_connection_get_policy (sender, error);
+      if (sender_policy == NULL)
+        {
+          _DBUS_ASSERT_ERROR_IS_SET (error);
+          return FALSE;
+        }
+      return FALSE;
     }
   else
     sender_policy = NULL;
@@ -848,12 +866,18 @@ bus_context_check_security_policy (BusContext     *context,
   if (recipient != NULL)
     {
       _dbus_assert (dbus_connection_get_is_authenticated (recipient));
-      recipient_policy = bus_connection_get_policy (recipient);
+      recipient_policy = bus_connection_get_policy (recipient, error);
+      if (recipient_policy == NULL)
+        {
+          _DBUS_ASSERT_ERROR_IS_SET (error);
+          return FALSE;
+        }
+      return FALSE;
     }
   else
     recipient_policy = NULL;
 
-  if (sender_policy &&
+  if (sender &&
       !bus_client_policy_check_can_send (sender_policy,
                                          context->registry, recipient,
                                          message))
@@ -869,7 +893,7 @@ bus_context_check_security_policy (BusContext     *context,
       return FALSE;
     }
 
-  if (recipient_policy &&
+  if (recipient &&
       !bus_client_policy_check_can_receive (recipient_policy,
                                             context->registry, sender,
                                             message))
index 7cffb33..8431ca2 100644 (file)
--- a/bus/bus.h
+++ b/bus/bus.h
@@ -44,44 +44,46 @@ typedef struct BusTransaction   BusTransaction;
 
 typedef struct
 {
-  long max_incoming_bytes;          /**< How many incoming messages for a connection */
-  long max_outgoing_bytes;          /**< How many outgoing bytes can be queued for a connection */
+  long max_incoming_bytes;          /**< How many incoming messages for a single connection */
+  long max_outgoing_bytes;          /**< How many outgoing bytes can be queued for a single connection */
   long max_message_size;            /**< Max size of a single message in bytes */
   int activation_timeout;           /**< How long to wait for an activation to time out */
   int auth_timeout;                 /**< How long to wait for an authentication to time out */
   int max_completed_connections;    /**< Max number of authorized connections */
   int max_incomplete_connections;   /**< Max number of incomplete connections */
   int max_connections_per_user;     /**< Max number of connections auth'd as same user */
+  int max_pending_activations;      /**< Max number of pending activations for the entire bus */
+  int max_services_per_connection;  /**< Max number of owned services for a single connection */
 } BusLimits;
 
-BusContext*       bus_context_new                            (const DBusString *config_file,
-                                                              int               print_addr_fd,
-                                                              DBusError        *error);
-void              bus_context_shutdown                       (BusContext       *context);
-void              bus_context_ref                            (BusContext       *context);
-void              bus_context_unref                          (BusContext       *context);
-const char*       bus_context_get_type                       (BusContext       *context);
-const char*       bus_context_get_address                    (BusContext       *context);
-BusRegistry*      bus_context_get_registry                   (BusContext       *context);
-BusConnections*   bus_context_get_connections                (BusContext       *context);
-BusActivation*    bus_context_get_activation                 (BusContext       *context);
-DBusLoop*         bus_context_get_loop                       (BusContext       *context);
-DBusUserDatabase* bus_context_get_user_database              (BusContext       *context);
-dbus_bool_t       bus_context_allow_user                     (BusContext       *context,
-                                                              unsigned long     uid);
-BusClientPolicy*  bus_context_create_client_policy           (BusContext       *context,
-                                                              DBusConnection   *connection);
-int               bus_context_get_activation_timeout         (BusContext       *context);
-int               bus_context_get_auth_timeout               (BusContext       *context);
-int               bus_context_get_max_completed_connections  (BusContext       *context);
-int               bus_context_get_max_incomplete_connections (BusContext       *context);
-int               bus_context_get_max_connections_per_user   (BusContext       *context);
-dbus_bool_t       bus_context_check_security_policy          (BusContext       *context,
-                                                              DBusConnection   *sender,
-                                                              DBusConnection   *recipient,
-                                                              DBusMessage      *message,
-                                                              DBusError        *error);
-
-
+BusContext*       bus_context_new                             (const DBusString *config_file,
+                                                               int               print_addr_fd,
+                                                               DBusError        *error);
+void              bus_context_shutdown                        (BusContext       *context);
+void              bus_context_ref                             (BusContext       *context);
+void              bus_context_unref                           (BusContext       *context);
+const char*       bus_context_get_type                        (BusContext       *context);
+const char*       bus_context_get_address                     (BusContext       *context);
+BusRegistry*      bus_context_get_registry                    (BusContext       *context);
+BusConnections*   bus_context_get_connections                 (BusContext       *context);
+BusActivation*    bus_context_get_activation                  (BusContext       *context);
+DBusLoop*         bus_context_get_loop                        (BusContext       *context);
+DBusUserDatabase* bus_context_get_user_database               (BusContext       *context);
+dbus_bool_t       bus_context_allow_user                      (BusContext       *context,
+                                                               unsigned long     uid);
+BusClientPolicy*  bus_context_create_client_policy            (BusContext       *context,
+                                                               DBusConnection   *connection);
+int               bus_context_get_activation_timeout          (BusContext       *context);
+int               bus_context_get_auth_timeout                (BusContext       *context);
+int               bus_context_get_max_completed_connections   (BusContext       *context);
+int               bus_context_get_max_incomplete_connections  (BusContext       *context);
+int               bus_context_get_max_connections_per_user    (BusContext       *context);
+int               bus_context_get_max_pending_activations     (BusContext       *context);
+int               bus_context_get_max_services_per_connection (BusContext       *context);
+dbus_bool_t       bus_context_check_security_policy           (BusContext       *context,
+                                                               DBusConnection   *sender,
+                                                               DBusConnection   *recipient,
+                                                               DBusMessage      *message,
+                                                               DBusError        *error);
 
 #endif /* BUS_BUS_H */
index bd1c47b..5e27963 100644 (file)
@@ -306,7 +306,7 @@ bus_config_parser_new (const DBusString *basedir)
    * and legitimate auth will fail.  If interactive auth (ask user for
    * password) is allowed, then potentially it has to be quite long.
    */     
-  parser->limits.auth_timeout = 3000; /* 3 seconds */
+  parser->limits.auth_timeout = 30000; /* 30 seconds */
 
   parser->limits.max_incomplete_connections = 32;
   parser->limits.max_connections_per_user = 128;
@@ -316,6 +316,9 @@ bus_config_parser_new (const DBusString *basedir)
    * DOS all the other users.
    */
   parser->limits.max_completed_connections = 1024;
+
+  parser->limits.max_pending_activations = 256;
+  parser->limits.max_services_per_connection = 256;
   
   parser->refcount = 1;
 
@@ -1215,6 +1218,18 @@ set_limit (BusConfigParser *parser,
       must_be_int = TRUE;
       parser->limits.max_connections_per_user = value;
     }
+  else if (strcmp (name, "max_pending_activations") == 0)
+    {
+      must_be_positive = TRUE;
+      must_be_int = TRUE;
+      parser->limits.max_pending_activations = value;
+    }
+  else if (strcmp (name, "max_services_per_connection") == 0)
+    {
+      must_be_positive = TRUE;
+      must_be_int = TRUE;
+      parser->limits.max_services_per_connection = value;
+    }
   else
     {
       dbus_set_error (error, DBUS_ERROR_FAILED,
index 68429b2..8907227 100644 (file)
@@ -52,6 +52,7 @@ typedef struct
   DBusList *link_in_connection_list;
   DBusConnection *connection;
   DBusList *services_owned;
+  int n_services_owned;
   char *name;
   DBusList *transaction_messages; /**< Stuff we need to send as part of a transaction */
   DBusMessage *oom_message;
@@ -387,6 +388,7 @@ free_connection_data (void *data)
 
   /* services_owned should be NULL since we should be disconnected */
   _dbus_assert (d->services_owned == NULL);
+  _dbus_assert (d->n_services_owned == 0);
   /* similarly */
   _dbus_assert (d->transaction_messages == NULL);
 
@@ -662,52 +664,54 @@ void
 bus_connections_expire_incomplete (BusConnections *connections)
 {    
   int next_interval;
-  long tv_sec, tv_usec;
-  DBusList *link;
-  int auth_timeout;
-  
-  if (connections->incomplete == NULL)
-    return;
 
-  _dbus_get_current_time (&tv_sec, &tv_usec);
-  auth_timeout = bus_context_get_auth_timeout (connections->context);
   next_interval = -1;
   
-  link = _dbus_list_get_first_link (&connections->incomplete);
-  while (link != NULL)
+  if (connections->incomplete != NULL)
     {
-      DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link);
-      DBusConnection *connection;
-      BusConnectionData *d;
-      double elapsed;
+      long tv_sec, tv_usec;
+      DBusList *link;
+      int auth_timeout;
       
-      connection = link->data;
+      _dbus_get_current_time (&tv_sec, &tv_usec);
+      auth_timeout = bus_context_get_auth_timeout (connections->context);
+  
+      link = _dbus_list_get_first_link (&connections->incomplete);
+      while (link != NULL)
+        {
+          DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link);
+          DBusConnection *connection;
+          BusConnectionData *d;
+          double elapsed;
       
-      d = BUS_CONNECTION_DATA (connection);
+          connection = link->data;
       
-      _dbus_assert (d != NULL);
+          d = BUS_CONNECTION_DATA (connection);
       
-      elapsed = ((double) tv_sec - (double) d->connection_tv_sec) * 1000.0 +
-        ((double) tv_usec - (double) d->connection_tv_usec) / 1000.0;
+          _dbus_assert (d != NULL);
+      
+          elapsed = ((double) tv_sec - (double) d->connection_tv_sec) * 1000.0 +
+            ((double) tv_usec - (double) d->connection_tv_usec) / 1000.0;
 
-      if (elapsed > (double) auth_timeout)
-        {
-          _dbus_verbose ("Timing out authentication for connection %p\n", connection);
-          dbus_connection_disconnect (connection);
-        }
-      else
-        {
-          /* We can end the loop, since the connections are in oldest-first order */
-          next_interval = auth_timeout - (int) elapsed;
-          _dbus_verbose ("Connection %p authentication expires in %d milliseconds\n",
-                         connection, next_interval);
+          if (elapsed >= (double) auth_timeout)
+            {
+              _dbus_verbose ("Timing out authentication for connection %p\n", connection);
+              dbus_connection_disconnect (connection);
+            }
+          else
+            {
+              /* We can end the loop, since the connections are in oldest-first order */
+              next_interval = ((double)auth_timeout) - elapsed;
+              _dbus_verbose ("Connection %p authentication expires in %d milliseconds\n",
+                             connection, next_interval);
           
-          break;
-        }
+              break;
+            }
       
-      link = next;
+          link = next;
+        }
     }
-
+  
   if (next_interval >= 0)
     {
       _dbus_timeout_set_interval (connections->expire_timeout,
@@ -717,13 +721,15 @@ bus_connections_expire_incomplete (BusConnections *connections)
       _dbus_verbose ("Enabled incomplete connections timeout with interval %d, %d incomplete connections\n",
                      next_interval, connections->n_incomplete);
     }
-  else
+  else if (dbus_timeout_get_enabled (connections->expire_timeout))
     {
       _dbus_timeout_set_enabled (connections->expire_timeout, FALSE);
 
       _dbus_verbose ("Disabled incomplete connections timeout, %d incomplete connections\n",
                      connections->n_incomplete);
     }
+  else
+    _dbus_verbose ("No need to disable incomplete connections timeout\n");
 }
 
 static dbus_bool_t
@@ -731,6 +737,8 @@ expire_incomplete_timeout (void *data)
 {
   BusConnections *connections = data;
 
+  _dbus_verbose ("Running %s\n", _DBUS_FUNCTION_NAME);
+  
   /* note that this may remove the timeout */
   bus_connections_expire_incomplete (connections);
 
@@ -803,7 +811,8 @@ bus_connection_is_in_group (DBusConnection *connection,
 }
 
 BusClientPolicy*
-bus_connection_get_policy (DBusConnection *connection)
+bus_connection_get_policy (DBusConnection *connection,
+                           DBusError      *error)
 {
   BusConnectionData *d;
     
@@ -814,6 +823,9 @@ bus_connection_get_policy (DBusConnection *connection)
   if (!dbus_connection_get_is_authenticated (connection))
     {
       _dbus_verbose ("Tried to get policy for unauthenticated connection!\n");
+      dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+                      "Connection is not yet authenticated; the pre-authentication "
+                      "implicit security policy is to deny everything");
       return NULL;
     }
   
@@ -828,11 +840,19 @@ bus_connection_get_policy (DBusConnection *connection)
 
       /* we may have a NULL policy on OOM or error getting list of
        * groups for a user. In the latter case we don't handle it so
-       * well currently, just keep pretending we're out of memory,
-       * which is kind of bizarre.
+       * well currently, as it will just keep failing over and over.
        */
     }
 
+  if (d->policy == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+                      "There was an error creating the security policy for connection \"%s\"; "
+                      "all operations will fail for now.",
+                      d->name ? d->name : "(inactive)");
+      return NULL;
+    }
+  
   return d->policy;
 }
 
@@ -1075,6 +1095,8 @@ bus_connection_add_owned_service_link (DBusConnection *connection,
   _dbus_assert (d != NULL);
 
   _dbus_list_append_link (&d->services_owned, link);
+
+  d->n_services_owned += 1;
 }
 
 dbus_bool_t
@@ -1103,6 +1125,20 @@ bus_connection_remove_owned_service (DBusConnection *connection,
   _dbus_assert (d != NULL);
 
   _dbus_list_remove_last (&d->services_owned, service);
+
+  d->n_services_owned -= 1;
+  _dbus_assert (d->n_services_owned >= 0);
+}
+
+int
+bus_connection_get_n_services_owned (DBusConnection *connection)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+  _dbus_assert (d != NULL);
+  
+  return d->n_services_owned;
 }
 
 dbus_bool_t
@@ -1144,6 +1180,9 @@ bus_connection_set_name (DBusConnection   *connection,
 
   _dbus_assert (d->connections->n_incomplete >= 0);
   _dbus_assert (d->connections->n_completed > 0);
+
+  /* See if we can remove the timeout */
+  bus_connections_expire_incomplete (d->connections);
   
   return TRUE;
 }
index fe5a376..ebfe2ad 100644 (file)
@@ -68,7 +68,7 @@ void        bus_connection_remove_owned_service   (DBusConnection *connection,
                                                    BusService     *service);
 void        bus_connection_add_owned_service_link (DBusConnection *connection,
                                                    DBusList       *link);
-
+int         bus_connection_get_n_services_owned   (DBusConnection *connection);
 
 /* called by driver.c */
 dbus_bool_t bus_connection_set_name (DBusConnection               *connection,
@@ -83,7 +83,8 @@ dbus_bool_t      bus_connection_is_in_group (DBusConnection       *connection,
 dbus_bool_t      bus_connection_get_groups  (DBusConnection       *connection,
                                              unsigned long       **groups,
                                              int                  *n_groups);
-BusClientPolicy* bus_connection_get_policy  (DBusConnection       *connection);
+BusClientPolicy* bus_connection_get_policy  (DBusConnection       *connection,
+                                             DBusError            *error);
 
 /* transaction API so we can send or not send a block of messages as a whole */
 
index 299968f..9839ff0 100644 (file)
@@ -204,10 +204,11 @@ create_unique_client_name (BusRegistry *registry,
    * for INT_MAX * INT_MAX combinations, should be pretty safe against
    * wraparound.
    */
+  /* FIXME these should be in BusRegistry rather than static vars */
   static int next_major_number = 0;
   static int next_minor_number = 0;
   int len;
-
+  
   len = _dbus_string_get_length (str);
   
   while (TRUE)
index dfc3ed0..fc749d0 100644 (file)
@@ -30,6 +30,7 @@
 #include "connection.h"
 #include "utils.h"
 #include "activation.h"
+#include "policy.h"
 
 struct BusService
 {
@@ -257,6 +258,7 @@ bus_registry_acquire_service (BusRegistry      *registry,
   dbus_bool_t retval;
   DBusConnection *old_owner;
   DBusConnection *current_owner;
+  BusClientPolicy *policy;
   BusService *service;
   
   retval = FALSE;
@@ -283,6 +285,37 @@ bus_registry_acquire_service (BusRegistry      *registry,
       
       goto out;
     }
+
+  policy = bus_connection_get_policy (connection, error);
+  if (policy == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      goto out;
+    }
+
+  if (!bus_client_policy_check_can_own (policy, connection,
+                                        service_name))
+    {
+      dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+                      "Connection \"%s\" is not allowed to own the service \"%s\" due "
+                      "to security policies in the configuration file",
+                      bus_connection_is_active (connection) ?
+                      bus_connection_get_name (connection) :
+                      "(inactive)");
+      goto out;
+    }
+
+  if (bus_connection_get_n_services_owned (connection) >=
+      bus_context_get_max_services_per_connection (registry->context))
+    {
+      dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
+                      "Connection \"%s\" is not allowed to own more services "
+                      "(increase limits in configuration file if required)",
+                      bus_connection_is_active (connection) ?
+                      bus_connection_get_name (connection) :
+                      "(inactive)");
+      goto out;
+    }
   
   service = bus_registry_lookup (registry, service_name);
 
index 1d1af78..6019188 100644 (file)
@@ -356,10 +356,12 @@ check_timeout (unsigned long    tv_sec,
   long interval_milliseconds;
   int interval;
 
+  /* I'm pretty sure this function could suck (a lot) less */
+  
   interval = dbus_timeout_get_interval (tcb->timeout);
   
-  interval_seconds = interval / 1000;
-  interval_milliseconds = interval - interval_seconds * 1000;
+  interval_seconds = interval / 1000L;
+  interval_milliseconds = interval % 1000L;
   
   expiration_tv_sec = tcb->last_tv_sec + interval_seconds;
   expiration_tv_usec = tcb->last_tv_usec + interval_milliseconds * 1000;
@@ -368,44 +370,35 @@ check_timeout (unsigned long    tv_sec,
       expiration_tv_usec -= 1000000;
       expiration_tv_sec += 1;
     }
-
-  if (expiration_tv_sec < tv_sec ||
-      (expiration_tv_sec == tv_sec && expiration_tv_usec < tv_usec))
-    {
-      _dbus_verbose ("System clock went backward interval_seconds %ld interval_msecs %ld last_tv_sec %lu last_tv_usec %lu tv_sec %lu tv_usec %lu\n",
-                     interval_seconds, interval_milliseconds,
-                     tcb->last_tv_sec, tcb->last_tv_usec, tv_sec, tv_usec);
-          
-      /* The system time has been set backwards, reset the timeout to "interval" in the future */  
-      
-      tcb->last_tv_sec = tv_sec;
-      tcb->last_tv_usec = tv_usec;
-
-      *timeout = interval;
-
-      return FALSE;
-    }
   
   sec_remaining = expiration_tv_sec - tv_sec;
-  msec_remaining = (expiration_tv_usec - tv_usec) / 1000;
-
-#if 0
-  printf ("Interval is %ld seconds %ld msecs\n",
-          interval_seconds,
-          interval_milliseconds);
-  printf ("Now is %lu seconds %lu usecs\n",
-          tv_sec, tv_usec);
-  printf ("Exp is %lu seconds %lu usecs\n",
-          expiration_tv_sec, expiration_tv_usec);
-  printf ("Pre-correction, remaining sec_remaining %ld msec_remaining %ld\n", sec_remaining, msec_remaining);
+  /* need to force this to be signed, as it is intended to sometimes
+   * produce a negative result
+   */
+  msec_remaining = ((long) expiration_tv_usec - (long) tv_usec) / 1000L;
+
+#if MAINLOOP_SPEW
+  _dbus_verbose ("Interval is %ld seconds %ld msecs\n",
+                 interval_seconds,
+                 interval_milliseconds);
+  _dbus_verbose ("Now is  %lu seconds %lu usecs\n",
+                 tv_sec, tv_usec);
+  _dbus_verbose ("Last is %lu seconds %lu usecs\n",
+                 tcb->last_tv_sec, tcb->last_tv_usec);
+  _dbus_verbose ("Exp is  %lu seconds %lu usecs\n",
+                 expiration_tv_sec, expiration_tv_usec);
+  _dbus_verbose ("Pre-correction, sec_remaining %ld msec_remaining %ld\n",
+                 sec_remaining, msec_remaining);
 #endif
   
   /* We do the following in a rather convoluted fashion to deal with
    * the fact that we don't have an integral type big enough to hold
-   * the difference of two timevals in millseconds.
+   * the difference of two timevals in milliseconds.
    */
   if (sec_remaining < 0 || (sec_remaining == 0 && msec_remaining < 0))
-    msec_remaining = 0;
+    {
+      *timeout = 0;
+    }
   else
     {
       if (msec_remaining < 0)
@@ -414,20 +407,29 @@ check_timeout (unsigned long    tv_sec,
          sec_remaining -= 1;
        }
 
-      if (msec_remaining > _DBUS_INT_MAX)
-        {
-          /* Not going to fit in a 32-bit integer */
-          msec_remaining = _DBUS_INT_MAX;
-        }
+      if (sec_remaining > (_DBUS_INT_MAX / 1000) ||
+          msec_remaining > _DBUS_INT_MAX)
+        *timeout = _DBUS_INT_MAX;
+      else
+        *timeout = sec_remaining * 1000 + msec_remaining;        
     }
 
-  *timeout = msec_remaining;
+  if (*timeout > interval)
+    {
+      /* This indicates that the system clock probably moved backward */
+      _dbus_verbose ("System clock set backward! Resetting timeout.\n");
+      
+      tcb->last_tv_sec = tv_sec;
+      tcb->last_tv_usec = tv_usec;
 
+      *timeout = interval;
+    }
+  
 #if MAINLOOP_SPEW
   _dbus_verbose ("  timeout expires in %d milliseconds\n", *timeout);
 #endif
   
-  return msec_remaining == 0;
+  return *timeout == 0;
 }
 
 dbus_bool_t
@@ -708,6 +710,12 @@ _dbus_loop_iterate (DBusLoop     *loop,
 
                   retval = TRUE;
                 }
+              else
+                {
+#if MAINLOOP_SPEW
+                  _dbus_verbose ("  timeout has not expired\n");
+#endif
+                }
             }
 
           link = next;
index 74210f9..1a2d296 100644 (file)
@@ -124,6 +124,8 @@ void
 _dbus_timeout_set_interval (DBusTimeout *timeout,
                             int          interval)
 {
+  _dbus_assert (interval >= 0);
+  
   timeout->interval = interval;
 }
 
index ed3cdfa..e6e24e0 100644 (file)
@@ -135,9 +135,9 @@ Elements:
 
     Available limits are:
       "max_incoming_bytes"         : total size in bytes of messages
-                                     incoming from a connection
+                                     incoming from a single connection
       "max_outgoing_bytes"         : total size in bytes of messages
-                                     queued up for a connection
+                                     queued up for a single connection
       "max_message_size"           : max size of a single message in
                                      bytes
       "activation_timeout"         : milliseconds (thousandths) until 
@@ -150,6 +150,10 @@ Elements:
                                      connections
       "max_connections_per_user"   : max number of completed connections from
                                      the same user
+      "max_pending_activations"    : max number of activations in
+                                     progress at the same time
+      "max_services_per_connection": max number of services a single 
+                                     connection can own
 
     Some notes:
 
index 5addd69..4500ad7 100644 (file)
@@ -19,5 +19,7 @@
   <limit name="max_completed_connections">50</limit>  
   <limit name="max_incomplete_connections">80</limit>
   <limit name="max_connections_per_user">64</limit>
+  <limit name="max_pending_activations">64</limit>
+  <limit name="max_services_per_connection">256</limit>
                                    
 </busconfig>