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