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