6a4b55d62bb2d617c75171ea0ff3724cff806c2b
[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 };
59
60 static dbus_int32_t connection_data_slot = -1;
61
62 typedef struct
63 {
64   BusConnections *connections;
65   DBusList *link_in_connection_list;
66   DBusConnection *connection;
67   DBusList *services_owned;
68   int n_services_owned;
69   DBusList *match_rules;
70   int n_match_rules;
71   char *name;
72   DBusList *transaction_messages; /**< Stuff we need to send as part of a transaction */
73   DBusMessage *oom_message;
74   DBusPreallocatedSend *oom_preallocated;
75   BusClientPolicy *policy;
76
77   long connection_tv_sec;  /**< Time when we connected (seconds component) */
78   long connection_tv_usec; /**< Time when we connected (microsec component) */
79   int stamp;               /**< connections->stamp last time we were traversed */
80 } BusConnectionData;
81
82 static dbus_bool_t expire_incomplete_timeout (void *data);
83
84 #define BUS_CONNECTION_DATA(connection) (dbus_connection_get_data ((connection), connection_data_slot))
85
86 static DBusLoop*
87 connection_get_loop (DBusConnection *connection)
88 {
89   BusConnectionData *d;
90
91   d = BUS_CONNECTION_DATA (connection);
92
93   return bus_context_get_loop (d->connections->context);
94 }
95
96
97 static int
98 get_connections_for_uid (BusConnections *connections,
99                          dbus_uid_t      uid)
100 {
101   void *val;
102   int current_count;
103
104   /* val is NULL is 0 when it isn't in the hash yet */
105   
106   val = _dbus_hash_table_lookup_ulong (connections->completed_by_user,
107                                        uid);
108
109   current_count = _DBUS_POINTER_TO_INT (val);
110
111   return current_count;
112 }
113
114 static dbus_bool_t
115 adjust_connections_for_uid (BusConnections *connections,
116                             dbus_uid_t      uid,
117                             int             adjustment)
118 {
119   int current_count;
120
121   current_count = get_connections_for_uid (connections, uid);
122
123   _dbus_verbose ("Adjusting connection count for UID " DBUS_UID_FORMAT
124                  ": was %d adjustment %d making %d\n",
125                  uid, current_count, adjustment, current_count + adjustment);
126   
127   _dbus_assert (current_count >= 0);
128   
129   current_count += adjustment;
130
131   _dbus_assert (current_count >= 0);
132
133   if (current_count == 0)
134     {
135       _dbus_hash_table_remove_ulong (connections->completed_by_user, uid);
136       return TRUE;
137     }
138   else
139     {
140       dbus_bool_t retval;
141       
142       retval = _dbus_hash_table_insert_ulong (connections->completed_by_user,
143                                               uid, _DBUS_INT_TO_POINTER (current_count));
144
145       /* only positive adjustment can fail as otherwise
146        * a hash entry should already exist
147        */
148       _dbus_assert (adjustment > 0 ||
149                     (adjustment <= 0 && retval));
150
151       return retval;
152     }
153 }
154
155 void
156 bus_connection_disconnected (DBusConnection *connection)
157 {
158   BusConnectionData *d;
159   BusService *service;
160   BusMatchmaker *matchmaker;
161   
162   d = BUS_CONNECTION_DATA (connection);
163   _dbus_assert (d != NULL);
164
165   _dbus_verbose ("%s disconnected, dropping all service ownership and releasing\n",
166                  d->name ? d->name : "(inactive)");
167
168   /* Delete our match rules */
169   if (d->n_match_rules > 0)
170     {
171       matchmaker = bus_context_get_matchmaker (d->connections->context);
172       bus_matchmaker_disconnected (matchmaker, connection);
173     }
174   
175   /* Drop any service ownership. FIXME Unfortunately, this requires
176    * memory allocation and there doesn't seem to be a good way to
177    * handle it other than sleeping; we can't "fail" the operation of
178    * disconnecting a client, and preallocating a broadcast "service is
179    * now gone" message for every client-service pair seems kind of
180    * involved. Probably we need to do that though.
181    */
182   while ((service = _dbus_list_get_last (&d->services_owned)))
183     {
184       BusTransaction *transaction;
185       DBusError error;
186
187     retry:
188       
189       dbus_error_init (&error);
190         
191       transaction = NULL;
192       while (transaction == NULL)
193         {
194           transaction = bus_transaction_new (d->connections->context);
195           _dbus_wait_for_memory ();
196         }
197         
198       if (!bus_service_remove_owner (service, connection,
199                                      transaction, &error))
200         {
201           _DBUS_ASSERT_ERROR_IS_SET (&error);
202           
203           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
204             {
205               dbus_error_free (&error);
206               bus_transaction_cancel_and_free (transaction);
207               _dbus_wait_for_memory ();
208               goto retry;
209             }
210           else
211             {
212               _dbus_verbose ("Failed to remove service owner: %s %s\n",
213                              error.name, error.message);
214               _dbus_assert_not_reached ("Removing service owner failed for non-memory-related reason");
215             }
216         }
217         
218       bus_transaction_execute_and_free (transaction);
219     }
220
221   bus_dispatch_remove_connection (connection);
222   
223   /* no more watching */
224   if (!dbus_connection_set_watch_functions (connection,
225                                             NULL, NULL, NULL,
226                                             connection,
227                                             NULL))
228     _dbus_assert_not_reached ("setting watch functions to NULL failed");
229
230   if (!dbus_connection_set_timeout_functions (connection,
231                                               NULL, NULL, NULL,
232                                               connection,
233                                               NULL))
234     _dbus_assert_not_reached ("setting timeout functions to NULL failed");
235   
236   dbus_connection_set_unix_user_function (connection,
237                                           NULL, NULL, NULL);
238
239   dbus_connection_set_dispatch_status_function (connection,
240                                                 NULL, NULL, NULL);
241   
242   bus_connection_remove_transactions (connection);
243
244   if (d->link_in_connection_list != NULL)
245     {
246       if (d->name != NULL)
247         {
248           unsigned long uid;
249           
250           _dbus_list_remove_link (&d->connections->completed, d->link_in_connection_list);
251           d->link_in_connection_list = NULL;
252           d->connections->n_completed -= 1;
253
254           if (dbus_connection_get_unix_user (connection, &uid))
255             {
256               if (!adjust_connections_for_uid (d->connections,
257                                                uid, -1))
258                 _dbus_assert_not_reached ("adjusting downward should never fail");
259             }
260         }
261       else
262         {
263           _dbus_list_remove_link (&d->connections->incomplete, d->link_in_connection_list);
264           d->link_in_connection_list = NULL;
265           d->connections->n_incomplete -= 1;
266         }
267       
268       _dbus_assert (d->connections->n_incomplete >= 0);
269       _dbus_assert (d->connections->n_completed >= 0);
270     }
271   
272   /* frees "d" as side effect */
273   dbus_connection_set_data (connection,
274                             connection_data_slot,
275                             NULL, NULL);
276
277   dbus_connection_unref (connection);
278 }
279
280 static dbus_bool_t
281 connection_watch_callback (DBusWatch     *watch,
282                            unsigned int   condition,
283                            void          *data)
284 {
285  /* FIXME this can be done in dbus-mainloop.c
286   * if the code in activation.c for the babysitter
287   * watch handler is fixed.
288   */
289   
290 #if 0
291   _dbus_verbose ("Calling handle_watch\n");
292 #endif
293   return dbus_watch_handle (watch, condition);
294 }
295
296 static dbus_bool_t
297 add_connection_watch (DBusWatch      *watch,
298                       void           *data)
299 {
300   DBusConnection *connection = data;
301
302   return _dbus_loop_add_watch (connection_get_loop (connection),
303                                watch, connection_watch_callback, connection,
304                                NULL);
305 }
306
307 static void
308 remove_connection_watch (DBusWatch      *watch,
309                          void           *data)
310 {
311   DBusConnection *connection = data;
312   
313   _dbus_loop_remove_watch (connection_get_loop (connection),
314                            watch, connection_watch_callback, connection);
315 }
316
317 static void
318 connection_timeout_callback (DBusTimeout   *timeout,
319                              void          *data)
320 {
321   /* DBusConnection *connection = data; */
322
323   /* can return FALSE on OOM but we just let it fire again later */
324   dbus_timeout_handle (timeout);
325 }
326
327 static dbus_bool_t
328 add_connection_timeout (DBusTimeout    *timeout,
329                         void           *data)
330 {
331   DBusConnection *connection = data;
332   
333   return _dbus_loop_add_timeout (connection_get_loop (connection),
334                                  timeout, connection_timeout_callback, connection, NULL);
335 }
336
337 static void
338 remove_connection_timeout (DBusTimeout    *timeout,
339                            void           *data)
340 {
341   DBusConnection *connection = data;
342   
343   _dbus_loop_remove_timeout (connection_get_loop (connection),
344                              timeout, connection_timeout_callback, connection);
345 }
346
347 static void
348 dispatch_status_function (DBusConnection    *connection,
349                           DBusDispatchStatus new_status,
350                           void              *data)
351 {
352   DBusLoop *loop = data;
353   
354   if (new_status != DBUS_DISPATCH_COMPLETE)
355     {
356       while (!_dbus_loop_queue_dispatch (loop, connection))
357         _dbus_wait_for_memory ();
358     }
359 }
360
361 static dbus_bool_t
362 allow_user_function (DBusConnection *connection,
363                      unsigned long   uid,
364                      void           *data)
365 {
366   BusConnectionData *d;
367     
368   d = BUS_CONNECTION_DATA (connection);
369
370   _dbus_assert (d != NULL);
371   
372   return bus_context_allow_user (d->connections->context, uid);
373 }
374
375 static void
376 free_connection_data (void *data)
377 {
378   BusConnectionData *d = data;
379
380   /* services_owned should be NULL since we should be disconnected */
381   _dbus_assert (d->services_owned == NULL);
382   _dbus_assert (d->n_services_owned == 0);
383   /* similarly */
384   _dbus_assert (d->transaction_messages == NULL);
385
386   if (d->oom_preallocated)
387     dbus_connection_free_preallocated_send (d->connection, d->oom_preallocated);
388
389   if (d->oom_message)
390     dbus_message_unref (d->oom_message);
391
392   if (d->policy)
393     bus_client_policy_unref (d->policy);
394   
395   dbus_free (d->name);
396   
397   dbus_free (d);
398 }
399
400 static void
401 call_timeout_callback (DBusTimeout   *timeout,
402                        void          *data)
403 {
404   /* can return FALSE on OOM but we just let it fire again later */
405   dbus_timeout_handle (timeout);
406 }
407
408 BusConnections*
409 bus_connections_new (BusContext *context)
410 {
411   BusConnections *connections;
412
413   if (!dbus_connection_allocate_data_slot (&connection_data_slot))
414     goto failed_0;
415
416   connections = dbus_new0 (BusConnections, 1);
417   if (connections == NULL)
418     goto failed_1;
419
420   connections->completed_by_user = _dbus_hash_table_new (DBUS_HASH_ULONG,
421                                                          NULL, NULL);
422   if (connections->completed_by_user == NULL)
423     goto failed_2;
424
425   connections->expire_timeout = _dbus_timeout_new (100, /* irrelevant */
426                                                    expire_incomplete_timeout,
427                                                    connections, NULL);
428   if (connections->expire_timeout == NULL)
429     goto failed_3;
430
431   _dbus_timeout_set_enabled (connections->expire_timeout, FALSE);
432
433   if (!_dbus_loop_add_timeout (bus_context_get_loop (context),
434                                connections->expire_timeout,
435                                call_timeout_callback, NULL, NULL))
436     goto failed_4;
437   
438   connections->refcount = 1;
439   connections->context = context;
440   
441   return connections;
442
443  failed_4:
444   _dbus_timeout_unref (connections->expire_timeout);
445  failed_3:
446   _dbus_hash_table_unref (connections->completed_by_user);
447  failed_2:
448   dbus_free (connections);
449  failed_1:
450   dbus_connection_free_data_slot (&connection_data_slot);
451  failed_0:
452   return NULL;
453 }
454
455 void
456 bus_connections_ref (BusConnections *connections)
457 {
458   _dbus_assert (connections->refcount > 0);
459   connections->refcount += 1;
460 }
461
462 void
463 bus_connections_unref (BusConnections *connections)
464 {
465   _dbus_assert (connections->refcount > 0);
466   connections->refcount -= 1;
467   if (connections->refcount == 0)
468     {
469       /* drop all incomplete */
470       while (connections->incomplete != NULL)
471         {
472           DBusConnection *connection;
473
474           connection = connections->incomplete->data;
475
476           dbus_connection_ref (connection);
477           dbus_connection_disconnect (connection);
478           bus_connection_disconnected (connection);
479           dbus_connection_unref (connection);
480         }
481
482       _dbus_assert (connections->n_incomplete == 0);
483       
484       /* drop all real connections */
485       while (connections->completed != NULL)
486         {
487           DBusConnection *connection;
488
489           connection = connections->completed->data;
490
491           dbus_connection_ref (connection);
492           dbus_connection_disconnect (connection);
493           bus_connection_disconnected (connection);
494           dbus_connection_unref (connection);          
495         }
496
497       _dbus_assert (connections->n_completed == 0);
498
499       _dbus_loop_remove_timeout (bus_context_get_loop (connections->context),
500                                  connections->expire_timeout,
501                                  call_timeout_callback, NULL);
502       
503       _dbus_timeout_unref (connections->expire_timeout);
504       
505       _dbus_hash_table_unref (connections->completed_by_user);
506       
507       dbus_free (connections);
508
509       dbus_connection_free_data_slot (&connection_data_slot);
510     }
511 }
512
513 dbus_bool_t
514 bus_connections_setup_connection (BusConnections *connections,
515                                   DBusConnection *connection)
516 {
517   BusConnectionData *d;
518   dbus_bool_t retval;
519   
520   d = dbus_new0 (BusConnectionData, 1);
521   
522   if (d == NULL)
523     return FALSE;
524
525   d->connections = connections;
526   d->connection = connection;
527   
528   _dbus_get_current_time (&d->connection_tv_sec,
529                           &d->connection_tv_usec);
530   
531   _dbus_assert (connection_data_slot >= 0);
532   
533   if (!dbus_connection_set_data (connection,
534                                  connection_data_slot,
535                                  d, free_connection_data))
536     {
537       dbus_free (d);
538       return FALSE;
539     }
540
541   retval = FALSE;
542   
543   if (!dbus_connection_set_watch_functions (connection,
544                                             add_connection_watch,
545                                             remove_connection_watch,
546                                             NULL,
547                                             connection,
548                                             NULL))
549     goto out;
550   
551   if (!dbus_connection_set_timeout_functions (connection,
552                                               add_connection_timeout,
553                                               remove_connection_timeout,
554                                               NULL,
555                                               connection, NULL))
556     goto out;
557   
558   dbus_connection_set_unix_user_function (connection,
559                                           allow_user_function,
560                                           NULL, NULL);
561
562   dbus_connection_set_dispatch_status_function (connection,
563                                                 dispatch_status_function,
564                                                 bus_context_get_loop (connections->context),
565                                                 NULL);
566
567   d->link_in_connection_list = _dbus_list_alloc_link (connection);
568   if (d->link_in_connection_list == NULL)
569     goto out;
570   
571   /* Setup the connection with the dispatcher */
572   if (!bus_dispatch_add_connection (connection))
573     goto out;
574
575   if (dbus_connection_get_dispatch_status (connection) != DBUS_DISPATCH_COMPLETE)
576     {
577       if (!_dbus_loop_queue_dispatch (bus_context_get_loop (connections->context), connection))
578         {
579           bus_dispatch_remove_connection (connection);
580           goto out;
581         }
582     }
583
584   _dbus_list_append_link (&connections->incomplete, d->link_in_connection_list);
585   connections->n_incomplete += 1;
586   
587   dbus_connection_ref (connection);
588
589   /* Note that we might disconnect ourselves here, but it only takes
590    * effect on return to the main loop. We call this to free up
591    * expired connections if possible, and to queue the timeout for our
592    * own expiration.
593    */
594   bus_connections_expire_incomplete (connections);
595   
596   /* And we might also disconnect ourselves here, but again it
597    * only takes effect on return to main loop.
598    */
599   if (connections->n_incomplete >
600       bus_context_get_max_incomplete_connections (connections->context))
601     {
602       _dbus_verbose ("Number of incomplete connections exceeds max, dropping oldest one\n");
603       
604       _dbus_assert (connections->incomplete != NULL);
605       /* Disconnect the oldest unauthenticated connection.  FIXME
606        * would it be more secure to drop a *random* connection?  This
607        * algorithm seems to mean that if someone can create new
608        * connections quickly enough, they can keep anyone else from
609        * completing authentication. But random may or may not really
610        * help with that, a more elaborate solution might be required.
611        */
612       dbus_connection_disconnect (connections->incomplete->data);
613     }
614   
615   retval = TRUE;
616
617  out:
618   if (!retval)
619     {      
620       if (!dbus_connection_set_watch_functions (connection,
621                                                 NULL, NULL, NULL,
622                                                 connection,
623                                                 NULL))
624         _dbus_assert_not_reached ("setting watch functions to NULL failed");
625       
626       if (!dbus_connection_set_timeout_functions (connection,
627                                                   NULL, NULL, NULL,
628                                                   connection,
629                                                   NULL))
630         _dbus_assert_not_reached ("setting timeout functions to NULL failed");
631
632       dbus_connection_set_unix_user_function (connection,
633                                               NULL, NULL, NULL);
634
635       dbus_connection_set_dispatch_status_function (connection,
636                                                     NULL, NULL, NULL);
637
638       if (d->link_in_connection_list != NULL)
639         {
640           _dbus_assert (d->link_in_connection_list->next == NULL);
641           _dbus_assert (d->link_in_connection_list->prev == NULL);
642           _dbus_list_free_link (d->link_in_connection_list);
643           d->link_in_connection_list = NULL;
644         }
645       
646       if (!dbus_connection_set_data (connection,
647                                      connection_data_slot,
648                                      NULL, NULL))
649         _dbus_assert_not_reached ("failed to set connection data to null");
650
651       /* "d" has now been freed */
652     }
653   
654   return retval;
655 }
656
657 void
658 bus_connections_expire_incomplete (BusConnections *connections)
659 {    
660   int next_interval;
661
662   next_interval = -1;
663   
664   if (connections->incomplete != NULL)
665     {
666       long tv_sec, tv_usec;
667       DBusList *link;
668       int auth_timeout;
669       
670       _dbus_get_current_time (&tv_sec, &tv_usec);
671       auth_timeout = bus_context_get_auth_timeout (connections->context);
672   
673       link = _dbus_list_get_first_link (&connections->incomplete);
674       while (link != NULL)
675         {
676           DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link);
677           DBusConnection *connection;
678           BusConnectionData *d;
679           double elapsed;
680       
681           connection = link->data;
682       
683           d = BUS_CONNECTION_DATA (connection);
684       
685           _dbus_assert (d != NULL);
686       
687           elapsed = ELAPSED_MILLISECONDS_SINCE (d->connection_tv_sec,
688                                                 d->connection_tv_usec,
689                                                 tv_sec, tv_usec);
690
691           if (elapsed >= (double) auth_timeout)
692             {
693               _dbus_verbose ("Timing out authentication for connection %p\n", connection);
694               dbus_connection_disconnect (connection);
695             }
696           else
697             {
698               /* We can end the loop, since the connections are in oldest-first order */
699               next_interval = ((double)auth_timeout) - elapsed;
700               _dbus_verbose ("Connection %p authentication expires in %d milliseconds\n",
701                              connection, next_interval);
702           
703               break;
704             }
705       
706           link = next;
707         }
708     }
709
710   bus_expire_timeout_set_interval (connections->expire_timeout,
711                                    next_interval);
712 }
713
714 static dbus_bool_t
715 expire_incomplete_timeout (void *data)
716 {
717   BusConnections *connections = data;
718
719   _dbus_verbose ("Running %s\n", _DBUS_FUNCTION_NAME);
720   
721   /* note that this may remove the timeout */
722   bus_connections_expire_incomplete (connections);
723
724   return TRUE;
725 }
726
727 dbus_bool_t
728 bus_connection_get_groups  (DBusConnection   *connection,
729                             unsigned long   **groups,
730                             int              *n_groups,
731                             DBusError        *error)
732 {
733   BusConnectionData *d;
734   unsigned long uid;
735   DBusUserDatabase *user_database;
736   
737   d = BUS_CONNECTION_DATA (connection);
738
739   _dbus_assert (d != NULL);
740
741   user_database = bus_context_get_user_database (d->connections->context);
742   
743   *groups = NULL;
744   *n_groups = 0;
745
746   if (dbus_connection_get_unix_user (connection, &uid))
747     {
748       if (!_dbus_user_database_get_groups (user_database,
749                                            uid, groups, n_groups,
750                                            error))
751         {
752           _DBUS_ASSERT_ERROR_IS_SET (error);
753           _dbus_verbose ("Did not get any groups for UID %lu\n",
754                          uid);
755           return FALSE;
756         }
757       else
758         {
759           _dbus_verbose ("Got %d groups for UID %lu\n",
760                          *n_groups, uid);
761           return TRUE;
762         }
763     }
764   else
765     return TRUE; /* successfully got 0 groups */
766 }
767
768 dbus_bool_t
769 bus_connection_is_in_group (DBusConnection *connection,
770                             unsigned long   gid)
771 {
772   int i;
773   unsigned long *group_ids;
774   int n_group_ids;
775
776   if (!bus_connection_get_groups (connection, &group_ids, &n_group_ids,
777                                   NULL))
778     return FALSE;
779
780   i = 0;
781   while (i < n_group_ids)
782     {
783       if (group_ids[i] == gid)
784         {
785           dbus_free (group_ids);
786           return TRUE;
787         }
788       ++i;
789     }
790
791   dbus_free (group_ids);
792   return FALSE;
793 }
794
795 BusClientPolicy*
796 bus_connection_get_policy (DBusConnection *connection)
797 {
798   BusConnectionData *d;
799     
800   d = BUS_CONNECTION_DATA (connection);
801
802   _dbus_assert (d != NULL);
803   _dbus_assert (d->policy != NULL);
804   
805   return d->policy;
806 }
807
808 static dbus_bool_t
809 foreach_active (BusConnections               *connections,
810                 BusConnectionForeachFunction  function,
811                 void                         *data)
812 {
813   DBusList *link;
814   
815   link = _dbus_list_get_first_link (&connections->completed);
816   while (link != NULL)
817     {
818       DBusConnection *connection = link->data;
819       DBusList *next = _dbus_list_get_next_link (&connections->completed, link);
820
821       if (!(* function) (connection, data))
822         return FALSE;
823       
824       link = next;
825     }
826
827   return TRUE;
828 }
829
830 static dbus_bool_t
831 foreach_inactive (BusConnections               *connections,
832                   BusConnectionForeachFunction  function,
833                   void                         *data)
834 {
835   DBusList *link;
836   
837   link = _dbus_list_get_first_link (&connections->incomplete);
838   while (link != NULL)
839     {
840       DBusConnection *connection = link->data;
841       DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link);
842
843       if (!(* function) (connection, data))
844         return FALSE;
845       
846       link = next;
847     }
848
849   return TRUE;
850 }
851
852 /**
853  * Calls function on each active connection; if the function returns
854  * #FALSE, stops iterating. Active connections are authenticated
855  * and have sent a Hello message.
856  *
857  * @param connections the connections object
858  * @param function the function
859  * @param data data to pass to it as a second arg
860  */
861 void
862 bus_connections_foreach_active (BusConnections               *connections,
863                                 BusConnectionForeachFunction  function,
864                                 void                         *data)
865 {
866   foreach_active (connections, function, data);
867 }
868
869 /**
870  * Calls function on each connection; if the function returns
871  * #FALSE, stops iterating.
872  *
873  * @param connections the connections object
874  * @param function the function
875  * @param data data to pass to it as a second arg
876  */
877 void
878 bus_connections_foreach (BusConnections               *connections,
879                          BusConnectionForeachFunction  function,
880                          void                         *data)
881 {
882   if (!foreach_active (connections, function, data))
883     return;
884
885   foreach_inactive (connections, function, data);
886 }
887
888 BusContext*
889 bus_connections_get_context (BusConnections *connections)
890 {
891   return connections->context;
892 }
893
894 /*
895  * This is used to avoid covering the same connection twice when
896  * traversing connections. Note that it assumes we will
897  * bus_connection_mark_stamp() each connection at least once per
898  * INT_MAX increments of the global stamp, or wraparound would break
899  * things.
900  */
901 void
902 bus_connections_increment_stamp (BusConnections *connections)
903 {
904   connections->stamp += 1;
905 }
906
907 /* Mark connection with current stamp, return TRUE if it
908  * didn't already have that stamp
909  */
910 dbus_bool_t
911 bus_connection_mark_stamp (DBusConnection *connection)
912 {
913   BusConnectionData *d;
914   
915   d = BUS_CONNECTION_DATA (connection);
916   
917   _dbus_assert (d != NULL);
918
919   if (d->stamp == d->connections->stamp)
920     return FALSE;
921   else
922     {
923       d->stamp = d->connections->stamp;
924       return TRUE;
925     }
926 }
927
928 BusContext*
929 bus_connection_get_context (DBusConnection *connection)
930 {
931   BusConnectionData *d;
932
933   d = BUS_CONNECTION_DATA (connection);
934
935   _dbus_assert (d != NULL);
936
937   return d->connections->context;
938 }
939
940 BusConnections*
941 bus_connection_get_connections (DBusConnection *connection)
942 {
943   BusConnectionData *d;
944     
945   d = BUS_CONNECTION_DATA (connection);
946
947   _dbus_assert (d != NULL);
948
949   return d->connections;
950 }
951
952 BusRegistry*
953 bus_connection_get_registry (DBusConnection *connection)
954 {
955   BusConnectionData *d;
956
957   d = BUS_CONNECTION_DATA (connection);
958
959   _dbus_assert (d != NULL);
960
961   return bus_context_get_registry (d->connections->context);
962 }
963
964 BusActivation*
965 bus_connection_get_activation (DBusConnection *connection)
966 {
967   BusConnectionData *d;
968
969   d = BUS_CONNECTION_DATA (connection);
970
971   _dbus_assert (d != NULL);
972
973   return bus_context_get_activation (d->connections->context);
974 }
975
976 BusMatchmaker*
977 bus_connection_get_matchmaker (DBusConnection *connection)
978 {
979   BusConnectionData *d;
980
981   d = BUS_CONNECTION_DATA (connection);
982
983   _dbus_assert (d != NULL);
984
985   return bus_context_get_matchmaker (d->connections->context);
986 }
987
988 /**
989  * Checks whether the connection is registered with the message bus.
990  *
991  * @param connection the connection
992  * @returns #TRUE if we're an active message bus participant
993  */
994 dbus_bool_t
995 bus_connection_is_active (DBusConnection *connection)
996 {
997   BusConnectionData *d;
998
999   d = BUS_CONNECTION_DATA (connection);
1000   
1001   return d != NULL && d->name != NULL;
1002 }
1003
1004 dbus_bool_t
1005 bus_connection_preallocate_oom_error (DBusConnection *connection)
1006 {
1007   DBusMessage *message;
1008   DBusPreallocatedSend *preallocated;
1009   BusConnectionData *d;
1010
1011   d = BUS_CONNECTION_DATA (connection);  
1012
1013   _dbus_assert (d != NULL);
1014
1015   if (d->oom_preallocated != NULL)
1016     return TRUE;
1017   
1018   preallocated = dbus_connection_preallocate_send (connection);
1019   if (preallocated == NULL)
1020     return FALSE;
1021
1022   message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
1023
1024   if (message == NULL)
1025     {
1026       dbus_connection_free_preallocated_send (connection, preallocated);
1027       return FALSE;
1028     }
1029
1030   /* d->name may be NULL, but that is OK */
1031   if (!dbus_message_set_error_name (message, DBUS_ERROR_NO_MEMORY) ||
1032       !dbus_message_set_destination (message, d->name) ||
1033       !dbus_message_set_sender (message,
1034                                 DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
1035     {
1036       dbus_connection_free_preallocated_send (connection, preallocated);
1037       dbus_message_unref (message);
1038       return FALSE;
1039     }
1040   
1041   /* set reply serial to placeholder value just so space is already allocated
1042    * for it.
1043    */
1044   if (!dbus_message_set_reply_serial (message, 14))
1045     {
1046       dbus_connection_free_preallocated_send (connection, preallocated);
1047       dbus_message_unref (message);
1048       return FALSE;
1049     }
1050
1051   d->oom_message = message;
1052   d->oom_preallocated = preallocated;
1053   
1054   return TRUE;
1055 }
1056
1057 void
1058 bus_connection_send_oom_error (DBusConnection *connection,
1059                                DBusMessage    *in_reply_to)
1060 {
1061   BusConnectionData *d;
1062
1063   d = BUS_CONNECTION_DATA (connection);  
1064
1065   _dbus_assert (d != NULL);  
1066   _dbus_assert (d->oom_message != NULL);
1067
1068   /* should always succeed since we set it to a placeholder earlier */
1069   if (!dbus_message_set_reply_serial (d->oom_message,
1070                                       dbus_message_get_serial (in_reply_to)))
1071     _dbus_assert_not_reached ("Failed to set reply serial for preallocated oom message");
1072
1073   _dbus_assert (dbus_message_get_sender (d->oom_message) != NULL);
1074   
1075   dbus_connection_send_preallocated (connection, d->oom_preallocated,
1076                                      d->oom_message, NULL);
1077
1078   dbus_message_unref (d->oom_message);
1079   d->oom_message = NULL;
1080   d->oom_preallocated = NULL;
1081 }
1082
1083 void
1084 bus_connection_add_match_rule_link (DBusConnection *connection,
1085                                     DBusList       *link)
1086 {
1087   BusConnectionData *d;
1088
1089   d = BUS_CONNECTION_DATA (connection);
1090   _dbus_assert (d != NULL);
1091
1092   _dbus_list_append_link (&d->match_rules, link);
1093
1094   d->n_match_rules += 1;
1095 }
1096
1097 dbus_bool_t
1098 bus_connection_add_match_rule (DBusConnection *connection,
1099                                BusMatchRule   *rule)
1100 {
1101     DBusList *link;
1102
1103   link = _dbus_list_alloc_link (rule);
1104
1105   if (link == NULL)
1106     return FALSE;
1107
1108   bus_connection_add_match_rule_link (connection, link);
1109
1110   return TRUE;
1111 }
1112
1113 void
1114 bus_connection_remove_match_rule (DBusConnection *connection,
1115                                   BusMatchRule   *rule)
1116 {
1117   BusConnectionData *d;
1118
1119   d = BUS_CONNECTION_DATA (connection);
1120   _dbus_assert (d != NULL);
1121
1122   _dbus_list_remove_last (&d->match_rules, rule);
1123
1124   d->n_match_rules -= 1;
1125   _dbus_assert (d->n_match_rules >= 0);
1126 }
1127
1128 int
1129 bus_connection_get_n_match_rules (DBusConnection *connection)
1130 {
1131   BusConnectionData *d;
1132
1133   d = BUS_CONNECTION_DATA (connection);
1134   _dbus_assert (d != NULL);
1135   
1136   return d->n_match_rules;
1137 }
1138
1139 void
1140 bus_connection_add_owned_service_link (DBusConnection *connection,
1141                                        DBusList       *link)
1142 {
1143   BusConnectionData *d;
1144
1145   d = BUS_CONNECTION_DATA (connection);
1146   _dbus_assert (d != NULL);
1147
1148   _dbus_list_append_link (&d->services_owned, link);
1149
1150   d->n_services_owned += 1;
1151 }
1152
1153 dbus_bool_t
1154 bus_connection_add_owned_service (DBusConnection *connection,
1155                                   BusService     *service)
1156 {
1157   DBusList *link;
1158
1159   link = _dbus_list_alloc_link (service);
1160
1161   if (link == NULL)
1162     return FALSE;
1163
1164   bus_connection_add_owned_service_link (connection, link);
1165
1166   return TRUE;
1167 }
1168
1169 void
1170 bus_connection_remove_owned_service (DBusConnection *connection,
1171                                      BusService     *service)
1172 {
1173   BusConnectionData *d;
1174
1175   d = BUS_CONNECTION_DATA (connection);
1176   _dbus_assert (d != NULL);
1177
1178   _dbus_list_remove_last (&d->services_owned, service);
1179
1180   d->n_services_owned -= 1;
1181   _dbus_assert (d->n_services_owned >= 0);
1182 }
1183
1184 int
1185 bus_connection_get_n_services_owned (DBusConnection *connection)
1186 {
1187   BusConnectionData *d;
1188
1189   d = BUS_CONNECTION_DATA (connection);
1190   _dbus_assert (d != NULL);
1191   
1192   return d->n_services_owned;
1193 }
1194
1195 dbus_bool_t
1196 bus_connection_complete (DBusConnection   *connection,
1197                          const DBusString *name,
1198                          DBusError        *error)
1199 {
1200   BusConnectionData *d;
1201   unsigned long uid;
1202   
1203   d = BUS_CONNECTION_DATA (connection);
1204   _dbus_assert (d != NULL);
1205   _dbus_assert (d->name == NULL);
1206   _dbus_assert (d->policy == NULL);
1207
1208   _dbus_assert (!bus_connection_is_active (connection));
1209   
1210   if (!_dbus_string_copy_data (name, &d->name))
1211     {
1212       BUS_SET_OOM (error);
1213       return FALSE;
1214     }
1215
1216   _dbus_assert (d->name != NULL);
1217   
1218   _dbus_verbose ("Name %s assigned to %p\n", d->name, connection);
1219
1220   d->policy = bus_context_create_client_policy (d->connections->context,
1221                                                 connection,
1222                                                 error);
1223
1224   /* we may have a NULL policy on OOM or error getting list of
1225    * groups for a user. In the latter case we don't handle it so
1226    * well currently, as it will just keep failing over and over.
1227    */
1228
1229   if (d->policy == NULL)
1230     {
1231       _dbus_verbose ("Failed to create security policy for connection %p\n",
1232                      connection);
1233       _DBUS_ASSERT_ERROR_IS_SET (error);
1234       dbus_free (d->name);
1235       d->name = NULL;
1236       return FALSE;
1237     }
1238   
1239   if (dbus_connection_get_unix_user (connection, &uid))
1240     {
1241       if (!adjust_connections_for_uid (d->connections,
1242                                        uid, 1))
1243         {
1244           BUS_SET_OOM (error);
1245           dbus_free (d->name);
1246           d->name = NULL;
1247           return FALSE;
1248         }
1249     }
1250   
1251   /* Now the connection is active, move it between lists */
1252   _dbus_list_unlink (&d->connections->incomplete,
1253                      d->link_in_connection_list);
1254   d->connections->n_incomplete -= 1;
1255   _dbus_list_append_link (&d->connections->completed,
1256                           d->link_in_connection_list);
1257   d->connections->n_completed += 1;
1258
1259   _dbus_assert (d->connections->n_incomplete >= 0);
1260   _dbus_assert (d->connections->n_completed > 0);
1261
1262   /* See if we can remove the timeout */
1263   bus_connections_expire_incomplete (d->connections);
1264
1265   _dbus_assert (bus_connection_is_active (connection));
1266   
1267   return TRUE;
1268 }
1269
1270 const char *
1271 bus_connection_get_name (DBusConnection *connection)
1272 {
1273   BusConnectionData *d;
1274   
1275   d = BUS_CONNECTION_DATA (connection);
1276   _dbus_assert (d != NULL);
1277   
1278   return d->name;
1279 }
1280
1281 /**
1282  * Check whether completing the passed-in connection would
1283  * exceed limits, and if so set error and return #FALSE
1284  */
1285 dbus_bool_t
1286 bus_connections_check_limits (BusConnections  *connections,
1287                               DBusConnection  *requesting_completion,
1288                               DBusError       *error)
1289 {
1290   BusConnectionData *d;
1291   unsigned long uid;
1292   
1293   d = BUS_CONNECTION_DATA (requesting_completion);
1294   _dbus_assert (d != NULL);
1295
1296   _dbus_assert (d->name == NULL);
1297
1298   if (connections->n_completed >=
1299       bus_context_get_max_completed_connections (connections->context))
1300     {
1301       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
1302                       "The maximum number of active connections has been reached");
1303       return FALSE;
1304     }
1305   
1306   if (dbus_connection_get_unix_user (requesting_completion, &uid))
1307     {
1308       if (get_connections_for_uid (connections, uid) >=
1309           bus_context_get_max_connections_per_user (connections->context))
1310         {
1311           dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
1312                           "The maximum number of active connections for UID %lu has been reached",
1313                           uid);
1314           return FALSE;
1315         }
1316     }
1317   
1318   return TRUE;
1319 }
1320
1321
1322 /*
1323  * Transactions
1324  *
1325  * Note that this is fairly fragile; in particular, don't try to use
1326  * one transaction across any main loop iterations.
1327  */
1328
1329 typedef struct
1330 {
1331   BusTransaction *transaction;
1332   DBusMessage    *message;
1333   DBusPreallocatedSend *preallocated;
1334 } MessageToSend;
1335
1336 typedef struct
1337 {
1338   BusTransactionCancelFunction cancel_function;
1339   DBusFreeFunction free_data_function;
1340   void *data;
1341 } CancelHook;
1342
1343 struct BusTransaction
1344 {
1345   DBusList *connections;
1346   BusContext *context;
1347   DBusList *cancel_hooks;
1348 };
1349
1350 static void
1351 message_to_send_free (DBusConnection *connection,
1352                       MessageToSend  *to_send)
1353 {
1354   if (to_send->message)
1355     dbus_message_unref (to_send->message);
1356
1357   if (to_send->preallocated)
1358     dbus_connection_free_preallocated_send (connection, to_send->preallocated);
1359
1360   dbus_free (to_send);
1361 }
1362
1363 static void
1364 cancel_hook_cancel (void *element,
1365                     void *data)
1366 {
1367   CancelHook *ch = element;
1368
1369   _dbus_verbose ("Running transaction cancel hook\n");
1370   
1371   if (ch->cancel_function)
1372     (* ch->cancel_function) (ch->data);  
1373 }
1374
1375 static void
1376 cancel_hook_free (void *element,
1377                   void *data)
1378 {
1379   CancelHook *ch = element;
1380
1381   if (ch->free_data_function)
1382     (* ch->free_data_function) (ch->data);
1383
1384   dbus_free (ch);
1385 }
1386
1387 static void
1388 free_cancel_hooks (BusTransaction *transaction)
1389 {
1390   _dbus_list_foreach (&transaction->cancel_hooks,
1391                       cancel_hook_free, NULL);
1392   
1393   _dbus_list_clear (&transaction->cancel_hooks);
1394 }
1395
1396 BusTransaction*
1397 bus_transaction_new (BusContext *context)
1398 {
1399   BusTransaction *transaction;
1400
1401   transaction = dbus_new0 (BusTransaction, 1);
1402   if (transaction == NULL)
1403     return NULL;
1404
1405   transaction->context = context;
1406   
1407   return transaction;
1408 }
1409
1410 BusContext*
1411 bus_transaction_get_context (BusTransaction  *transaction)
1412 {
1413   return transaction->context;
1414 }
1415
1416 BusConnections*
1417 bus_transaction_get_connections (BusTransaction  *transaction)
1418 {
1419   return bus_context_get_connections (transaction->context);
1420 }
1421
1422 dbus_bool_t
1423 bus_transaction_send_from_driver (BusTransaction *transaction,
1424                                   DBusConnection *connection,
1425                                   DBusMessage    *message)
1426 {
1427   /* We have to set the sender to the driver, and have
1428    * to check security policy since it was not done in
1429    * dispatch.c
1430    */
1431   _dbus_verbose ("Sending %s %s %s from driver\n",
1432                  dbus_message_get_interface (message) ?
1433                  dbus_message_get_interface (message) : "(no interface)",
1434                  dbus_message_get_member (message) ?
1435                  dbus_message_get_member (message) : "(no member)",
1436                  dbus_message_get_error_name (message) ?
1437                  dbus_message_get_error_name (message) : "(no error name)");
1438                  
1439   if (!dbus_message_set_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
1440     return FALSE;
1441
1442   /* If security policy doesn't allow the message, we silently
1443    * eat it; the driver doesn't care about getting a reply.
1444    */
1445   if (!bus_context_check_security_policy (bus_transaction_get_context (transaction),
1446                                           NULL, connection, connection, message, NULL))
1447     return TRUE;
1448
1449   return bus_transaction_send (transaction, connection, message);
1450 }
1451
1452 dbus_bool_t
1453 bus_transaction_send (BusTransaction *transaction,
1454                       DBusConnection *connection,
1455                       DBusMessage    *message)
1456 {
1457   MessageToSend *to_send;
1458   BusConnectionData *d;
1459   DBusList *link;
1460
1461   _dbus_verbose ("  trying to add %s interface=%s member=%s error=%s to transaction%s\n",
1462                  dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR ? "error" :
1463                  dbus_message_get_reply_serial (message) != 0 ? "reply" :
1464                  "message",
1465                  dbus_message_get_interface (message) ?
1466                  dbus_message_get_interface (message) : "(unset)",
1467                  dbus_message_get_member (message) ?
1468                  dbus_message_get_member (message) : "(unset)",
1469                  dbus_message_get_error_name (message) ?
1470                  dbus_message_get_error_name (message) : "(unset)",
1471                  dbus_connection_get_is_connected (connection) ?
1472                  "" : " (disconnected)");
1473
1474   _dbus_assert (dbus_message_get_sender (message) != NULL);
1475   
1476   if (!dbus_connection_get_is_connected (connection))
1477     return TRUE; /* silently ignore disconnected connections */
1478   
1479   d = BUS_CONNECTION_DATA (connection);
1480   _dbus_assert (d != NULL);
1481   
1482   to_send = dbus_new (MessageToSend, 1);
1483   if (to_send == NULL)
1484     {
1485       return FALSE;
1486     }
1487
1488   to_send->preallocated = dbus_connection_preallocate_send (connection);
1489   if (to_send->preallocated == NULL)
1490     {
1491       dbus_free (to_send);
1492       return FALSE;
1493     }  
1494   
1495   dbus_message_ref (message);
1496   to_send->message = message;
1497   to_send->transaction = transaction;
1498
1499   _dbus_verbose ("about to prepend message\n");
1500   
1501   if (!_dbus_list_prepend (&d->transaction_messages, to_send))
1502     {
1503       message_to_send_free (connection, to_send);
1504       return FALSE;
1505     }
1506
1507   _dbus_verbose ("prepended message\n");
1508   
1509   /* See if we already had this connection in the list
1510    * for this transaction. If we have a pending message,
1511    * then we should already be in transaction->connections
1512    */
1513   link = _dbus_list_get_first_link (&d->transaction_messages);
1514   _dbus_assert (link->data == to_send);
1515   link = _dbus_list_get_next_link (&d->transaction_messages, link);
1516   while (link != NULL)
1517     {
1518       MessageToSend *m = link->data;
1519       DBusList *next = _dbus_list_get_next_link (&d->transaction_messages, link);
1520       
1521       if (m->transaction == transaction)
1522         break;
1523         
1524       link = next;
1525     }
1526
1527   if (link == NULL)
1528     {
1529       if (!_dbus_list_prepend (&transaction->connections, connection))
1530         {
1531           _dbus_list_remove (&d->transaction_messages, to_send);
1532           message_to_send_free (connection, to_send);
1533           return FALSE;
1534         }
1535     }
1536
1537   return TRUE;
1538 }
1539
1540 static void
1541 connection_cancel_transaction (DBusConnection *connection,
1542                                BusTransaction *transaction)
1543 {
1544   DBusList *link;
1545   BusConnectionData *d;
1546   
1547   d = BUS_CONNECTION_DATA (connection);
1548   _dbus_assert (d != NULL);
1549   
1550   link = _dbus_list_get_first_link (&d->transaction_messages);
1551   while (link != NULL)
1552     {
1553       MessageToSend *m = link->data;
1554       DBusList *next = _dbus_list_get_next_link (&d->transaction_messages, link);
1555       
1556       if (m->transaction == transaction)
1557         {
1558           _dbus_list_remove_link (&d->transaction_messages,
1559                                   link);
1560           
1561           message_to_send_free (connection, m);
1562         }
1563         
1564       link = next;
1565     }
1566 }
1567
1568 void
1569 bus_transaction_cancel_and_free (BusTransaction *transaction)
1570 {
1571   DBusConnection *connection;
1572
1573   _dbus_verbose ("TRANSACTION: cancelled\n");
1574   
1575   while ((connection = _dbus_list_pop_first (&transaction->connections)))
1576     connection_cancel_transaction (connection, transaction);
1577
1578   _dbus_assert (transaction->connections == NULL);
1579
1580   _dbus_list_foreach (&transaction->cancel_hooks,
1581                       cancel_hook_cancel, NULL);
1582
1583   free_cancel_hooks (transaction);
1584   
1585   dbus_free (transaction);
1586 }
1587
1588 static void
1589 connection_execute_transaction (DBusConnection *connection,
1590                                 BusTransaction *transaction)
1591 {
1592   DBusList *link;
1593   BusConnectionData *d;
1594   
1595   d = BUS_CONNECTION_DATA (connection);
1596   _dbus_assert (d != NULL);
1597
1598   /* Send the queue in order (FIFO) */
1599   link = _dbus_list_get_last_link (&d->transaction_messages);
1600   while (link != NULL)
1601     {
1602       MessageToSend *m = link->data;
1603       DBusList *prev = _dbus_list_get_prev_link (&d->transaction_messages, link);
1604       
1605       if (m->transaction == transaction)
1606         {
1607           _dbus_list_remove_link (&d->transaction_messages,
1608                                   link);
1609
1610           _dbus_assert (dbus_message_get_sender (m->message) != NULL);
1611           
1612           dbus_connection_send_preallocated (connection,
1613                                              m->preallocated,
1614                                              m->message,
1615                                              NULL);
1616
1617           m->preallocated = NULL; /* so we don't double-free it */
1618           
1619           message_to_send_free (connection, m);
1620         }
1621         
1622       link = prev;
1623     }
1624 }
1625
1626 void
1627 bus_transaction_execute_and_free (BusTransaction *transaction)
1628 {
1629   /* For each connection in transaction->connections
1630    * send the messages
1631    */
1632   DBusConnection *connection;
1633
1634   _dbus_verbose ("TRANSACTION: executing\n");
1635   
1636   while ((connection = _dbus_list_pop_first (&transaction->connections)))
1637     connection_execute_transaction (connection, transaction);
1638
1639   _dbus_assert (transaction->connections == NULL);
1640
1641   free_cancel_hooks (transaction);
1642   
1643   dbus_free (transaction);
1644 }
1645
1646 static void
1647 bus_connection_remove_transactions (DBusConnection *connection)
1648 {
1649   MessageToSend *to_send;
1650   BusConnectionData *d;
1651   
1652   d = BUS_CONNECTION_DATA (connection);
1653   _dbus_assert (d != NULL);
1654   
1655   while ((to_send = _dbus_list_get_first (&d->transaction_messages)))
1656     {
1657       /* only has an effect for the first MessageToSend listing this transaction */
1658       _dbus_list_remove (&to_send->transaction->connections,
1659                          connection);
1660
1661       _dbus_list_remove (&d->transaction_messages, to_send);
1662       message_to_send_free (connection, to_send);
1663     }
1664 }
1665
1666 /**
1667  * Converts the DBusError to a message reply
1668  */
1669 dbus_bool_t
1670 bus_transaction_send_error_reply (BusTransaction  *transaction,
1671                                   DBusConnection  *connection,
1672                                   const DBusError *error,
1673                                   DBusMessage     *in_reply_to)
1674 {
1675   DBusMessage *reply;
1676   
1677   _dbus_assert (error != NULL);
1678   _DBUS_ASSERT_ERROR_IS_SET (error);
1679   
1680   _dbus_verbose ("Sending error reply %s \"%s\"\n",
1681                  error->name, error->message);
1682
1683   reply = dbus_message_new_error (in_reply_to,
1684                                   error->name,
1685                                   error->message);
1686   if (reply == NULL)
1687     return FALSE;
1688
1689   if (!bus_transaction_send_from_driver (transaction, connection, reply))
1690     {
1691       dbus_message_unref (reply);
1692       return FALSE;
1693     }
1694
1695   dbus_message_unref (reply);
1696   
1697   return TRUE;
1698 }
1699
1700 dbus_bool_t
1701 bus_transaction_add_cancel_hook (BusTransaction               *transaction,
1702                                  BusTransactionCancelFunction  cancel_function,
1703                                  void                         *data,
1704                                  DBusFreeFunction              free_data_function)
1705 {
1706   CancelHook *ch;
1707
1708   ch = dbus_new (CancelHook, 1);
1709   if (ch == NULL)
1710     return FALSE;
1711   
1712   ch->cancel_function = cancel_function;
1713   ch->data = data;
1714   ch->free_data_function = free_data_function;
1715
1716   /* It's important that the hooks get run in reverse order that they
1717    * were added
1718    */
1719   if (!_dbus_list_prepend (&transaction->cancel_hooks, ch))
1720     {
1721       dbus_free (ch);
1722       return FALSE;
1723     }
1724
1725   return TRUE;
1726 }