2003-10-28 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 dbus_bool_t 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 void
1344 bus_pending_reply_free (BusPendingReply *pending)
1345 {
1346   _dbus_verbose ("Freeing pending reply %p, replier %p receiver %p serial %u\n",
1347                  pending,
1348                  pending->will_send_reply,
1349                  pending->will_get_reply,
1350                  pending->reply_serial);
1351
1352   dbus_free (pending);
1353 }
1354
1355 static dbus_bool_t
1356 bus_pending_reply_send_no_reply (BusConnections  *connections,
1357                                  BusTransaction  *transaction,
1358                                  BusPendingReply *pending)
1359 {
1360   DBusMessage *message;
1361   DBusMessageIter iter;
1362   dbus_bool_t retval;
1363
1364   retval = FALSE;
1365   
1366   message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
1367   if (message == NULL)
1368     return FALSE;
1369   
1370   dbus_message_set_no_reply (message, TRUE);
1371   
1372   if (!dbus_message_set_reply_serial (message,
1373                                       pending->reply_serial))
1374     goto out;
1375
1376   if (!dbus_message_set_error_name (message,
1377                                     DBUS_ERROR_NO_REPLY))
1378     goto out;
1379   
1380   dbus_message_append_iter_init (message, &iter);
1381   if (!dbus_message_iter_append_string (&iter, "Message did not receive a reply (timeout by message bus)"))
1382     goto out;
1383     
1384   if (!bus_transaction_send_from_driver (transaction, pending->will_get_reply,
1385                                          message))
1386     goto out;
1387
1388   retval = TRUE;
1389
1390  out:
1391   dbus_message_unref (message);
1392   return retval;
1393 }
1394
1395 static dbus_bool_t
1396 bus_pending_reply_expired (BusExpireList *list,
1397                            DBusList      *link,
1398                            void          *data)
1399 {
1400   BusPendingReply *pending = link->data;
1401   BusConnections *connections = data;
1402   BusTransaction *transaction;
1403   
1404   /* No reply is forthcoming. So nuke it if we can. If not,
1405    * leave it in the list to try expiring again later when we
1406    * get more memory.
1407    */
1408
1409   _dbus_verbose ("Expiring pending reply %p, replier %p receiver %p serial %u\n",
1410                  pending,
1411                  pending->will_send_reply,
1412                  pending->will_get_reply,
1413                  pending->reply_serial);
1414   
1415   transaction = bus_transaction_new (connections->context);
1416   if (transaction == NULL)
1417     return FALSE;
1418   
1419   if (!bus_pending_reply_send_no_reply (connections,
1420                                         transaction,
1421                                         pending))
1422     {
1423       bus_transaction_cancel_and_free (transaction);
1424       return FALSE;
1425     }
1426   
1427   _dbus_list_remove_link (&connections->pending_replies->items,
1428                           link);
1429   bus_pending_reply_free (pending);
1430   bus_transaction_execute_and_free (transaction);
1431
1432   return TRUE;
1433 }
1434
1435 static void
1436 bus_connection_drop_pending_replies (BusConnections  *connections,
1437                                      DBusConnection  *connection)
1438 {
1439   /* The DBusConnection is almost 100% finalized here, so you can't
1440    * do anything with it except check for pointer equality
1441    */
1442   DBusList *link;
1443
1444   _dbus_verbose ("Dropping pending replies that involve connection %p\n",
1445                  connection);
1446   
1447   link = _dbus_list_get_first_link (&connections->pending_replies->items);
1448   while (link != NULL)
1449     {
1450       DBusList *next;
1451       BusPendingReply *pending;
1452
1453       next = _dbus_list_get_next_link (&connections->pending_replies->items,
1454                                        link);
1455       pending = link->data;
1456
1457       if (pending->will_get_reply == connection)
1458         {
1459           /* We don't need to track this pending reply anymore */
1460
1461           _dbus_verbose ("Dropping pending reply %p, replier %p receiver %p serial %u\n",
1462                          pending,
1463                          pending->will_send_reply,
1464                          pending->will_get_reply,
1465                          pending->reply_serial);
1466           
1467           _dbus_list_remove_link (&connections->pending_replies->items,
1468                                   link);
1469           bus_pending_reply_free (pending);
1470         }
1471       else if (pending->will_send_reply == connection)
1472         {
1473           /* The reply isn't going to be sent, so set things
1474            * up so it will be expired right away
1475            */
1476           _dbus_verbose ("Will expire pending reply %p, replier %p receiver %p serial %u\n",
1477                          pending,
1478                          pending->will_send_reply,
1479                          pending->will_get_reply,
1480                          pending->reply_serial);
1481           
1482           pending->will_send_reply = NULL;
1483           pending->expire_item.added_tv_sec = 0;
1484           pending->expire_item.added_tv_usec = 0;
1485
1486           bus_expire_timeout_set_interval (connections->pending_replies->timeout,
1487                                            0);
1488         }
1489       
1490       link = next;
1491     }
1492 }
1493
1494
1495 typedef struct
1496 {
1497   BusPendingReply *pending;
1498   BusConnections  *connections;
1499 } CancelPendingReplyData;
1500
1501 static void
1502 cancel_pending_reply (void *data)
1503 {
1504   CancelPendingReplyData *d = data;
1505
1506   _dbus_verbose ("%s: d = %p\n", _DBUS_FUNCTION_NAME, d);
1507   
1508   if (!_dbus_list_remove (&d->connections->pending_replies->items,
1509                           d->pending))
1510     _dbus_assert_not_reached ("pending reply did not exist to be cancelled");
1511
1512   bus_pending_reply_free (d->pending); /* since it's been cancelled */
1513 }
1514
1515 static void
1516 cancel_pending_reply_data_free (void *data)
1517 {
1518   CancelPendingReplyData *d = data;
1519
1520   _dbus_verbose ("%s: d = %p\n", _DBUS_FUNCTION_NAME, d);
1521   
1522   /* d->pending should be either freed or still
1523    * in the list of pending replies (owned by someone
1524    * else)
1525    */
1526   
1527   dbus_free (d);
1528 }
1529
1530 /*
1531  * Record that a reply is allowed; return TRUE on success.
1532  */
1533 dbus_bool_t
1534 bus_connections_expect_reply (BusConnections  *connections,
1535                               BusTransaction  *transaction,
1536                               DBusConnection  *will_get_reply,
1537                               DBusConnection  *will_send_reply,
1538                               DBusMessage     *reply_to_this,
1539                               DBusError       *error)
1540 {
1541   BusPendingReply *pending;
1542   dbus_uint32_t reply_serial;
1543   DBusList *link;
1544   CancelPendingReplyData *cprd;
1545
1546   _dbus_assert (will_get_reply != NULL);
1547   _dbus_assert (will_send_reply != NULL);
1548   _dbus_assert (reply_to_this != NULL);
1549   
1550   if (dbus_message_get_no_reply (reply_to_this))
1551     return TRUE; /* we won't allow a reply, since client doesn't care for one. */
1552   
1553   reply_serial = dbus_message_get_serial (reply_to_this);
1554
1555   link = _dbus_list_get_first_link (&connections->pending_replies->items);
1556   while (link != NULL)
1557     {
1558       pending = link->data;
1559
1560       if (pending->reply_serial == reply_serial &&
1561           pending->will_get_reply == will_get_reply &&
1562           pending->will_send_reply == will_send_reply)
1563         {
1564           dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
1565                           "Message has the same reply serial as a currently-outstanding existing method call");
1566           return FALSE;
1567         }
1568       
1569       link = _dbus_list_get_next_link (&connections->pending_replies->items,
1570                                        link);
1571     }
1572   
1573   pending = dbus_new0 (BusPendingReply, 1);
1574   if (pending == NULL)
1575     {
1576       BUS_SET_OOM (error);
1577       return FALSE;
1578     }
1579
1580 #ifdef DBUS_ENABLE_VERBOSE_MODE
1581   /* so we can see a not-yet-added pending reply */
1582   pending->expire_item.added_tv_sec = 1;
1583   pending->expire_item.added_tv_usec = 1;
1584 #endif
1585
1586   pending->will_get_reply = will_get_reply;
1587   pending->will_send_reply = will_send_reply;
1588   pending->reply_serial = reply_serial;
1589   
1590   cprd = dbus_new0 (CancelPendingReplyData, 1);
1591   if (cprd == NULL)
1592     {
1593       BUS_SET_OOM (error);
1594       bus_pending_reply_free (pending);
1595       return FALSE;
1596     }
1597   
1598   if (!_dbus_list_prepend (&connections->pending_replies->items,
1599                            pending))
1600     {
1601       BUS_SET_OOM (error);
1602       dbus_free (cprd);
1603       bus_pending_reply_free (pending);
1604       return FALSE;
1605     }
1606
1607   if (!bus_transaction_add_cancel_hook (transaction,
1608                                         cancel_pending_reply,
1609                                         cprd,
1610                                         cancel_pending_reply_data_free))
1611     {
1612       BUS_SET_OOM (error);
1613       _dbus_list_remove (&connections->pending_replies->items, pending);
1614       dbus_free (cprd);
1615       bus_pending_reply_free (pending);
1616       return FALSE;
1617     }
1618                                         
1619   cprd->pending = pending;
1620   cprd->connections = connections;
1621   
1622   _dbus_get_current_time (&pending->expire_item.added_tv_sec,
1623                           &pending->expire_item.added_tv_usec);
1624
1625   _dbus_verbose ("Added pending reply %p, replier %p receiver %p serial %u\n",
1626                  pending,
1627                  pending->will_send_reply,
1628                  pending->will_get_reply,
1629                  pending->reply_serial);
1630   
1631   return TRUE;
1632 }
1633
1634 typedef struct
1635 {
1636   DBusList        *link;
1637   BusConnections  *connections;
1638 } CheckPendingReplyData;
1639
1640 static void
1641 cancel_check_pending_reply (void *data)
1642 {
1643   CheckPendingReplyData *d = data;
1644
1645   _dbus_verbose ("%s: d = %p\n", _DBUS_FUNCTION_NAME, d);
1646   
1647   _dbus_list_prepend_link (&d->connections->pending_replies->items,
1648                            d->link);
1649   d->link = NULL;
1650 }
1651
1652 static void
1653 check_pending_reply_data_free (void *data)
1654 {
1655   CheckPendingReplyData *d = data;
1656
1657   _dbus_verbose ("%s: d = %p\n", _DBUS_FUNCTION_NAME, d);
1658   
1659   if (d->link != NULL)
1660     {
1661       BusPendingReply *pending = d->link->data;
1662       
1663       _dbus_assert (_dbus_list_find_last (&d->connections->pending_replies->items,
1664                                           pending) == NULL);
1665       
1666       bus_pending_reply_free (pending);
1667       _dbus_list_free_link (d->link);
1668     }
1669   
1670   dbus_free (d);
1671 }
1672
1673 /*
1674  * Check whether a reply is allowed, remove BusPendingReply
1675  * if so, return TRUE if so.
1676  */
1677 dbus_bool_t
1678 bus_connections_check_reply (BusConnections *connections,
1679                              BusTransaction *transaction,
1680                              DBusConnection *sending_reply,
1681                              DBusConnection *receiving_reply,
1682                              DBusMessage    *reply,
1683                              DBusError      *error)
1684 {
1685   CheckPendingReplyData *cprd;
1686   DBusList *link;
1687   dbus_uint32_t reply_serial;
1688   
1689   _dbus_assert (sending_reply != NULL);
1690   _dbus_assert (receiving_reply != NULL);
1691
1692   reply_serial = dbus_message_get_reply_serial (reply);
1693
1694   link = _dbus_list_get_first_link (&connections->pending_replies->items);
1695   while (link != NULL)
1696     {
1697       BusPendingReply *pending = link->data;
1698
1699       if (pending->reply_serial == reply_serial &&
1700           pending->will_get_reply == receiving_reply &&
1701           pending->will_send_reply == sending_reply)
1702         {
1703           _dbus_verbose ("Found pending reply with serial %u\n", reply_serial);
1704           break;
1705         }
1706       
1707       link = _dbus_list_get_next_link (&connections->pending_replies->items,
1708                                        link);
1709     }
1710
1711   if (link == NULL)
1712     {
1713       _dbus_verbose ("No pending reply expected\n");
1714
1715       return FALSE;
1716     }
1717
1718   cprd = dbus_new0 (CheckPendingReplyData, 1);
1719   if (cprd == NULL)
1720     {
1721       BUS_SET_OOM (error);
1722       return FALSE;
1723     }
1724   
1725   if (!bus_transaction_add_cancel_hook (transaction,
1726                                         cancel_check_pending_reply,
1727                                         cprd,
1728                                         check_pending_reply_data_free))
1729     {
1730       BUS_SET_OOM (error);
1731       dbus_free (cprd);
1732       return FALSE;
1733     }
1734
1735   cprd->link = link;
1736   cprd->connections = connections;
1737   
1738   _dbus_list_unlink (&connections->pending_replies->items,
1739                      link);
1740   
1741   _dbus_assert (_dbus_list_find_last (&connections->pending_replies->items,
1742                                       link->data) == NULL);
1743
1744   return TRUE;
1745 }
1746
1747 /*
1748  * Transactions
1749  *
1750  * Note that this is fairly fragile; in particular, don't try to use
1751  * one transaction across any main loop iterations.
1752  */
1753
1754 typedef struct
1755 {
1756   BusTransaction *transaction;
1757   DBusMessage    *message;
1758   DBusPreallocatedSend *preallocated;
1759 } MessageToSend;
1760
1761 typedef struct
1762 {
1763   BusTransactionCancelFunction cancel_function;
1764   DBusFreeFunction free_data_function;
1765   void *data;
1766 } CancelHook;
1767
1768 struct BusTransaction
1769 {
1770   DBusList *connections;
1771   BusContext *context;
1772   DBusList *cancel_hooks;
1773 };
1774
1775 static void
1776 message_to_send_free (DBusConnection *connection,
1777                       MessageToSend  *to_send)
1778 {
1779   if (to_send->message)
1780     dbus_message_unref (to_send->message);
1781
1782   if (to_send->preallocated)
1783     dbus_connection_free_preallocated_send (connection, to_send->preallocated);
1784
1785   dbus_free (to_send);
1786 }
1787
1788 static void
1789 cancel_hook_cancel (void *element,
1790                     void *data)
1791 {
1792   CancelHook *ch = element;
1793
1794   _dbus_verbose ("Running transaction cancel hook\n");
1795   
1796   if (ch->cancel_function)
1797     (* ch->cancel_function) (ch->data);  
1798 }
1799
1800 static void
1801 cancel_hook_free (void *element,
1802                   void *data)
1803 {
1804   CancelHook *ch = element;
1805
1806   if (ch->free_data_function)
1807     (* ch->free_data_function) (ch->data);
1808
1809   dbus_free (ch);
1810 }
1811
1812 static void
1813 free_cancel_hooks (BusTransaction *transaction)
1814 {
1815   _dbus_list_foreach (&transaction->cancel_hooks,
1816                       cancel_hook_free, NULL);
1817   
1818   _dbus_list_clear (&transaction->cancel_hooks);
1819 }
1820
1821 BusTransaction*
1822 bus_transaction_new (BusContext *context)
1823 {
1824   BusTransaction *transaction;
1825
1826   transaction = dbus_new0 (BusTransaction, 1);
1827   if (transaction == NULL)
1828     return NULL;
1829
1830   transaction->context = context;
1831   
1832   return transaction;
1833 }
1834
1835 BusContext*
1836 bus_transaction_get_context (BusTransaction  *transaction)
1837 {
1838   return transaction->context;
1839 }
1840
1841 BusConnections*
1842 bus_transaction_get_connections (BusTransaction  *transaction)
1843 {
1844   return bus_context_get_connections (transaction->context);
1845 }
1846
1847 dbus_bool_t
1848 bus_transaction_send_from_driver (BusTransaction *transaction,
1849                                   DBusConnection *connection,
1850                                   DBusMessage    *message)
1851 {
1852   /* We have to set the sender to the driver, and have
1853    * to check security policy since it was not done in
1854    * dispatch.c
1855    */
1856   _dbus_verbose ("Sending %s %s %s from driver\n",
1857                  dbus_message_get_interface (message) ?
1858                  dbus_message_get_interface (message) : "(no interface)",
1859                  dbus_message_get_member (message) ?
1860                  dbus_message_get_member (message) : "(no member)",
1861                  dbus_message_get_error_name (message) ?
1862                  dbus_message_get_error_name (message) : "(no error name)");
1863                  
1864   if (!dbus_message_set_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
1865     return FALSE;
1866
1867   if (bus_connection_is_active (connection))
1868     {
1869       if (!dbus_message_set_destination (message,
1870                                          bus_connection_get_name (connection)))
1871         return FALSE;
1872     }
1873   
1874   /* bus driver never wants a reply */
1875   dbus_message_set_no_reply (message, TRUE);
1876   
1877   /* If security policy doesn't allow the message, we silently
1878    * eat it; the driver doesn't care about getting a reply.
1879    */
1880   if (!bus_context_check_security_policy (bus_transaction_get_context (transaction),
1881                                           transaction,
1882                                           NULL, connection, connection, message, NULL))
1883     return TRUE;
1884
1885   return bus_transaction_send (transaction, connection, message);
1886 }
1887
1888 dbus_bool_t
1889 bus_transaction_send (BusTransaction *transaction,
1890                       DBusConnection *connection,
1891                       DBusMessage    *message)
1892 {
1893   MessageToSend *to_send;
1894   BusConnectionData *d;
1895   DBusList *link;
1896
1897   _dbus_verbose ("  trying to add %s interface=%s member=%s error=%s to transaction%s\n",
1898                  dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ? "error" :
1899                  dbus_message_get_reply_serial (message) != 0 ? "reply" :
1900                  "message",
1901                  dbus_message_get_interface (message) ?
1902                  dbus_message_get_interface (message) : "(unset)",
1903                  dbus_message_get_member (message) ?
1904                  dbus_message_get_member (message) : "(unset)",
1905                  dbus_message_get_error_name (message) ?
1906                  dbus_message_get_error_name (message) : "(unset)",
1907                  dbus_connection_get_is_connected (connection) ?
1908                  "" : " (disconnected)");
1909
1910   _dbus_assert (dbus_message_get_sender (message) != NULL);
1911   
1912   if (!dbus_connection_get_is_connected (connection))
1913     return TRUE; /* silently ignore disconnected connections */
1914   
1915   d = BUS_CONNECTION_DATA (connection);
1916   _dbus_assert (d != NULL);
1917   
1918   to_send = dbus_new (MessageToSend, 1);
1919   if (to_send == NULL)
1920     {
1921       return FALSE;
1922     }
1923
1924   to_send->preallocated = dbus_connection_preallocate_send (connection);
1925   if (to_send->preallocated == NULL)
1926     {
1927       dbus_free (to_send);
1928       return FALSE;
1929     }  
1930   
1931   dbus_message_ref (message);
1932   to_send->message = message;
1933   to_send->transaction = transaction;
1934
1935   _dbus_verbose ("about to prepend message\n");
1936   
1937   if (!_dbus_list_prepend (&d->transaction_messages, to_send))
1938     {
1939       message_to_send_free (connection, to_send);
1940       return FALSE;
1941     }
1942
1943   _dbus_verbose ("prepended message\n");
1944   
1945   /* See if we already had this connection in the list
1946    * for this transaction. If we have a pending message,
1947    * then we should already be in transaction->connections
1948    */
1949   link = _dbus_list_get_first_link (&d->transaction_messages);
1950   _dbus_assert (link->data == to_send);
1951   link = _dbus_list_get_next_link (&d->transaction_messages, link);
1952   while (link != NULL)
1953     {
1954       MessageToSend *m = link->data;
1955       DBusList *next = _dbus_list_get_next_link (&d->transaction_messages, link);
1956       
1957       if (m->transaction == transaction)
1958         break;
1959         
1960       link = next;
1961     }
1962
1963   if (link == NULL)
1964     {
1965       if (!_dbus_list_prepend (&transaction->connections, connection))
1966         {
1967           _dbus_list_remove (&d->transaction_messages, to_send);
1968           message_to_send_free (connection, to_send);
1969           return FALSE;
1970         }
1971     }
1972
1973   return TRUE;
1974 }
1975
1976 static void
1977 connection_cancel_transaction (DBusConnection *connection,
1978                                BusTransaction *transaction)
1979 {
1980   DBusList *link;
1981   BusConnectionData *d;
1982   
1983   d = BUS_CONNECTION_DATA (connection);
1984   _dbus_assert (d != NULL);
1985   
1986   link = _dbus_list_get_first_link (&d->transaction_messages);
1987   while (link != NULL)
1988     {
1989       MessageToSend *m = link->data;
1990       DBusList *next = _dbus_list_get_next_link (&d->transaction_messages, link);
1991       
1992       if (m->transaction == transaction)
1993         {
1994           _dbus_list_remove_link (&d->transaction_messages,
1995                                   link);
1996           
1997           message_to_send_free (connection, m);
1998         }
1999         
2000       link = next;
2001     }
2002 }
2003
2004 void
2005 bus_transaction_cancel_and_free (BusTransaction *transaction)
2006 {
2007   DBusConnection *connection;
2008
2009   _dbus_verbose ("TRANSACTION: cancelled\n");
2010   
2011   while ((connection = _dbus_list_pop_first (&transaction->connections)))
2012     connection_cancel_transaction (connection, transaction);
2013
2014   _dbus_assert (transaction->connections == NULL);
2015
2016   _dbus_list_foreach (&transaction->cancel_hooks,
2017                       cancel_hook_cancel, NULL);
2018
2019   free_cancel_hooks (transaction);
2020   
2021   dbus_free (transaction);
2022 }
2023
2024 static void
2025 connection_execute_transaction (DBusConnection *connection,
2026                                 BusTransaction *transaction)
2027 {
2028   DBusList *link;
2029   BusConnectionData *d;
2030   
2031   d = BUS_CONNECTION_DATA (connection);
2032   _dbus_assert (d != NULL);
2033
2034   /* Send the queue in order (FIFO) */
2035   link = _dbus_list_get_last_link (&d->transaction_messages);
2036   while (link != NULL)
2037     {
2038       MessageToSend *m = link->data;
2039       DBusList *prev = _dbus_list_get_prev_link (&d->transaction_messages, link);
2040       
2041       if (m->transaction == transaction)
2042         {
2043           _dbus_list_remove_link (&d->transaction_messages,
2044                                   link);
2045
2046           _dbus_assert (dbus_message_get_sender (m->message) != NULL);
2047           
2048           dbus_connection_send_preallocated (connection,
2049                                              m->preallocated,
2050                                              m->message,
2051                                              NULL);
2052
2053           m->preallocated = NULL; /* so we don't double-free it */
2054           
2055           message_to_send_free (connection, m);
2056         }
2057         
2058       link = prev;
2059     }
2060 }
2061
2062 void
2063 bus_transaction_execute_and_free (BusTransaction *transaction)
2064 {
2065   /* For each connection in transaction->connections
2066    * send the messages
2067    */
2068   DBusConnection *connection;
2069
2070   _dbus_verbose ("TRANSACTION: executing\n");
2071   
2072   while ((connection = _dbus_list_pop_first (&transaction->connections)))
2073     connection_execute_transaction (connection, transaction);
2074
2075   _dbus_assert (transaction->connections == NULL);
2076
2077   free_cancel_hooks (transaction);
2078   
2079   dbus_free (transaction);
2080 }
2081
2082 static void
2083 bus_connection_remove_transactions (DBusConnection *connection)
2084 {
2085   MessageToSend *to_send;
2086   BusConnectionData *d;
2087   
2088   d = BUS_CONNECTION_DATA (connection);
2089   _dbus_assert (d != NULL);
2090   
2091   while ((to_send = _dbus_list_get_first (&d->transaction_messages)))
2092     {
2093       /* only has an effect for the first MessageToSend listing this transaction */
2094       _dbus_list_remove (&to_send->transaction->connections,
2095                          connection);
2096
2097       _dbus_list_remove (&d->transaction_messages, to_send);
2098       message_to_send_free (connection, to_send);
2099     }
2100 }
2101
2102 /**
2103  * Converts the DBusError to a message reply
2104  */
2105 dbus_bool_t
2106 bus_transaction_send_error_reply (BusTransaction  *transaction,
2107                                   DBusConnection  *connection,
2108                                   const DBusError *error,
2109                                   DBusMessage     *in_reply_to)
2110 {
2111   DBusMessage *reply;
2112   
2113   _dbus_assert (error != NULL);
2114   _DBUS_ASSERT_ERROR_IS_SET (error);
2115   
2116   _dbus_verbose ("Sending error reply %s \"%s\"\n",
2117                  error->name, error->message);
2118
2119   reply = dbus_message_new_error (in_reply_to,
2120                                   error->name,
2121                                   error->message);
2122   if (reply == NULL)
2123     return FALSE;
2124
2125   if (!bus_transaction_send_from_driver (transaction, connection, reply))
2126     {
2127       dbus_message_unref (reply);
2128       return FALSE;
2129     }
2130
2131   dbus_message_unref (reply);
2132   
2133   return TRUE;
2134 }
2135
2136 dbus_bool_t
2137 bus_transaction_add_cancel_hook (BusTransaction               *transaction,
2138                                  BusTransactionCancelFunction  cancel_function,
2139                                  void                         *data,
2140                                  DBusFreeFunction              free_data_function)
2141 {
2142   CancelHook *ch;
2143
2144   ch = dbus_new (CancelHook, 1);
2145   if (ch == NULL)
2146     return FALSE;
2147
2148   _dbus_verbose ("     adding cancel hook function = %p data = %p\n",
2149                  cancel_function, data);
2150   
2151   ch->cancel_function = cancel_function;
2152   ch->data = data;
2153   ch->free_data_function = free_data_function;
2154
2155   /* It's important that the hooks get run in reverse order that they
2156    * were added
2157    */
2158   if (!_dbus_list_prepend (&transaction->cancel_hooks, ch))
2159     {
2160       dbus_free (ch);
2161       return FALSE;
2162     }
2163
2164   return TRUE;
2165 }