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