Home | History | Annotate | Download | only in bus
      1 /* -*- mode: C; c-file-style: "gnu" -*- */
      2 /* connection.c  Client connections
      3  *
      4  * Copyright (C) 2003  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     21  *
     22  */
     23 #include "connection.h"
     24 #include "dispatch.h"
     25 #include "policy.h"
     26 #include "services.h"
     27 #include "utils.h"
     28 #include "signals.h"
     29 #include "expirelist.h"
     30 #include "selinux.h"
     31 #include <dbus/dbus-list.h>
     32 #include <dbus/dbus-hash.h>
     33 #include <dbus/dbus-timeout.h>
     34 
     35 static void bus_connection_remove_transactions (DBusConnection *connection);
     36 
     37 typedef struct
     38 {
     39   BusExpireItem expire_item;
     40 
     41   DBusConnection *will_get_reply;
     42   DBusConnection *will_send_reply;
     43 
     44   dbus_uint32_t reply_serial;
     45 
     46 } BusPendingReply;
     47 
     48 struct BusConnections
     49 {
     50   int refcount;
     51   DBusList *completed;  /**< List of all completed connections */
     52   int n_completed;      /**< Length of completed list */
     53   DBusList *incomplete; /**< List of all not-yet-active connections */
     54   int n_incomplete;     /**< Length of incomplete list */
     55   BusContext *context;
     56   DBusHashTable *completed_by_user; /**< Number of completed connections for each UID */
     57   DBusTimeout *expire_timeout; /**< Timeout for expiring incomplete connections. */
     58   int stamp;                   /**< Incrementing number */
     59   BusExpireList *pending_replies; /**< List of pending replies */
     60 };
     61 
     62 static dbus_int32_t connection_data_slot = -1;
     63 
     64 typedef struct
     65 {
     66   BusConnections *connections;
     67   DBusList *link_in_connection_list;
     68   DBusConnection *connection;
     69   DBusList *services_owned;
     70   int n_services_owned;
     71   DBusList *match_rules;
     72   int n_match_rules;
     73   char *name;
     74   DBusList *transaction_messages; /**< Stuff we need to send as part of a transaction */
     75   DBusMessage *oom_message;
     76   DBusPreallocatedSend *oom_preallocated;
     77   BusClientPolicy *policy;
     78 
     79   BusSELinuxID *selinux_id;
     80 
     81   long connection_tv_sec;  /**< Time when we connected (seconds component) */
     82   long connection_tv_usec; /**< Time when we connected (microsec component) */
     83   int stamp;               /**< connections->stamp last time we were traversed */
     84 } BusConnectionData;
     85 
     86 static dbus_bool_t bus_pending_reply_expired (BusExpireList *list,
     87                                               DBusList      *link,
     88                                               void          *data);
     89 
     90 static void bus_connection_drop_pending_replies (BusConnections  *connections,
     91                                                  DBusConnection  *connection);
     92 
     93 static dbus_bool_t expire_incomplete_timeout (void *data);
     94 
     95 #define BUS_CONNECTION_DATA(connection) (dbus_connection_get_data ((connection), connection_data_slot))
     96 
     97 static DBusLoop*
     98 connection_get_loop (DBusConnection *connection)
     99 {
    100   BusConnectionData *d;
    101 
    102   d = BUS_CONNECTION_DATA (connection);
    103 
    104   return bus_context_get_loop (d->connections->context);
    105 }
    106 
    107 
    108 static int
    109 get_connections_for_uid (BusConnections *connections,
    110                          dbus_uid_t      uid)
    111 {
    112   void *val;
    113   int current_count;
    114 
    115   /* val is NULL is 0 when it isn't in the hash yet */
    116 
    117   val = _dbus_hash_table_lookup_ulong (connections->completed_by_user,
    118                                        uid);
    119 
    120   current_count = _DBUS_POINTER_TO_INT (val);
    121 
    122   return current_count;
    123 }
    124 
    125 static dbus_bool_t
    126 adjust_connections_for_uid (BusConnections *connections,
    127                             dbus_uid_t      uid,
    128                             int             adjustment)
    129 {
    130   int current_count;
    131 
    132   current_count = get_connections_for_uid (connections, uid);
    133 
    134   _dbus_verbose ("Adjusting connection count for UID " DBUS_UID_FORMAT
    135                  ": was %d adjustment %d making %d\n",
    136                  uid, current_count, adjustment, current_count + adjustment);
    137 
    138   _dbus_assert (current_count >= 0);
    139 
    140   current_count += adjustment;
    141 
    142   _dbus_assert (current_count >= 0);
    143 
    144   if (current_count == 0)
    145     {
    146       _dbus_hash_table_remove_ulong (connections->completed_by_user, uid);
    147       return TRUE;
    148     }
    149   else
    150     {
    151       dbus_bool_t retval;
    152 
    153       retval = _dbus_hash_table_insert_ulong (connections->completed_by_user,
    154                                               uid, _DBUS_INT_TO_POINTER (current_count));
    155 
    156       /* only positive adjustment can fail as otherwise
    157        * a hash entry should already exist
    158        */
    159       _dbus_assert (adjustment > 0 ||
    160                     (adjustment <= 0 && retval));
    161 
    162       return retval;
    163     }
    164 }
    165 
    166 void
    167 bus_connection_disconnected (DBusConnection *connection)
    168 {
    169   BusConnectionData *d;
    170   BusService *service;
    171   BusMatchmaker *matchmaker;
    172 
    173   d = BUS_CONNECTION_DATA (connection);
    174   _dbus_assert (d != NULL);
    175 
    176   _dbus_verbose ("%s disconnected, dropping all service ownership and releasing\n",
    177                  d->name ? d->name : "(inactive)");
    178 
    179   /* Delete our match rules */
    180   if (d->n_match_rules > 0)
    181     {
    182       matchmaker = bus_context_get_matchmaker (d->connections->context);
    183       bus_matchmaker_disconnected (matchmaker, connection);
    184     }
    185 
    186   /* Drop any service ownership. Unfortunately, this requires
    187    * memory allocation and there doesn't seem to be a good way to
    188    * handle it other than sleeping; we can't "fail" the operation of
    189    * disconnecting a client, and preallocating a broadcast "service is
    190    * now gone" message for every client-service pair seems kind of
    191    * involved.
    192    */
    193   while ((service = _dbus_list_get_last (&d->services_owned)))
    194     {
    195       BusTransaction *transaction;
    196       DBusError error;
    197 
    198     retry:
    199 
    200       dbus_error_init (&error);
    201 
    202       while ((transaction = bus_transaction_new (d->connections->context)) == NULL)
    203         _dbus_wait_for_memory ();
    204 
    205       if (!bus_service_remove_owner (service, connection,
    206                                      transaction, &error))
    207         {
    208           _DBUS_ASSERT_ERROR_IS_SET (&error);
    209 
    210           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
    211             {
    212               dbus_error_free (&error);
    213               bus_transaction_cancel_and_free (transaction);
    214               _dbus_wait_for_memory ();
    215               goto retry;
    216             }
    217           else
    218             {
    219               _dbus_verbose ("Failed to remove service owner: %s %s\n",
    220                              error.name, error.message);
    221               _dbus_assert_not_reached ("Removing service owner failed for non-memory-related reason");
    222             }
    223         }
    224 
    225       bus_transaction_execute_and_free (transaction);
    226     }
    227 
    228   bus_dispatch_remove_connection (connection);
    229 
    230   /* no more watching */
    231   if (!dbus_connection_set_watch_functions (connection,
    232                                             NULL, NULL, NULL,
    233                                             connection,
    234                                             NULL))
    235     _dbus_assert_not_reached ("setting watch functions to NULL failed");
    236 
    237   if (!dbus_connection_set_timeout_functions (connection,
    238                                               NULL, NULL, NULL,
    239                                               connection,
    240                                               NULL))
    241     _dbus_assert_not_reached ("setting timeout functions to NULL failed");
    242 
    243   dbus_connection_set_unix_user_function (connection,
    244                                           NULL, NULL, NULL);
    245 
    246   dbus_connection_set_dispatch_status_function (connection,
    247                                                 NULL, NULL, NULL);
    248 
    249   bus_connection_remove_transactions (connection);
    250 
    251   if (d->link_in_connection_list != NULL)
    252     {
    253       if (d->name != NULL)
    254         {
    255           unsigned long uid;
    256 
    257           _dbus_list_remove_link (&d->connections->completed, d->link_in_connection_list);
    258           d->link_in_connection_list = NULL;
    259           d->connections->n_completed -= 1;
    260 
    261           if (dbus_connection_get_unix_user (connection, &uid))
    262             {
    263               if (!adjust_connections_for_uid (d->connections,
    264                                                uid, -1))
    265                 _dbus_assert_not_reached ("adjusting downward should never fail");
    266             }
    267         }
    268       else
    269         {
    270           _dbus_list_remove_link (&d->connections->incomplete, d->link_in_connection_list);
    271           d->link_in_connection_list = NULL;
    272           d->connections->n_incomplete -= 1;
    273         }
    274 
    275       _dbus_assert (d->connections->n_incomplete >= 0);
    276       _dbus_assert (d->connections->n_completed >= 0);
    277     }
    278 
    279   bus_connection_drop_pending_replies (d->connections, connection);
    280 
    281   /* frees "d" as side effect */
    282   dbus_connection_set_data (connection,
    283                             connection_data_slot,
    284                             NULL, NULL);
    285 
    286   dbus_connection_unref (connection);
    287 }
    288 
    289 static dbus_bool_t
    290 connection_watch_callback (DBusWatch     *watch,
    291                            unsigned int   condition,
    292                            void          *data)
    293 {
    294  /* FIXME this can be done in dbus-mainloop.c
    295   * if the code in activation.c for the babysitter
    296   * watch handler is fixed.
    297   */
    298 
    299 #if 0
    300   _dbus_verbose ("Calling handle_watch\n");
    301 #endif
    302   return dbus_watch_handle (watch, condition);
    303 }
    304 
    305 static dbus_bool_t
    306 add_connection_watch (DBusWatch      *watch,
    307                       void           *data)
    308 {
    309   DBusConnection *connection = data;
    310 
    311   return _dbus_loop_add_watch (connection_get_loop (connection),
    312                                watch, connection_watch_callback, connection,
    313                                NULL);
    314 }
    315 
    316 static void
    317 remove_connection_watch (DBusWatch      *watch,
    318                          void           *data)
    319 {
    320   DBusConnection *connection = data;
    321 
    322   _dbus_loop_remove_watch (connection_get_loop (connection),
    323                            watch, connection_watch_callback, connection);
    324 }
    325 
    326 static void
    327 connection_timeout_callback (DBusTimeout   *timeout,
    328                              void          *data)
    329 {
    330   /* DBusConnection *connection = data; */
    331 
    332   /* can return FALSE on OOM but we just let it fire again later */
    333   dbus_timeout_handle (timeout);
    334 }
    335 
    336 static dbus_bool_t
    337 add_connection_timeout (DBusTimeout    *timeout,
    338                         void           *data)
    339 {
    340   DBusConnection *connection = data;
    341 
    342   return _dbus_loop_add_timeout (connection_get_loop (connection),
    343                                  timeout, connection_timeout_callback, connection, NULL);
    344 }
    345 
    346 static void
    347 remove_connection_timeout (DBusTimeout    *timeout,
    348                            void           *data)
    349 {
    350   DBusConnection *connection = data;
    351 
    352   _dbus_loop_remove_timeout (connection_get_loop (connection),
    353                              timeout, connection_timeout_callback, connection);
    354 }
    355 
    356 static void
    357 dispatch_status_function (DBusConnection    *connection,
    358                           DBusDispatchStatus new_status,
    359                           void              *data)
    360 {
    361   DBusLoop *loop = data;
    362 
    363   if (new_status != DBUS_DISPATCH_COMPLETE)
    364     {
    365       while (!_dbus_loop_queue_dispatch (loop, connection))
    366         _dbus_wait_for_memory ();
    367     }
    368 }
    369 
    370 static dbus_bool_t
    371 allow_user_function (DBusConnection *connection,
    372                      unsigned long   uid,
    373                      void           *data)
    374 {
    375   BusConnectionData *d;
    376 
    377   d = BUS_CONNECTION_DATA (connection);
    378 
    379   _dbus_assert (d != NULL);
    380 
    381   return bus_context_allow_user (d->connections->context, uid);
    382 }
    383 
    384 static void
    385 free_connection_data (void *data)
    386 {
    387   BusConnectionData *d = data;
    388 
    389   /* services_owned should be NULL since we should be disconnected */
    390   _dbus_assert (d->services_owned == NULL);
    391   _dbus_assert (d->n_services_owned == 0);
    392   /* similarly */
    393   _dbus_assert (d->transaction_messages == NULL);
    394 
    395   if (d->oom_preallocated)
    396     dbus_connection_free_preallocated_send (d->connection, d->oom_preallocated);
    397 
    398   if (d->oom_message)
    399     dbus_message_unref (d->oom_message);
    400 
    401   if (d->policy)
    402     bus_client_policy_unref (d->policy);
    403 
    404   if (d->selinux_id)
    405     bus_selinux_id_unref (d->selinux_id);
    406 
    407   dbus_free (d->name);
    408 
    409   dbus_free (d);
    410 }
    411 
    412 static void
    413 call_timeout_callback (DBusTimeout   *timeout,
    414                        void          *data)
    415 {
    416   /* can return FALSE on OOM but we just let it fire again later */
    417   dbus_timeout_handle (timeout);
    418 }
    419 
    420 BusConnections*
    421 bus_connections_new (BusContext *context)
    422 {
    423   BusConnections *connections;
    424 
    425   if (!dbus_connection_allocate_data_slot (&connection_data_slot))
    426     goto failed_0;
    427 
    428   connections = dbus_new0 (BusConnections, 1);
    429   if (connections == NULL)
    430     goto failed_1;
    431 
    432   connections->completed_by_user = _dbus_hash_table_new (DBUS_HASH_ULONG,
    433                                                          NULL, NULL);
    434   if (connections->completed_by_user == NULL)
    435     goto failed_2;
    436 
    437   connections->expire_timeout = _dbus_timeout_new (100, /* irrelevant */
    438                                                    expire_incomplete_timeout,
    439                                                    connections, NULL);
    440   if (connections->expire_timeout == NULL)
    441     goto failed_3;
    442 
    443   _dbus_timeout_set_enabled (connections->expire_timeout, FALSE);
    444 
    445   connections->pending_replies = bus_expire_list_new (bus_context_get_loop (context),
    446                                                       bus_context_get_reply_timeout (context),
    447                                                       bus_pending_reply_expired,
    448                                                       connections);
    449   if (connections->pending_replies == NULL)
    450     goto failed_4;
    451 
    452   if (!_dbus_loop_add_timeout (bus_context_get_loop (context),
    453                                connections->expire_timeout,
    454                                call_timeout_callback, NULL, NULL))
    455     goto failed_5;
    456 
    457   connections->refcount = 1;
    458   connections->context = context;
    459 
    460   return connections;
    461 
    462  failed_5:
    463   bus_expire_list_free (connections->pending_replies);
    464  failed_4:
    465   _dbus_timeout_unref (connections->expire_timeout);
    466  failed_3:
    467   _dbus_hash_table_unref (connections->completed_by_user);
    468  failed_2:
    469   dbus_free (connections);
    470  failed_1:
    471   dbus_connection_free_data_slot (&connection_data_slot);
    472  failed_0:
    473   return NULL;
    474 }
    475 
    476 BusConnections *
    477 bus_connections_ref (BusConnections *connections)
    478 {
    479   _dbus_assert (connections->refcount > 0);
    480   connections->refcount += 1;
    481 
    482   return connections;
    483 }
    484 
    485 void
    486 bus_connections_unref (BusConnections *connections)
    487 {
    488   _dbus_assert (connections->refcount > 0);
    489   connections->refcount -= 1;
    490   if (connections->refcount == 0)
    491     {
    492       /* drop all incomplete */
    493       while (connections->incomplete != NULL)
    494         {
    495           DBusConnection *connection;
    496 
    497           connection = connections->incomplete->data;
    498 
    499           dbus_connection_ref (connection);
    500           dbus_connection_close (connection);
    501           bus_connection_disconnected (connection);
    502           dbus_connection_unref (connection);
    503         }
    504 
    505       _dbus_assert (connections->n_incomplete == 0);
    506 
    507       /* drop all real connections */
    508       while (connections->completed != NULL)
    509         {
    510           DBusConnection *connection;
    511 
    512           connection = connections->completed->data;
    513 
    514           dbus_connection_ref (connection);
    515           dbus_connection_close (connection);
    516           bus_connection_disconnected (connection);
    517           dbus_connection_unref (connection);
    518         }
    519 
    520       _dbus_assert (connections->n_completed == 0);
    521 
    522       bus_expire_list_free (connections->pending_replies);
    523 
    524       _dbus_loop_remove_timeout (bus_context_get_loop (connections->context),
    525                                  connections->expire_timeout,
    526                                  call_timeout_callback, NULL);
    527 
    528       _dbus_timeout_unref (connections->expire_timeout);
    529 
    530       _dbus_hash_table_unref (connections->completed_by_user);
    531 
    532       dbus_free (connections);
    533 
    534       dbus_connection_free_data_slot (&connection_data_slot);
    535     }
    536 }
    537 
    538 dbus_bool_t
    539 bus_connections_setup_connection (BusConnections *connections,
    540                                   DBusConnection *connection)
    541 {
    542   BusConnectionData *d;
    543   dbus_bool_t retval;
    544   DBusError error;
    545 
    546   d = dbus_new0 (BusConnectionData, 1);
    547 
    548   if (d == NULL)
    549     return FALSE;
    550 
    551   d->connections = connections;
    552   d->connection = connection;
    553 
    554   _dbus_get_current_time (&d->connection_tv_sec,
    555                           &d->connection_tv_usec);
    556 
    557   _dbus_assert (connection_data_slot >= 0);
    558 
    559   if (!dbus_connection_set_data (connection,
    560                                  connection_data_slot,
    561                                  d, free_connection_data))
    562     {
    563       dbus_free (d);
    564       return FALSE;
    565     }
    566 
    567   dbus_connection_set_route_peer_messages (connection, TRUE);
    568 
    569   retval = FALSE;
    570 
    571   dbus_error_init (&error);
    572   d->selinux_id = bus_selinux_init_connection_id (connection,
    573                                                   &error);
    574   if (dbus_error_is_set (&error))
    575     {
    576       /* This is a bit bogus because we pretend all errors
    577        * are OOM; this is done because we know that in bus.c
    578        * an OOM error disconnects the connection, which is
    579        * the same thing we want on any other error.
    580        */
    581       dbus_error_free (&error);
    582       goto out;
    583     }
    584 
    585   if (!dbus_connection_set_watch_functions (connection,
    586                                             add_connection_watch,
    587                                             remove_connection_watch,
    588                                             NULL,
    589                                             connection,
    590                                             NULL))
    591     goto out;
    592 
    593   if (!dbus_connection_set_timeout_functions (connection,
    594                                               add_connection_timeout,
    595                                               remove_connection_timeout,
    596                                               NULL,
    597                                               connection, NULL))
    598     goto out;
    599 
    600   dbus_connection_set_unix_user_function (connection,
    601                                           allow_user_function,
    602                                           NULL, NULL);
    603 
    604   dbus_connection_set_dispatch_status_function (connection,
    605                                                 dispatch_status_function,
    606                                                 bus_context_get_loop (connections->context),
    607                                                 NULL);
    608 
    609   d->link_in_connection_list = _dbus_list_alloc_link (connection);
    610   if (d->link_in_connection_list == NULL)
    611     goto out;
    612 
    613   /* Setup the connection with the dispatcher */
    614   if (!bus_dispatch_add_connection (connection))
    615     goto out;
    616 
    617   if (dbus_connection_get_dispatch_status (connection) != DBUS_DISPATCH_COMPLETE)
    618     {
    619       if (!_dbus_loop_queue_dispatch (bus_context_get_loop (connections->context), connection))
    620         {
    621           bus_dispatch_remove_connection (connection);
    622           goto out;
    623         }
    624     }
    625 
    626   _dbus_list_append_link (&connections->incomplete, d->link_in_connection_list);
    627   connections->n_incomplete += 1;
    628 
    629   dbus_connection_ref (connection);
    630 
    631   /* Note that we might disconnect ourselves here, but it only takes
    632    * effect on return to the main loop. We call this to free up
    633    * expired connections if possible, and to queue the timeout for our
    634    * own expiration.
    635    */
    636   bus_connections_expire_incomplete (connections);
    637 
    638   /* And we might also disconnect ourselves here, but again it
    639    * only takes effect on return to main loop.
    640    */
    641   if (connections->n_incomplete >
    642       bus_context_get_max_incomplete_connections (connections->context))
    643     {
    644       _dbus_verbose ("Number of incomplete connections exceeds max, dropping oldest one\n");
    645 
    646       _dbus_assert (connections->incomplete != NULL);
    647       /* Disconnect the oldest unauthenticated connection.  FIXME
    648        * would it be more secure to drop a *random* connection?  This
    649        * algorithm seems to mean that if someone can create new
    650        * connections quickly enough, they can keep anyone else from
    651        * completing authentication. But random may or may not really
    652        * help with that, a more elaborate solution might be required.
    653        */
    654       dbus_connection_close (connections->incomplete->data);
    655     }
    656 
    657   retval = TRUE;
    658 
    659  out:
    660   if (!retval)
    661     {
    662       if (d->selinux_id)
    663         bus_selinux_id_unref (d->selinux_id);
    664       d->selinux_id = NULL;
    665 
    666       if (!dbus_connection_set_watch_functions (connection,
    667                                                 NULL, NULL, NULL,
    668                                                 connection,
    669                                                 NULL))
    670         _dbus_assert_not_reached ("setting watch functions to NULL failed");
    671 
    672       if (!dbus_connection_set_timeout_functions (connection,
    673                                                   NULL, NULL, NULL,
    674                                                   connection,
    675                                                   NULL))
    676         _dbus_assert_not_reached ("setting timeout functions to NULL failed");
    677 
    678       dbus_connection_set_unix_user_function (connection,
    679                                               NULL, NULL, NULL);
    680 
    681       dbus_connection_set_dispatch_status_function (connection,
    682                                                     NULL, NULL, NULL);
    683 
    684       if (d->link_in_connection_list != NULL)
    685         {
    686           _dbus_assert (d->link_in_connection_list->next == NULL);
    687           _dbus_assert (d->link_in_connection_list->prev == NULL);
    688           _dbus_list_free_link (d->link_in_connection_list);
    689           d->link_in_connection_list = NULL;
    690         }
    691 
    692       if (!dbus_connection_set_data (connection,
    693                                      connection_data_slot,
    694                                      NULL, NULL))
    695         _dbus_assert_not_reached ("failed to set connection data to null");
    696 
    697       /* "d" has now been freed */
    698     }
    699 
    700   return retval;
    701 }
    702 
    703 void
    704 bus_connections_expire_incomplete (BusConnections *connections)
    705 {
    706   int next_interval;
    707 
    708   next_interval = -1;
    709 
    710   if (connections->incomplete != NULL)
    711     {
    712       long tv_sec, tv_usec;
    713       DBusList *link;
    714       int auth_timeout;
    715 
    716       _dbus_get_current_time (&tv_sec, &tv_usec);
    717       auth_timeout = bus_context_get_auth_timeout (connections->context);
    718 
    719       link = _dbus_list_get_first_link (&connections->incomplete);
    720       while (link != NULL)
    721         {
    722           DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link);
    723           DBusConnection *connection;
    724           BusConnectionData *d;
    725           double elapsed;
    726 
    727           connection = link->data;
    728 
    729           d = BUS_CONNECTION_DATA (connection);
    730 
    731           _dbus_assert (d != NULL);
    732 
    733           elapsed = ELAPSED_MILLISECONDS_SINCE (d->connection_tv_sec,
    734                                                 d->connection_tv_usec,
    735                                                 tv_sec, tv_usec);
    736 
    737           if (elapsed >= (double) auth_timeout)
    738             {
    739               _dbus_verbose ("Timing out authentication for connection %p\n", connection);
    740               dbus_connection_close (connection);
    741             }
    742           else
    743             {
    744               /* We can end the loop, since the connections are in oldest-first order */
    745               next_interval = ((double)auth_timeout) - elapsed;
    746               _dbus_verbose ("Connection %p authentication expires in %d milliseconds\n",
    747                              connection, next_interval);
    748 
    749               break;
    750             }
    751 
    752           link = next;
    753         }
    754     }
    755 
    756   bus_expire_timeout_set_interval (connections->expire_timeout,
    757                                    next_interval);
    758 }
    759 
    760 static dbus_bool_t
    761 expire_incomplete_timeout (void *data)
    762 {
    763   BusConnections *connections = data;
    764 
    765   _dbus_verbose ("Running %s\n", _DBUS_FUNCTION_NAME);
    766 
    767   /* note that this may remove the timeout */
    768   bus_connections_expire_incomplete (connections);
    769 
    770   return TRUE;
    771 }
    772 
    773 dbus_bool_t
    774 bus_connection_get_groups  (DBusConnection   *connection,
    775                             unsigned long   **groups,
    776                             int              *n_groups,
    777                             DBusError        *error)
    778 {
    779   BusConnectionData *d;
    780   unsigned long uid;
    781   DBusUserDatabase *user_database;
    782 
    783   d = BUS_CONNECTION_DATA (connection);
    784 
    785   _dbus_assert (d != NULL);
    786 
    787   user_database = bus_context_get_user_database (d->connections->context);
    788 
    789   *groups = NULL;
    790   *n_groups = 0;
    791 
    792   if (dbus_connection_get_unix_user (connection, &uid))
    793     {
    794       if (!_dbus_user_database_get_groups (user_database,
    795                                            uid, groups, n_groups,
    796                                            error))
    797         {
    798           _DBUS_ASSERT_ERROR_IS_SET (error);
    799           _dbus_verbose ("Did not get any groups for UID %lu\n",
    800                          uid);
    801           return FALSE;
    802         }
    803       else
    804         {
    805           _dbus_verbose ("Got %d groups for UID %lu\n",
    806                          *n_groups, uid);
    807           return TRUE;
    808         }
    809     }
    810   else
    811     return TRUE; /* successfully got 0 groups */
    812 }
    813 
    814 dbus_bool_t
    815 bus_connection_is_in_group (DBusConnection *connection,
    816                             unsigned long   gid)
    817 {
    818   int i;
    819   unsigned long *group_ids;
    820   int n_group_ids;
    821 
    822   if (!bus_connection_get_groups (connection, &group_ids, &n_group_ids,
    823                                   NULL))
    824     return FALSE;
    825 
    826   i = 0;
    827   while (i < n_group_ids)
    828     {
    829       if (group_ids[i] == gid)
    830         {
    831           dbus_free (group_ids);
    832           return TRUE;
    833         }
    834       ++i;
    835     }
    836 
    837   dbus_free (group_ids);
    838   return FALSE;
    839 }
    840 
    841 BusClientPolicy*
    842 bus_connection_get_policy (DBusConnection *connection)
    843 {
    844   BusConnectionData *d;
    845 
    846   d = BUS_CONNECTION_DATA (connection);
    847 
    848   _dbus_assert (d != NULL);
    849   _dbus_assert (d->policy != NULL);
    850 
    851   return d->policy;
    852 }
    853 
    854 static dbus_bool_t
    855 foreach_active (BusConnections               *connections,
    856                 BusConnectionForeachFunction  function,
    857                 void                         *data)
    858 {
    859   DBusList *link;
    860 
    861   link = _dbus_list_get_first_link (&connections->completed);
    862   while (link != NULL)
    863     {
    864       DBusConnection *connection = link->data;
    865       DBusList *next = _dbus_list_get_next_link (&connections->completed, link);
    866 
    867       if (!(* function) (connection, data))
    868         return FALSE;
    869 
    870       link = next;
    871     }
    872 
    873   return TRUE;
    874 }
    875 
    876 static dbus_bool_t
    877 foreach_inactive (BusConnections               *connections,
    878                   BusConnectionForeachFunction  function,
    879                   void                         *data)
    880 {
    881   DBusList *link;
    882 
    883   link = _dbus_list_get_first_link (&connections->incomplete);
    884   while (link != NULL)
    885     {
    886       DBusConnection *connection = link->data;
    887       DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link);
    888 
    889       if (!(* function) (connection, data))
    890         return FALSE;
    891 
    892       link = next;
    893     }
    894 
    895   return TRUE;
    896 }
    897 
    898 /**
    899  * Calls function on each active connection; if the function returns
    900  * #FALSE, stops iterating. Active connections are authenticated
    901  * and have sent a Hello message.
    902  *
    903  * @param connections the connections object
    904  * @param function the function
    905  * @param data data to pass to it as a second arg
    906  */
    907 void
    908 bus_connections_foreach_active (BusConnections               *connections,
    909                                 BusConnectionForeachFunction  function,
    910                                 void                         *data)
    911 {
    912   foreach_active (connections, function, data);
    913 }
    914 
    915 /**
    916  * Calls function on each connection; if the function returns
    917  * #FALSE, stops iterating.
    918  *
    919  * @param connections the connections object
    920  * @param function the function
    921  * @param data data to pass to it as a second arg
    922  */
    923 void
    924 bus_connections_foreach (BusConnections               *connections,
    925                          BusConnectionForeachFunction  function,
    926                          void                         *data)
    927 {
    928   if (!foreach_active (connections, function, data))
    929     return;
    930 
    931   foreach_inactive (connections, function, data);
    932 }
    933 
    934 BusContext*
    935 bus_connections_get_context (BusConnections *connections)
    936 {
    937   return connections->context;
    938 }
    939 
    940 /*
    941  * This is used to avoid covering the same connection twice when
    942  * traversing connections. Note that it assumes we will
    943  * bus_connection_mark_stamp() each connection at least once per
    944  * INT_MAX increments of the global stamp, or wraparound would break
    945  * things.
    946  */
    947 void
    948 bus_connections_increment_stamp (BusConnections *connections)
    949 {
    950   connections->stamp += 1;
    951 }
    952 
    953 /* Mark connection with current stamp, return TRUE if it
    954  * didn't already have that stamp
    955  */
    956 dbus_bool_t
    957 bus_connection_mark_stamp (DBusConnection *connection)
    958 {
    959   BusConnectionData *d;
    960 
    961   d = BUS_CONNECTION_DATA (connection);
    962 
    963   _dbus_assert (d != NULL);
    964 
    965   if (d->stamp == d->connections->stamp)
    966     return FALSE;
    967   else
    968     {
    969       d->stamp = d->connections->stamp;
    970       return TRUE;
    971     }
    972 }
    973 
    974 BusContext*
    975 bus_connection_get_context (DBusConnection *connection)
    976 {
    977   BusConnectionData *d;
    978 
    979   d = BUS_CONNECTION_DATA (connection);
    980 
    981   _dbus_assert (d != NULL);
    982 
    983   return d->connections->context;
    984 }
    985 
    986 BusConnections*
    987 bus_connection_get_connections (DBusConnection *connection)
    988 {
    989   BusConnectionData *d;
    990 
    991   d = BUS_CONNECTION_DATA (connection);
    992 
    993   _dbus_assert (d != NULL);
    994 
    995   return d->connections;
    996 }
    997 
    998 BusRegistry*
    999 bus_connection_get_registry (DBusConnection *connection)
   1000 {
   1001   BusConnectionData *d;
   1002 
   1003   d = BUS_CONNECTION_DATA (connection);
   1004 
   1005   _dbus_assert (d != NULL);
   1006 
   1007   return bus_context_get_registry (d->connections->context);
   1008 }
   1009 
   1010 BusActivation*
   1011 bus_connection_get_activation (DBusConnection *connection)
   1012 {
   1013   BusConnectionData *d;
   1014 
   1015   d = BUS_CONNECTION_DATA (connection);
   1016 
   1017   _dbus_assert (d != NULL);
   1018 
   1019   return bus_context_get_activation (d->connections->context);
   1020 }
   1021 
   1022 BusMatchmaker*
   1023 bus_connection_get_matchmaker (DBusConnection *connection)
   1024 {
   1025   BusConnectionData *d;
   1026 
   1027   d = BUS_CONNECTION_DATA (connection);
   1028 
   1029   _dbus_assert (d != NULL);
   1030 
   1031   return bus_context_get_matchmaker (d->connections->context);
   1032 }
   1033 
   1034 BusSELinuxID*
   1035 bus_connection_get_selinux_id (DBusConnection *connection)
   1036 {
   1037   BusConnectionData *d;
   1038 
   1039   d = BUS_CONNECTION_DATA (connection);
   1040 
   1041   _dbus_assert (d != NULL);
   1042 
   1043   return d->selinux_id;
   1044 }
   1045 
   1046 /**
   1047  * Checks whether the connection is registered with the message bus.
   1048  *
   1049  * @param connection the connection
   1050  * @returns #TRUE if we're an active message bus participant
   1051  */
   1052 dbus_bool_t
   1053 bus_connection_is_active (DBusConnection *connection)
   1054 {
   1055   BusConnectionData *d;
   1056 
   1057   d = BUS_CONNECTION_DATA (connection);
   1058 
   1059   return d != NULL && d->name != NULL;
   1060 }
   1061 
   1062 dbus_bool_t
   1063 bus_connection_preallocate_oom_error (DBusConnection *connection)
   1064 {
   1065   DBusMessage *message;
   1066   DBusPreallocatedSend *preallocated;
   1067   BusConnectionData *d;
   1068 
   1069   d = BUS_CONNECTION_DATA (connection);
   1070 
   1071   _dbus_assert (d != NULL);
   1072 
   1073   if (d->oom_preallocated != NULL)
   1074     return TRUE;
   1075 
   1076   preallocated = dbus_connection_preallocate_send (connection);
   1077   if (preallocated == NULL)
   1078     return FALSE;
   1079 
   1080   message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
   1081 
   1082   if (message == NULL)
   1083     {
   1084       dbus_connection_free_preallocated_send (connection, preallocated);
   1085       return FALSE;
   1086     }
   1087 
   1088   /* d->name may be NULL, but that is OK */
   1089   if (!dbus_message_set_error_name (message, DBUS_ERROR_NO_MEMORY) ||
   1090       !dbus_message_set_destination (message, d->name) ||
   1091       !dbus_message_set_sender (message,
   1092                                 DBUS_SERVICE_DBUS))
   1093     {
   1094       dbus_connection_free_preallocated_send (connection, preallocated);
   1095       dbus_message_unref (message);
   1096       return FALSE;
   1097     }
   1098 
   1099   /* set reply serial to placeholder value just so space is already allocated
   1100    * for it.
   1101    */
   1102   if (!dbus_message_set_reply_serial (message, 14))
   1103     {
   1104       dbus_connection_free_preallocated_send (connection, preallocated);
   1105       dbus_message_unref (message);
   1106       return FALSE;
   1107     }
   1108 
   1109   d->oom_message = message;
   1110   d->oom_preallocated = preallocated;
   1111 
   1112   return TRUE;
   1113 }
   1114 
   1115 void
   1116 bus_connection_send_oom_error (DBusConnection *connection,
   1117                                DBusMessage    *in_reply_to)
   1118 {
   1119   BusConnectionData *d;
   1120 
   1121   d = BUS_CONNECTION_DATA (connection);
   1122 
   1123   _dbus_assert (d != NULL);
   1124   _dbus_assert (d->oom_message != NULL);
   1125 
   1126   /* should always succeed since we set it to a placeholder earlier */
   1127   if (!dbus_message_set_reply_serial (d->oom_message,
   1128                                       dbus_message_get_serial (in_reply_to)))
   1129     _dbus_assert_not_reached ("Failed to set reply serial for preallocated oom message");
   1130 
   1131   _dbus_assert (dbus_message_get_sender (d->oom_message) != NULL);
   1132 
   1133   dbus_connection_send_preallocated (connection, d->oom_preallocated,
   1134                                      d->oom_message, NULL);
   1135 
   1136   dbus_message_unref (d->oom_message);
   1137   d->oom_message = NULL;
   1138   d->oom_preallocated = NULL;
   1139 }
   1140 
   1141 void
   1142 bus_connection_add_match_rule_link (DBusConnection *connection,
   1143                                     DBusList       *link)
   1144 {
   1145   BusConnectionData *d;
   1146 
   1147   d = BUS_CONNECTION_DATA (connection);
   1148   _dbus_assert (d != NULL);
   1149 
   1150   _dbus_list_append_link (&d->match_rules, link);
   1151 
   1152   d->n_match_rules += 1;
   1153 }
   1154 
   1155 dbus_bool_t
   1156 bus_connection_add_match_rule (DBusConnection *connection,
   1157                                BusMatchRule   *rule)
   1158 {
   1159     DBusList *link;
   1160 
   1161   link = _dbus_list_alloc_link (rule);
   1162 
   1163   if (link == NULL)
   1164     return FALSE;
   1165 
   1166   bus_connection_add_match_rule_link (connection, link);
   1167 
   1168   return TRUE;
   1169 }
   1170 
   1171 void
   1172 bus_connection_remove_match_rule (DBusConnection *connection,
   1173                                   BusMatchRule   *rule)
   1174 {
   1175   BusConnectionData *d;
   1176 
   1177   d = BUS_CONNECTION_DATA (connection);
   1178   _dbus_assert (d != NULL);
   1179 
   1180   _dbus_list_remove_last (&d->match_rules, rule);
   1181 
   1182   d->n_match_rules -= 1;
   1183   _dbus_assert (d->n_match_rules >= 0);
   1184 }
   1185 
   1186 int
   1187 bus_connection_get_n_match_rules (DBusConnection *connection)
   1188 {
   1189   BusConnectionData *d;
   1190 
   1191   d = BUS_CONNECTION_DATA (connection);
   1192   _dbus_assert (d != NULL);
   1193 
   1194   return d->n_match_rules;
   1195 }
   1196 
   1197 void
   1198 bus_connection_add_owned_service_link (DBusConnection *connection,
   1199                                        DBusList       *link)
   1200 {
   1201   BusConnectionData *d;
   1202 
   1203   d = BUS_CONNECTION_DATA (connection);
   1204   _dbus_assert (d != NULL);
   1205 
   1206   _dbus_list_append_link (&d->services_owned, link);
   1207 
   1208   d->n_services_owned += 1;
   1209 }
   1210 
   1211 dbus_bool_t
   1212 bus_connection_add_owned_service (DBusConnection *connection,
   1213                                   BusService     *service)
   1214 {
   1215   DBusList *link;
   1216 
   1217   link = _dbus_list_alloc_link (service);
   1218 
   1219   if (link == NULL)
   1220     return FALSE;
   1221 
   1222   bus_connection_add_owned_service_link (connection, link);
   1223 
   1224   return TRUE;
   1225 }
   1226 
   1227 void
   1228 bus_connection_remove_owned_service (DBusConnection *connection,
   1229                                      BusService     *service)
   1230 {
   1231   BusConnectionData *d;
   1232 
   1233   d = BUS_CONNECTION_DATA (connection);
   1234   _dbus_assert (d != NULL);
   1235 
   1236   _dbus_list_remove_last (&d->services_owned, service);
   1237 
   1238   d->n_services_owned -= 1;
   1239   _dbus_assert (d->n_services_owned >= 0);
   1240 }
   1241 
   1242 int
   1243 bus_connection_get_n_services_owned (DBusConnection *connection)
   1244 {
   1245   BusConnectionData *d;
   1246 
   1247   d = BUS_CONNECTION_DATA (connection);
   1248   _dbus_assert (d != NULL);
   1249 
   1250   return d->n_services_owned;
   1251 }
   1252 
   1253 dbus_bool_t
   1254 bus_connection_complete (DBusConnection   *connection,
   1255 			 const DBusString *name,
   1256                          DBusError        *error)
   1257 {
   1258   BusConnectionData *d;
   1259   unsigned long uid;
   1260 
   1261   d = BUS_CONNECTION_DATA (connection);
   1262   _dbus_assert (d != NULL);
   1263   _dbus_assert (d->name == NULL);
   1264   _dbus_assert (d->policy == NULL);
   1265 
   1266   _dbus_assert (!bus_connection_is_active (connection));
   1267 
   1268   if (!_dbus_string_copy_data (name, &d->name))
   1269     {
   1270       BUS_SET_OOM (error);
   1271       return FALSE;
   1272     }
   1273 
   1274   _dbus_assert (d->name != NULL);
   1275 
   1276   _dbus_verbose ("Name %s assigned to %p\n", d->name, connection);
   1277 
   1278   d->policy = bus_context_create_client_policy (d->connections->context,
   1279                                                 connection,
   1280                                                 error);
   1281 
   1282   /* we may have a NULL policy on OOM or error getting list of
   1283    * groups for a user. In the latter case we don't handle it so
   1284    * well currently, as it will just keep failing over and over.
   1285    */
   1286 
   1287   if (d->policy == NULL)
   1288     {
   1289       _dbus_verbose ("Failed to create security policy for connection %p\n",
   1290                      connection);
   1291       _DBUS_ASSERT_ERROR_IS_SET (error);
   1292       dbus_free (d->name);
   1293       d->name = NULL;
   1294       return FALSE;
   1295     }
   1296 
   1297   if (dbus_connection_get_unix_user (connection, &uid))
   1298     {
   1299       if (!adjust_connections_for_uid (d->connections,
   1300                                        uid, 1))
   1301         {
   1302           BUS_SET_OOM (error);
   1303           dbus_free (d->name);
   1304           d->name = NULL;
   1305           return FALSE;
   1306         }
   1307     }
   1308 
   1309   /* Now the connection is active, move it between lists */
   1310   _dbus_list_unlink (&d->connections->incomplete,
   1311                      d->link_in_connection_list);
   1312   d->connections->n_incomplete -= 1;
   1313   _dbus_list_append_link (&d->connections->completed,
   1314                           d->link_in_connection_list);
   1315   d->connections->n_completed += 1;
   1316 
   1317   _dbus_assert (d->connections->n_incomplete >= 0);
   1318   _dbus_assert (d->connections->n_completed > 0);
   1319 
   1320   /* See if we can remove the timeout */
   1321   bus_connections_expire_incomplete (d->connections);
   1322 
   1323   _dbus_assert (bus_connection_is_active (connection));
   1324 
   1325   return TRUE;
   1326 }
   1327 
   1328 const char *
   1329 bus_connection_get_name (DBusConnection *connection)
   1330 {
   1331   BusConnectionData *d;
   1332 
   1333   d = BUS_CONNECTION_DATA (connection);
   1334   _dbus_assert (d != NULL);
   1335 
   1336   return d->name;
   1337 }
   1338 
   1339 /**
   1340  * Check whether completing the passed-in connection would
   1341  * exceed limits, and if so set error and return #FALSE
   1342  */
   1343 dbus_bool_t
   1344 bus_connections_check_limits (BusConnections  *connections,
   1345                               DBusConnection  *requesting_completion,
   1346                               DBusError       *error)
   1347 {
   1348   BusConnectionData *d;
   1349   unsigned long uid;
   1350 
   1351   d = BUS_CONNECTION_DATA (requesting_completion);
   1352   _dbus_assert (d != NULL);
   1353 
   1354   _dbus_assert (d->name == NULL);
   1355 
   1356   if (connections->n_completed >=
   1357       bus_context_get_max_completed_connections (connections->context))
   1358     {
   1359       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
   1360                       "The maximum number of active connections has been reached");
   1361       return FALSE;
   1362     }
   1363 
   1364   if (dbus_connection_get_unix_user (requesting_completion, &uid))
   1365     {
   1366       if (get_connections_for_uid (connections, uid) >=
   1367           bus_context_get_max_connections_per_user (connections->context))
   1368         {
   1369           dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
   1370                           "The maximum number of active connections for UID %lu has been reached",
   1371                           uid);
   1372           return FALSE;
   1373         }
   1374     }
   1375 
   1376   return TRUE;
   1377 }
   1378 
   1379 static void
   1380 bus_pending_reply_free (BusPendingReply *pending)
   1381 {
   1382   _dbus_verbose ("Freeing pending reply %p, replier %p receiver %p serial %u\n",
   1383                  pending,
   1384                  pending->will_send_reply,
   1385                  pending->will_get_reply,
   1386                  pending->reply_serial);
   1387 
   1388   dbus_free (pending);
   1389 }
   1390 
   1391 static dbus_bool_t
   1392 bus_pending_reply_send_no_reply (BusConnections  *connections,
   1393                                  BusTransaction  *transaction,
   1394                                  BusPendingReply *pending)
   1395 {
   1396   DBusMessage *message;
   1397   DBusMessageIter iter;
   1398   dbus_bool_t retval;
   1399   const char *errmsg;
   1400 
   1401   retval = FALSE;
   1402 
   1403   message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
   1404   if (message == NULL)
   1405     return FALSE;
   1406 
   1407   dbus_message_set_no_reply (message, TRUE);
   1408 
   1409   if (!dbus_message_set_reply_serial (message,
   1410                                       pending->reply_serial))
   1411     goto out;
   1412 
   1413   if (!dbus_message_set_error_name (message,
   1414                                     DBUS_ERROR_NO_REPLY))
   1415     goto out;
   1416 
   1417   errmsg = "Message did not receive a reply (timeout by message bus)";
   1418   dbus_message_iter_init_append (message, &iter);
   1419   if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &errmsg))
   1420     goto out;
   1421 
   1422   if (!bus_transaction_send_from_driver (transaction, pending->will_get_reply,
   1423                                          message))
   1424     goto out;
   1425 
   1426   retval = TRUE;
   1427 
   1428  out:
   1429   dbus_message_unref (message);
   1430   return retval;
   1431 }
   1432 
   1433 static dbus_bool_t
   1434 bus_pending_reply_expired (BusExpireList *list,
   1435                            DBusList      *link,
   1436                            void          *data)
   1437 {
   1438   BusPendingReply *pending = link->data;
   1439   BusConnections *connections = data;
   1440   BusTransaction *transaction;
   1441 
   1442   /* No reply is forthcoming. So nuke it if we can. If not,
   1443    * leave it in the list to try expiring again later when we
   1444    * get more memory.
   1445    */
   1446 
   1447   _dbus_verbose ("Expiring pending reply %p, replier %p receiver %p serial %u\n",
   1448                  pending,
   1449                  pending->will_send_reply,
   1450                  pending->will_get_reply,
   1451                  pending->reply_serial);
   1452 
   1453   transaction = bus_transaction_new (connections->context);
   1454   if (transaction == NULL)
   1455     return FALSE;
   1456 
   1457   if (!bus_pending_reply_send_no_reply (connections,
   1458                                         transaction,
   1459                                         pending))
   1460     {
   1461       bus_transaction_cancel_and_free (transaction);
   1462       return FALSE;
   1463     }
   1464 
   1465   _dbus_list_remove_link (&connections->pending_replies->items,
   1466                           link);
   1467   bus_pending_reply_free (pending);
   1468   bus_transaction_execute_and_free (transaction);
   1469 
   1470   return TRUE;
   1471 }
   1472 
   1473 static void
   1474 bus_connection_drop_pending_replies (BusConnections  *connections,
   1475                                      DBusConnection  *connection)
   1476 {
   1477   /* The DBusConnection is almost 100% finalized here, so you can't
   1478    * do anything with it except check for pointer equality
   1479    */
   1480   DBusList *link;
   1481 
   1482   _dbus_verbose ("Dropping pending replies that involve connection %p\n",
   1483                  connection);
   1484 
   1485   link = _dbus_list_get_first_link (&connections->pending_replies->items);
   1486   while (link != NULL)
   1487     {
   1488       DBusList *next;
   1489       BusPendingReply *pending;
   1490 
   1491       next = _dbus_list_get_next_link (&connections->pending_replies->items,
   1492                                        link);
   1493       pending = link->data;
   1494 
   1495       if (pending->will_get_reply == connection)
   1496         {
   1497           /* We don't need to track this pending reply anymore */
   1498 
   1499           _dbus_verbose ("Dropping pending reply %p, replier %p receiver %p serial %u\n",
   1500                          pending,
   1501                          pending->will_send_reply,
   1502                          pending->will_get_reply,
   1503                          pending->reply_serial);
   1504 
   1505           _dbus_list_remove_link (&connections->pending_replies->items,
   1506                                   link);
   1507           bus_pending_reply_free (pending);
   1508         }
   1509       else if (pending->will_send_reply == connection)
   1510         {
   1511           /* The reply isn't going to be sent, so set things
   1512            * up so it will be expired right away
   1513            */
   1514           _dbus_verbose ("Will expire pending reply %p, replier %p receiver %p serial %u\n",
   1515                          pending,
   1516                          pending->will_send_reply,
   1517                          pending->will_get_reply,
   1518                          pending->reply_serial);
   1519 
   1520           pending->will_send_reply = NULL;
   1521           pending->expire_item.added_tv_sec = 0;
   1522           pending->expire_item.added_tv_usec = 0;
   1523 
   1524           bus_expire_timeout_set_interval (connections->pending_replies->timeout,
   1525                                            0);
   1526         }
   1527 
   1528       link = next;
   1529     }
   1530 }
   1531 
   1532 
   1533 typedef struct
   1534 {
   1535   BusPendingReply *pending;
   1536   BusConnections  *connections;
   1537 } CancelPendingReplyData;
   1538 
   1539 static void
   1540 cancel_pending_reply (void *data)
   1541 {
   1542   CancelPendingReplyData *d = data;
   1543 
   1544   _dbus_verbose ("%s: d = %p\n", _DBUS_FUNCTION_NAME, d);
   1545 
   1546   if (!_dbus_list_remove (&d->connections->pending_replies->items,
   1547                           d->pending))
   1548     _dbus_assert_not_reached ("pending reply did not exist to be cancelled");
   1549 
   1550   bus_pending_reply_free (d->pending); /* since it's been cancelled */
   1551 }
   1552 
   1553 static void
   1554 cancel_pending_reply_data_free (void *data)
   1555 {
   1556   CancelPendingReplyData *d = data;
   1557 
   1558   _dbus_verbose ("%s: d = %p\n", _DBUS_FUNCTION_NAME, d);
   1559 
   1560   /* d->pending should be either freed or still
   1561    * in the list of pending replies (owned by someone
   1562    * else)
   1563    */
   1564 
   1565   dbus_free (d);
   1566 }
   1567 
   1568 /*
   1569  * Record that a reply is allowed; return TRUE on success.
   1570  */
   1571 dbus_bool_t
   1572 bus_connections_expect_reply (BusConnections  *connections,
   1573                               BusTransaction  *transaction,
   1574                               DBusConnection  *will_get_reply,
   1575                               DBusConnection  *will_send_reply,
   1576                               DBusMessage     *reply_to_this,
   1577                               DBusError       *error)
   1578 {
   1579   BusPendingReply *pending;
   1580   dbus_uint32_t reply_serial;
   1581   DBusList *link;
   1582   CancelPendingReplyData *cprd;
   1583   int count;
   1584 
   1585   _dbus_assert (will_get_reply != NULL);
   1586   _dbus_assert (will_send_reply != NULL);
   1587   _dbus_assert (reply_to_this != NULL);
   1588 
   1589   if (dbus_message_get_no_reply (reply_to_this))
   1590     return TRUE; /* we won't allow a reply, since client doesn't care for one. */
   1591 
   1592   reply_serial = dbus_message_get_serial (reply_to_this);
   1593 
   1594   link = _dbus_list_get_first_link (&connections->pending_replies->items);
   1595   count = 0;
   1596   while (link != NULL)
   1597     {
   1598       pending = link->data;
   1599 
   1600       if (pending->reply_serial == reply_serial &&
   1601           pending->will_get_reply == will_get_reply &&
   1602           pending->will_send_reply == will_send_reply)
   1603         {
   1604           dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
   1605                           "Message has the same reply serial as a currently-outstanding existing method call");
   1606           return FALSE;
   1607         }
   1608 
   1609       link = _dbus_list_get_next_link (&connections->pending_replies->items,
   1610                                        link);
   1611       if (pending->will_get_reply == will_get_reply)
   1612         ++count;
   1613     }
   1614 
   1615   if (count >=
   1616       bus_context_get_max_replies_per_connection (connections->context))
   1617     {
   1618       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
   1619 		      "The maximum number of pending replies per connection has been reached");
   1620       return FALSE;
   1621     }
   1622 
   1623   pending = dbus_new0 (BusPendingReply, 1);
   1624   if (pending == NULL)
   1625     {
   1626       BUS_SET_OOM (error);
   1627       return FALSE;
   1628     }
   1629 
   1630 #ifdef DBUS_ENABLE_VERBOSE_MODE
   1631   /* so we can see a not-yet-added pending reply */
   1632   pending->expire_item.added_tv_sec = 1;
   1633   pending->expire_item.added_tv_usec = 1;
   1634 #endif
   1635 
   1636   pending->will_get_reply = will_get_reply;
   1637   pending->will_send_reply = will_send_reply;
   1638   pending->reply_serial = reply_serial;
   1639 
   1640   cprd = dbus_new0 (CancelPendingReplyData, 1);
   1641   if (cprd == NULL)
   1642     {
   1643       BUS_SET_OOM (error);
   1644       bus_pending_reply_free (pending);
   1645       return FALSE;
   1646     }
   1647 
   1648   if (!_dbus_list_prepend (&connections->pending_replies->items,
   1649                            pending))
   1650     {
   1651       BUS_SET_OOM (error);
   1652       dbus_free (cprd);
   1653       bus_pending_reply_free (pending);
   1654       return FALSE;
   1655     }
   1656 
   1657   if (!bus_transaction_add_cancel_hook (transaction,
   1658                                         cancel_pending_reply,
   1659                                         cprd,
   1660                                         cancel_pending_reply_data_free))
   1661     {
   1662       BUS_SET_OOM (error);
   1663       _dbus_list_remove (&connections->pending_replies->items, pending);
   1664       dbus_free (cprd);
   1665       bus_pending_reply_free (pending);
   1666       return FALSE;
   1667     }
   1668 
   1669   cprd->pending = pending;
   1670   cprd->connections = connections;
   1671 
   1672   _dbus_get_current_time (&pending->expire_item.added_tv_sec,
   1673                           &pending->expire_item.added_tv_usec);
   1674 
   1675   _dbus_verbose ("Added pending reply %p, replier %p receiver %p serial %u\n",
   1676                  pending,
   1677                  pending->will_send_reply,
   1678                  pending->will_get_reply,
   1679                  pending->reply_serial);
   1680 
   1681   return TRUE;
   1682 }
   1683 
   1684 typedef struct
   1685 {
   1686   DBusList        *link;
   1687   BusConnections  *connections;
   1688 } CheckPendingReplyData;
   1689 
   1690 static void
   1691 cancel_check_pending_reply (void *data)
   1692 {
   1693   CheckPendingReplyData *d = data;
   1694 
   1695   _dbus_verbose ("%s: d = %p\n", _DBUS_FUNCTION_NAME, d);
   1696 
   1697   _dbus_list_prepend_link (&d->connections->pending_replies->items,
   1698                            d->link);
   1699   d->link = NULL;
   1700 }
   1701 
   1702 static void
   1703 check_pending_reply_data_free (void *data)
   1704 {
   1705   CheckPendingReplyData *d = data;
   1706 
   1707   _dbus_verbose ("%s: d = %p\n", _DBUS_FUNCTION_NAME, d);
   1708 
   1709   if (d->link != NULL)
   1710     {
   1711       BusPendingReply *pending = d->link->data;
   1712 
   1713       _dbus_assert (_dbus_list_find_last (&d->connections->pending_replies->items,
   1714                                           pending) == NULL);
   1715 
   1716       bus_pending_reply_free (pending);
   1717       _dbus_list_free_link (d->link);
   1718     }
   1719 
   1720   dbus_free (d);
   1721 }
   1722 
   1723 /*
   1724  * Check whether a reply is allowed, remove BusPendingReply
   1725  * if so, return TRUE if so.
   1726  */
   1727 dbus_bool_t
   1728 bus_connections_check_reply (BusConnections *connections,
   1729                              BusTransaction *transaction,
   1730                              DBusConnection *sending_reply,
   1731                              DBusConnection *receiving_reply,
   1732                              DBusMessage    *reply,
   1733                              DBusError      *error)
   1734 {
   1735   CheckPendingReplyData *cprd;
   1736   DBusList *link;
   1737   dbus_uint32_t reply_serial;
   1738 
   1739   _dbus_assert (sending_reply != NULL);
   1740   _dbus_assert (receiving_reply != NULL);
   1741 
   1742   reply_serial = dbus_message_get_reply_serial (reply);
   1743 
   1744   link = _dbus_list_get_first_link (&connections->pending_replies->items);
   1745   while (link != NULL)
   1746     {
   1747       BusPendingReply *pending = link->data;
   1748 
   1749       if (pending->reply_serial == reply_serial &&
   1750           pending->will_get_reply == receiving_reply &&
   1751           pending->will_send_reply == sending_reply)
   1752         {
   1753           _dbus_verbose ("Found pending reply with serial %u\n", reply_serial);
   1754           break;
   1755         }
   1756 
   1757       link = _dbus_list_get_next_link (&connections->pending_replies->items,
   1758                                        link);
   1759     }
   1760 
   1761   if (link == NULL)
   1762     {
   1763       _dbus_verbose ("No pending reply expected\n");
   1764 
   1765       return FALSE;
   1766     }
   1767 
   1768   cprd = dbus_new0 (CheckPendingReplyData, 1);
   1769   if (cprd == NULL)
   1770     {
   1771       BUS_SET_OOM (error);
   1772       return FALSE;
   1773     }
   1774 
   1775   if (!bus_transaction_add_cancel_hook (transaction,
   1776                                         cancel_check_pending_reply,
   1777                                         cprd,
   1778                                         check_pending_reply_data_free))
   1779     {
   1780       BUS_SET_OOM (error);
   1781       dbus_free (cprd);
   1782       return FALSE;
   1783     }
   1784 
   1785   cprd->link = link;
   1786   cprd->connections = connections;
   1787 
   1788   _dbus_list_unlink (&connections->pending_replies->items,
   1789                      link);
   1790 
   1791   _dbus_assert (_dbus_list_find_last (&connections->pending_replies->items,
   1792                                       link->data) == NULL);
   1793 
   1794   return TRUE;
   1795 }
   1796 
   1797 /*
   1798  * Transactions
   1799  *
   1800  * Note that this is fairly fragile; in particular, don't try to use
   1801  * one transaction across any main loop iterations.
   1802  */
   1803 
   1804 typedef struct
   1805 {
   1806   BusTransaction *transaction;
   1807   DBusMessage    *message;
   1808   DBusPreallocatedSend *preallocated;
   1809 } MessageToSend;
   1810 
   1811 typedef struct
   1812 {
   1813   BusTransactionCancelFunction cancel_function;
   1814   DBusFreeFunction free_data_function;
   1815   void *data;
   1816 } CancelHook;
   1817 
   1818 struct BusTransaction
   1819 {
   1820   DBusList *connections;
   1821   BusContext *context;
   1822   DBusList *cancel_hooks;
   1823 };
   1824 
   1825 static void
   1826 message_to_send_free (DBusConnection *connection,
   1827                       MessageToSend  *to_send)
   1828 {
   1829   if (to_send->message)
   1830     dbus_message_unref (to_send->message);
   1831 
   1832   if (to_send->preallocated)
   1833     dbus_connection_free_preallocated_send (connection, to_send->preallocated);
   1834 
   1835   dbus_free (to_send);
   1836 }
   1837 
   1838 static void
   1839 cancel_hook_cancel (void *element,
   1840                     void *data)
   1841 {
   1842   CancelHook *ch = element;
   1843 
   1844   _dbus_verbose ("Running transaction cancel hook\n");
   1845 
   1846   if (ch->cancel_function)
   1847     (* ch->cancel_function) (ch->data);
   1848 }
   1849 
   1850 static void
   1851 cancel_hook_free (void *element,
   1852                   void *data)
   1853 {
   1854   CancelHook *ch = element;
   1855 
   1856   if (ch->free_data_function)
   1857     (* ch->free_data_function) (ch->data);
   1858 
   1859   dbus_free (ch);
   1860 }
   1861 
   1862 static void
   1863 free_cancel_hooks (BusTransaction *transaction)
   1864 {
   1865   _dbus_list_foreach (&transaction->cancel_hooks,
   1866                       cancel_hook_free, NULL);
   1867 
   1868   _dbus_list_clear (&transaction->cancel_hooks);
   1869 }
   1870 
   1871 BusTransaction*
   1872 bus_transaction_new (BusContext *context)
   1873 {
   1874   BusTransaction *transaction;
   1875 
   1876   transaction = dbus_new0 (BusTransaction, 1);
   1877   if (transaction == NULL)
   1878     return NULL;
   1879 
   1880   transaction->context = context;
   1881 
   1882   return transaction;
   1883 }
   1884 
   1885 BusContext*
   1886 bus_transaction_get_context (BusTransaction  *transaction)
   1887 {
   1888   return transaction->context;
   1889 }
   1890 
   1891 BusConnections*
   1892 bus_transaction_get_connections (BusTransaction  *transaction)
   1893 {
   1894   return bus_context_get_connections (transaction->context);
   1895 }
   1896 
   1897 dbus_bool_t
   1898 bus_transaction_send_from_driver (BusTransaction *transaction,
   1899                                   DBusConnection *connection,
   1900                                   DBusMessage    *message)
   1901 {
   1902   /* We have to set the sender to the driver, and have
   1903    * to check security policy since it was not done in
   1904    * dispatch.c
   1905    */
   1906   _dbus_verbose ("Sending %s %s %s from driver\n",
   1907                  dbus_message_get_interface (message) ?
   1908                  dbus_message_get_interface (message) : "(no interface)",
   1909                  dbus_message_get_member (message) ?
   1910                  dbus_message_get_member (message) : "(no member)",
   1911                  dbus_message_get_error_name (message) ?
   1912                  dbus_message_get_error_name (message) : "(no error name)");
   1913 
   1914   if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
   1915     return FALSE;
   1916 
   1917   if (bus_connection_is_active (connection))
   1918     {
   1919       if (!dbus_message_set_destination (message,
   1920                                          bus_connection_get_name (connection)))
   1921         return FALSE;
   1922     }
   1923 
   1924   /* bus driver never wants a reply */
   1925   dbus_message_set_no_reply (message, TRUE);
   1926 
   1927   /* If security policy doesn't allow the message, we silently
   1928    * eat it; the driver doesn't care about getting a reply.
   1929    */
   1930   if (!bus_context_check_security_policy (bus_transaction_get_context (transaction),
   1931                                           transaction,
   1932                                           NULL, connection, connection, message, NULL))
   1933     return TRUE;
   1934 
   1935   return bus_transaction_send (transaction, connection, message);
   1936 }
   1937 
   1938 dbus_bool_t
   1939 bus_transaction_send (BusTransaction *transaction,
   1940                       DBusConnection *connection,
   1941                       DBusMessage    *message)
   1942 {
   1943   MessageToSend *to_send;
   1944   BusConnectionData *d;
   1945   DBusList *link;
   1946 
   1947   _dbus_verbose ("  trying to add %s interface=%s member=%s error=%s to transaction%s\n",
   1948                  dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ? "error" :
   1949                  dbus_message_get_reply_serial (message) != 0 ? "reply" :
   1950                  "message",
   1951                  dbus_message_get_interface (message) ?
   1952                  dbus_message_get_interface (message) : "(unset)",
   1953                  dbus_message_get_member (message) ?
   1954                  dbus_message_get_member (message) : "(unset)",
   1955                  dbus_message_get_error_name (message) ?
   1956                  dbus_message_get_error_name (message) : "(unset)",
   1957                  dbus_connection_get_is_connected (connection) ?
   1958                  "" : " (disconnected)");
   1959 
   1960   _dbus_assert (dbus_message_get_sender (message) != NULL);
   1961 
   1962   if (!dbus_connection_get_is_connected (connection))
   1963     return TRUE; /* silently ignore disconnected connections */
   1964 
   1965   d = BUS_CONNECTION_DATA (connection);
   1966   _dbus_assert (d != NULL);
   1967 
   1968   to_send = dbus_new (MessageToSend, 1);
   1969   if (to_send == NULL)
   1970     {
   1971       return FALSE;
   1972     }
   1973 
   1974   to_send->preallocated = dbus_connection_preallocate_send (connection);
   1975   if (to_send->preallocated == NULL)
   1976     {
   1977       dbus_free (to_send);
   1978       return FALSE;
   1979     }
   1980 
   1981   dbus_message_ref (message);
   1982   to_send->message = message;
   1983   to_send->transaction = transaction;
   1984 
   1985   _dbus_verbose ("about to prepend message\n");
   1986 
   1987   if (!_dbus_list_prepend (&d->transaction_messages, to_send))
   1988     {
   1989       message_to_send_free (connection, to_send);
   1990       return FALSE;
   1991     }
   1992 
   1993   _dbus_verbose ("prepended message\n");
   1994 
   1995   /* See if we already had this connection in the list
   1996    * for this transaction. If we have a pending message,
   1997    * then we should already be in transaction->connections
   1998    */
   1999   link = _dbus_list_get_first_link (&d->transaction_messages);
   2000   _dbus_assert (link->data == to_send);
   2001   link = _dbus_list_get_next_link (&d->transaction_messages, link);
   2002   while (link != NULL)
   2003     {
   2004       MessageToSend *m = link->data;
   2005       DBusList *next = _dbus_list_get_next_link (&d->transaction_messages, link);
   2006 
   2007       if (m->transaction == transaction)
   2008         break;
   2009 
   2010       link = next;
   2011     }
   2012 
   2013   if (link == NULL)
   2014     {
   2015       if (!_dbus_list_prepend (&transaction->connections, connection))
   2016         {
   2017           _dbus_list_remove (&d->transaction_messages, to_send);
   2018           message_to_send_free (connection, to_send);
   2019           return FALSE;
   2020         }
   2021     }
   2022 
   2023   return TRUE;
   2024 }
   2025 
   2026 static void
   2027 connection_cancel_transaction (DBusConnection *connection,
   2028                                BusTransaction *transaction)
   2029 {
   2030   DBusList *link;
   2031   BusConnectionData *d;
   2032 
   2033   d = BUS_CONNECTION_DATA (connection);
   2034   _dbus_assert (d != NULL);
   2035 
   2036   link = _dbus_list_get_first_link (&d->transaction_messages);
   2037   while (link != NULL)
   2038     {
   2039       MessageToSend *m = link->data;
   2040       DBusList *next = _dbus_list_get_next_link (&d->transaction_messages, link);
   2041 
   2042       if (m->transaction == transaction)
   2043         {
   2044           _dbus_list_remove_link (&d->transaction_messages,
   2045                                   link);
   2046 
   2047           message_to_send_free (connection, m);
   2048         }
   2049 
   2050       link = next;
   2051     }
   2052 }
   2053 
   2054 void
   2055 bus_transaction_cancel_and_free (BusTransaction *transaction)
   2056 {
   2057   DBusConnection *connection;
   2058 
   2059   _dbus_verbose ("TRANSACTION: cancelled\n");
   2060 
   2061   while ((connection = _dbus_list_pop_first (&transaction->connections)))
   2062     connection_cancel_transaction (connection, transaction);
   2063 
   2064   _dbus_assert (transaction->connections == NULL);
   2065 
   2066   _dbus_list_foreach (&transaction->cancel_hooks,
   2067                       cancel_hook_cancel, NULL);
   2068 
   2069   free_cancel_hooks (transaction);
   2070 
   2071   dbus_free (transaction);
   2072 }
   2073 
   2074 static void
   2075 connection_execute_transaction (DBusConnection *connection,
   2076                                 BusTransaction *transaction)
   2077 {
   2078   DBusList *link;
   2079   BusConnectionData *d;
   2080 
   2081   d = BUS_CONNECTION_DATA (connection);
   2082   _dbus_assert (d != NULL);
   2083 
   2084   /* Send the queue in order (FIFO) */
   2085   link = _dbus_list_get_last_link (&d->transaction_messages);
   2086   while (link != NULL)
   2087     {
   2088       MessageToSend *m = link->data;
   2089       DBusList *prev = _dbus_list_get_prev_link (&d->transaction_messages, link);
   2090 
   2091       if (m->transaction == transaction)
   2092         {
   2093           _dbus_list_remove_link (&d->transaction_messages,
   2094                                   link);
   2095 
   2096           _dbus_assert (dbus_message_get_sender (m->message) != NULL);
   2097 
   2098           dbus_connection_send_preallocated (connection,
   2099                                              m->preallocated,
   2100                                              m->message,
   2101                                              NULL);
   2102 
   2103           m->preallocated = NULL; /* so we don't double-free it */
   2104 
   2105           message_to_send_free (connection, m);
   2106         }
   2107 
   2108       link = prev;
   2109     }
   2110 }
   2111 
   2112 void
   2113 bus_transaction_execute_and_free (BusTransaction *transaction)
   2114 {
   2115   /* For each connection in transaction->connections
   2116    * send the messages
   2117    */
   2118   DBusConnection *connection;
   2119 
   2120   _dbus_verbose ("TRANSACTION: executing\n");
   2121 
   2122   while ((connection = _dbus_list_pop_first (&transaction->connections)))
   2123     connection_execute_transaction (connection, transaction);
   2124 
   2125   _dbus_assert (transaction->connections == NULL);
   2126 
   2127   free_cancel_hooks (transaction);
   2128 
   2129   dbus_free (transaction);
   2130 }
   2131 
   2132 static void
   2133 bus_connection_remove_transactions (DBusConnection *connection)
   2134 {
   2135   MessageToSend *to_send;
   2136   BusConnectionData *d;
   2137 
   2138   d = BUS_CONNECTION_DATA (connection);
   2139   _dbus_assert (d != NULL);
   2140 
   2141   while ((to_send = _dbus_list_get_first (&d->transaction_messages)))
   2142     {
   2143       /* only has an effect for the first MessageToSend listing this transaction */
   2144       _dbus_list_remove (&to_send->transaction->connections,
   2145                          connection);
   2146 
   2147       _dbus_list_remove (&d->transaction_messages, to_send);
   2148       message_to_send_free (connection, to_send);
   2149     }
   2150 }
   2151 
   2152 /**
   2153  * Converts the DBusError to a message reply
   2154  */
   2155 dbus_bool_t
   2156 bus_transaction_send_error_reply (BusTransaction  *transaction,
   2157                                   DBusConnection  *connection,
   2158                                   const DBusError *error,
   2159                                   DBusMessage     *in_reply_to)
   2160 {
   2161   DBusMessage *reply;
   2162 
   2163   _dbus_assert (error != NULL);
   2164   _DBUS_ASSERT_ERROR_IS_SET (error);
   2165 
   2166   _dbus_verbose ("Sending error reply %s \"%s\"\n",
   2167                  error->name, error->message);
   2168 
   2169   reply = dbus_message_new_error (in_reply_to,
   2170                                   error->name,
   2171                                   error->message);
   2172   if (reply == NULL)
   2173     return FALSE;
   2174 
   2175   if (!bus_transaction_send_from_driver (transaction, connection, reply))
   2176     {
   2177       dbus_message_unref (reply);
   2178       return FALSE;
   2179     }
   2180 
   2181   dbus_message_unref (reply);
   2182 
   2183   return TRUE;
   2184 }
   2185 
   2186 dbus_bool_t
   2187 bus_transaction_add_cancel_hook (BusTransaction               *transaction,
   2188                                  BusTransactionCancelFunction  cancel_function,
   2189                                  void                         *data,
   2190                                  DBusFreeFunction              free_data_function)
   2191 {
   2192   CancelHook *ch;
   2193 
   2194   ch = dbus_new (CancelHook, 1);
   2195   if (ch == NULL)
   2196     return FALSE;
   2197 
   2198   _dbus_verbose ("     adding cancel hook function = %p data = %p\n",
   2199                  cancel_function, data);
   2200 
   2201   ch->cancel_function = cancel_function;
   2202   ch->data = data;
   2203   ch->free_data_function = free_data_function;
   2204 
   2205   /* It's important that the hooks get run in reverse order that they
   2206    * were added
   2207    */
   2208   if (!_dbus_list_prepend (&transaction->cancel_hooks, ch))
   2209     {
   2210       dbus_free (ch);
   2211       return FALSE;
   2212     }
   2213 
   2214   return TRUE;
   2215 }
   2216