2003-04-06 Havoc Pennington <hp@pobox.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 <dbus/dbus-list.h>
29
30 static void bus_connection_remove_transactions (DBusConnection *connection);
31
32 struct BusConnections
33 {
34   int refcount;
35   DBusList *list; /**< List of all the connections */
36   BusContext *context;
37 };
38
39 static int connection_data_slot = -1;
40 static int connection_data_slot_refcount = 0;
41
42 typedef struct
43 {
44   BusConnections *connections;
45   DBusConnection *connection;
46   DBusList *services_owned;
47   char *name;
48   DBusList *transaction_messages; /**< Stuff we need to send as part of a transaction */
49   DBusMessage *oom_message;
50   DBusPreallocatedSend *oom_preallocated;
51   unsigned long *group_ids;
52   int n_group_ids;
53   BusPolicy *policy;
54 } BusConnectionData;
55
56 #define BUS_CONNECTION_DATA(connection) (dbus_connection_get_data ((connection), connection_data_slot))
57
58 static dbus_bool_t
59 connection_data_slot_ref (void)
60 {
61   if (connection_data_slot < 0)
62     {
63       connection_data_slot = dbus_connection_allocate_data_slot ();
64       
65       if (connection_data_slot < 0)
66         return FALSE;
67
68       _dbus_assert (connection_data_slot_refcount == 0);
69     }  
70
71   connection_data_slot_refcount += 1;
72
73   return TRUE;
74
75 }
76
77 static void
78 connection_data_slot_unref (void)
79 {
80   _dbus_assert (connection_data_slot_refcount > 0);
81
82   connection_data_slot_refcount -= 1;
83   
84   if (connection_data_slot_refcount == 0)
85     {
86       dbus_connection_free_data_slot (connection_data_slot);
87       connection_data_slot = -1;
88     }
89 }
90
91 static DBusLoop*
92 connection_get_loop (DBusConnection *connection)
93 {
94   BusConnectionData *d;
95
96   d = BUS_CONNECTION_DATA (connection);
97
98   return bus_context_get_loop (d->connections->context);
99 }
100
101 void
102 bus_connection_disconnected (DBusConnection *connection)
103 {
104   BusConnectionData *d;
105   BusService *service;
106
107   d = BUS_CONNECTION_DATA (connection);
108   _dbus_assert (d != NULL);
109
110   _dbus_verbose ("%s disconnected, dropping all service ownership and releasing\n",
111                  d->name ? d->name : "(inactive)");
112   
113   /* Drop any service ownership. FIXME Unfortunately, this requires
114    * memory allocation and there doesn't seem to be a good way to
115    * handle it other than sleeping; we can't "fail" the operation of
116    * disconnecting a client, and preallocating a broadcast "service is
117    * now gone" message for every client-service pair seems kind of
118    * involved. Probably we need to do that though, and also
119    * extend BusTransaction to be able to revert generic
120    * stuff, not just sending a message (so we can e.g. revert
121    * removal of service owners).
122    */
123   while ((service = _dbus_list_get_last (&d->services_owned)))
124     {
125       BusTransaction *transaction;
126       DBusError error;
127
128     retry:
129       
130       dbus_error_init (&error);
131         
132       transaction = NULL;
133       while (transaction == NULL)
134         {
135           transaction = bus_transaction_new (d->connections->context);
136           _dbus_wait_for_memory ();
137         }
138         
139       if (!bus_service_remove_owner (service, connection,
140                                      transaction, &error))
141         {
142           if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
143             {
144               dbus_error_free (&error);
145               bus_transaction_cancel_and_free (transaction);
146               _dbus_wait_for_memory ();
147               goto retry;
148             }
149           else
150             _dbus_assert_not_reached ("Removing service owner failed for non-memory-related reason");
151         }
152         
153       bus_transaction_execute_and_free (transaction);
154     }
155
156   bus_dispatch_remove_connection (connection);
157   
158   /* no more watching */
159   if (!dbus_connection_set_watch_functions (connection,
160                                             NULL, NULL, NULL,
161                                             connection,
162                                             NULL))
163     _dbus_assert_not_reached ("setting watch functions to NULL failed");
164
165   if (!dbus_connection_set_timeout_functions (connection,
166                                               NULL, NULL, NULL,
167                                               connection,
168                                               NULL))
169     _dbus_assert_not_reached ("setting timeout functions to NULL failed");
170   
171   dbus_connection_set_unix_user_function (connection,
172                                           NULL, NULL, NULL);
173   
174   bus_connection_remove_transactions (connection);
175
176   _dbus_list_remove (&d->connections->list, connection);
177
178   /* frees "d" as side effect */
179   dbus_connection_set_data (connection,
180                             connection_data_slot,
181                             NULL, NULL);
182
183   dbus_connection_unref (connection);
184 }
185
186 static dbus_bool_t
187 connection_watch_callback (DBusWatch     *watch,
188                            unsigned int   condition,
189                            void          *data)
190 {
191   DBusConnection *connection = data;
192   dbus_bool_t retval;
193
194   dbus_connection_ref (connection);
195   
196   retval = dbus_connection_handle_watch (connection, watch, condition);
197
198   bus_connection_dispatch_all_messages (connection);
199   
200   dbus_connection_unref (connection);
201
202   return retval;
203 }
204
205 static dbus_bool_t
206 add_connection_watch (DBusWatch      *watch,
207                       void           *data)
208 {
209   DBusConnection *connection = data;
210
211   return _dbus_loop_add_watch (connection_get_loop (connection),
212                                watch, connection_watch_callback, connection,
213                                NULL);
214 }
215
216 static void
217 remove_connection_watch (DBusWatch      *watch,
218                          void           *data)
219 {
220   DBusConnection *connection = data;
221   
222   _dbus_loop_remove_watch (connection_get_loop (connection),
223                            watch, connection_watch_callback, connection);
224 }
225
226 static void
227 connection_timeout_callback (DBusTimeout   *timeout,
228                              void          *data)
229 {
230   DBusConnection *connection = data;
231
232   dbus_connection_ref (connection);
233
234   /* can return FALSE on OOM but we just let it fire again later */
235   dbus_timeout_handle (timeout);
236
237   bus_connection_dispatch_all_messages (connection);
238   
239   dbus_connection_unref (connection);
240 }
241
242 static dbus_bool_t
243 add_connection_timeout (DBusTimeout    *timeout,
244                         void           *data)
245 {
246   DBusConnection *connection = data;
247   
248   return _dbus_loop_add_timeout (connection_get_loop (connection),
249                                  timeout, connection_timeout_callback, connection, NULL);
250 }
251
252 static void
253 remove_connection_timeout (DBusTimeout    *timeout,
254                            void           *data)
255 {
256   DBusConnection *connection = data;
257   
258   _dbus_loop_remove_timeout (connection_get_loop (connection),
259                              timeout, connection_timeout_callback, connection);
260 }
261
262 static dbus_bool_t
263 allow_user_function (DBusConnection *connection,
264                      unsigned long   uid,
265                      void           *data)
266 {
267   BusConnectionData *d;
268     
269   d = BUS_CONNECTION_DATA (connection);
270
271   _dbus_assert (d != NULL);
272
273   return TRUE; /* FIXME - this is just until we can parse a config file */
274   
275   return bus_context_allow_user (d->connections->context, uid);
276 }
277
278 static void
279 free_connection_data (void *data)
280 {
281   BusConnectionData *d = data;
282
283   /* services_owned should be NULL since we should be disconnected */
284   _dbus_assert (d->services_owned == NULL);
285   /* similarly */
286   _dbus_assert (d->transaction_messages == NULL);
287
288   if (d->oom_preallocated)
289     dbus_connection_free_preallocated_send (d->connection, d->oom_preallocated);
290
291   if (d->oom_message)
292     dbus_message_unref (d->oom_message);
293
294   if (d->policy)
295     bus_policy_unref (d->policy);
296   
297   dbus_free (d->group_ids);
298   
299   dbus_free (d->name);
300   
301   dbus_free (d);
302 }
303
304 BusConnections*
305 bus_connections_new (BusContext *context)
306 {
307   BusConnections *connections;
308
309   if (!connection_data_slot_ref ())
310     return NULL;
311
312   connections = dbus_new0 (BusConnections, 1);
313   if (connections == NULL)
314     {
315       connection_data_slot_unref ();
316       return NULL;
317     }
318   
319   connections->refcount = 1;
320   connections->context = context;
321   
322   return connections;
323 }
324
325 void
326 bus_connections_ref (BusConnections *connections)
327 {
328   _dbus_assert (connections->refcount > 0);
329   connections->refcount += 1;
330 }
331
332 void
333 bus_connections_unref (BusConnections *connections)
334 {
335   _dbus_assert (connections->refcount > 0);
336   connections->refcount -= 1;
337   if (connections->refcount == 0)
338     {
339       while (connections->list != NULL)
340         {
341           DBusConnection *connection;
342
343           connection = connections->list->data;
344
345           dbus_connection_ref (connection);
346           dbus_connection_disconnect (connection);
347           bus_connection_disconnected (connection);
348           dbus_connection_unref (connection);
349         }
350       
351       _dbus_list_clear (&connections->list);
352       
353       dbus_free (connections);
354
355       connection_data_slot_unref ();
356     }
357 }
358
359 dbus_bool_t
360 bus_connections_setup_connection (BusConnections *connections,
361                                   DBusConnection *connection)
362 {
363   BusConnectionData *d;
364   dbus_bool_t retval;
365   
366   d = dbus_new0 (BusConnectionData, 1);
367   
368   if (d == NULL)
369     return FALSE;
370
371   d->connections = connections;
372   d->connection = connection;
373
374   _dbus_assert (connection_data_slot >= 0);
375   
376   if (!dbus_connection_set_data (connection,
377                                  connection_data_slot,
378                                  d, free_connection_data))
379     {
380       dbus_free (d);
381       return FALSE;
382     }
383
384   retval = FALSE;
385
386   d->n_group_ids = 0;
387   d->group_ids = NULL;
388   
389   if (!dbus_connection_set_watch_functions (connection,
390                                             add_connection_watch,
391                                             remove_connection_watch,
392                                             NULL,
393                                             connection,
394                                             NULL))
395     goto out;
396   
397   if (!dbus_connection_set_timeout_functions (connection,
398                                               add_connection_timeout,
399                                               remove_connection_timeout,
400                                               NULL,
401                                               connection, NULL))
402     goto out;
403
404
405   dbus_connection_set_unix_user_function (connection,
406                                           allow_user_function,
407                                           NULL, NULL);
408   
409   /* Setup the connection with the dispatcher */
410   if (!bus_dispatch_add_connection (connection))
411     goto out;
412   
413   if (!_dbus_list_append (&connections->list, connection))
414     {
415       bus_dispatch_remove_connection (connection);
416       goto out;
417     }
418   
419   dbus_connection_ref (connection);
420   retval = TRUE;
421
422  out:
423   if (!retval)
424     {        
425       if (!dbus_connection_set_watch_functions (connection,
426                                                 NULL, NULL, NULL,
427                                                 connection,
428                                                 NULL))
429         _dbus_assert_not_reached ("setting watch functions to NULL failed");
430       
431       if (!dbus_connection_set_timeout_functions (connection,
432                                                   NULL, NULL, NULL,
433                                                   connection,
434                                                   NULL))
435         _dbus_assert_not_reached ("setting timeout functions to NULL failed");
436
437       dbus_connection_set_unix_user_function (connection,
438                                               NULL, NULL, NULL);
439
440       if (!dbus_connection_set_data (connection,
441                                      connection_data_slot,
442                                      NULL, NULL))
443         _dbus_assert_not_reached ("failed to set connection data to null");
444     }
445   
446   return retval;
447 }
448
449 dbus_bool_t
450 bus_connection_get_groups  (DBusConnection       *connection,
451                             const unsigned long **groups,
452                             int                  *n_groups)
453 {
454   BusConnectionData *d;
455     
456   d = BUS_CONNECTION_DATA (connection);
457
458   _dbus_assert (d != NULL);
459
460   *groups = NULL;
461   *n_groups = 0;
462
463   /* we do a lazy lookup on groups a user is in for two reasons:
464    * 1) we can't do it on connection setup since the user
465    * hasn't authenticated and 2) it might be expensive
466    * and we don't need to do it if there are no group-based
467    * rules in the config file
468    */
469   
470   if (d->n_group_ids == 0)
471     {
472       unsigned long uid;
473       
474       if (dbus_connection_get_unix_user (connection, &uid))
475         {
476           if (!_dbus_get_groups (uid, &d->group_ids, &d->n_group_ids))
477             {
478               _dbus_verbose ("Did not get any groups for UID %lu\n",
479                              uid);
480               return FALSE;
481             }
482         }
483     }
484
485   *groups = d->group_ids;
486   *n_groups = d->n_group_ids;
487
488   return TRUE;
489 }
490
491 dbus_bool_t
492 bus_connection_is_in_group (DBusConnection *connection,
493                             unsigned long   gid)
494 {
495   int i;
496   const unsigned long *group_ids;
497   int n_group_ids;
498
499   if (!bus_connection_get_groups (connection, &group_ids, &n_group_ids))
500     return FALSE;
501
502   i = 0;
503   while (i < n_group_ids)
504     {
505       if (group_ids[i] == gid)
506         return TRUE;
507       ++i;
508     }
509
510   return FALSE;
511 }
512
513 BusPolicy*
514 bus_connection_get_policy (DBusConnection *connection)
515 {
516   BusConnectionData *d;
517     
518   d = BUS_CONNECTION_DATA (connection);
519
520   _dbus_assert (d != NULL);
521
522   if (!dbus_connection_get_is_authenticated (connection))
523     {
524       _dbus_verbose ("Tried to get policy for unauthenticated connection!\n");
525       return NULL;
526     }
527   
528   /* We do lazy creation of the policy because
529    * it can only be done post-authentication.
530    */
531   if (d->policy == NULL)
532     {
533       d->policy =
534         bus_context_create_connection_policy (d->connections->context,
535                                               connection);
536
537       /* we may have a NULL policy on OOM or error getting list of
538        * groups for a user. In the latter case we don't handle it so
539        * well currently, just keep pretending we're out of memory,
540        * which is kind of bizarre.
541        */
542     }
543
544   return d->policy;
545 }
546
547 /**
548  * Calls function on each connection; if the function returns
549  * #FALSE, stops iterating.
550  *
551  * @param connections the connections object
552  * @param function the function
553  * @param data data to pass to it as a second arg
554  */
555 void
556 bus_connections_foreach (BusConnections               *connections,
557                          BusConnectionForeachFunction  function,
558                         void                          *data)
559 {
560   DBusList *link;
561   
562   link = _dbus_list_get_first_link (&connections->list);
563   while (link != NULL)
564     {
565       DBusConnection *connection = link->data;
566       DBusList *next = _dbus_list_get_next_link (&connections->list, link);
567
568       if (!(* function) (connection, data))
569         break;
570       
571       link = next;
572     }
573 }
574
575 BusContext*
576 bus_connections_get_context (BusConnections *connections)
577 {
578   return connections->context;
579 }
580
581 BusContext*
582 bus_connection_get_context (DBusConnection *connection)
583 {
584   BusConnectionData *d;
585
586   d = BUS_CONNECTION_DATA (connection);
587
588   _dbus_assert (d != NULL);
589
590   return d->connections->context;
591 }
592
593 BusConnections*
594 bus_connection_get_connections (DBusConnection *connection)
595 {
596   BusConnectionData *d;
597     
598   d = BUS_CONNECTION_DATA (connection);
599
600   _dbus_assert (d != NULL);
601
602   return d->connections;
603 }
604
605 BusRegistry*
606 bus_connection_get_registry (DBusConnection *connection)
607 {
608   BusConnectionData *d;
609
610   d = BUS_CONNECTION_DATA (connection);
611
612   _dbus_assert (d != NULL);
613
614   return bus_context_get_registry (d->connections->context);
615 }
616
617 BusActivation*
618 bus_connection_get_activation (DBusConnection *connection)
619 {
620   BusConnectionData *d;
621
622   d = BUS_CONNECTION_DATA (connection);
623
624   _dbus_assert (d != NULL);
625
626   return bus_context_get_activation (d->connections->context);
627 }
628
629 /**
630  * Checks whether the connection is registered with the message bus.
631  *
632  * @param connection the connection
633  * @returns #TRUE if we're an active message bus participant
634  */
635 dbus_bool_t
636 bus_connection_is_active (DBusConnection *connection)
637 {
638   BusConnectionData *d;
639
640   d = BUS_CONNECTION_DATA (connection);
641   
642   return d != NULL && d->name != NULL;
643 }
644
645 dbus_bool_t
646 bus_connection_preallocate_oom_error (DBusConnection *connection)
647 {
648   DBusMessage *message;
649   DBusPreallocatedSend *preallocated;
650   BusConnectionData *d;
651
652   d = BUS_CONNECTION_DATA (connection);  
653
654   _dbus_assert (d != NULL);
655
656   if (d->oom_preallocated != NULL)
657     return TRUE;
658   
659   preallocated = dbus_connection_preallocate_send (connection);
660   if (preallocated == NULL)
661     return FALSE;
662
663   /* d->name may be NULL, but that should be OK */
664   message = dbus_message_new (d->name,
665                               DBUS_ERROR_NO_MEMORY);
666   if (message == NULL)
667     {
668       dbus_connection_free_preallocated_send (connection, preallocated);
669       return FALSE;
670     }
671
672   dbus_message_set_is_error (message, TRUE);
673
674   if (!dbus_message_set_sender (message,
675                                 DBUS_SERVICE_DBUS))
676     {
677       dbus_connection_free_preallocated_send (connection, preallocated);
678       dbus_message_unref (message);
679       return FALSE;
680     }
681   
682   /* set reply serial to placeholder value just so space is already allocated
683    * for it.
684    */
685   if (!dbus_message_set_reply_serial (message, 14))
686     {
687       dbus_connection_free_preallocated_send (connection, preallocated);
688       dbus_message_unref (message);
689       return FALSE;
690     }
691
692   d->oom_message = message;
693   d->oom_preallocated = preallocated;
694   
695   return TRUE;
696 }
697
698 void
699 bus_connection_send_oom_error (DBusConnection *connection,
700                                DBusMessage    *in_reply_to)
701 {
702   BusConnectionData *d;
703
704   d = BUS_CONNECTION_DATA (connection);  
705
706   _dbus_assert (d != NULL);  
707   _dbus_assert (d->oom_message != NULL);
708
709   /* should always succeed since we set it to a placeholder earlier */
710   if (!dbus_message_set_reply_serial (d->oom_message,
711                                       dbus_message_get_serial (in_reply_to)))
712     _dbus_assert_not_reached ("Failed to set reply serial for preallocated oom message");
713
714   _dbus_assert (dbus_message_get_sender (d->oom_message) != NULL);
715   
716   dbus_connection_send_preallocated (connection, d->oom_preallocated,
717                                      d->oom_message, NULL);
718
719   dbus_message_unref (d->oom_message);
720   d->oom_message = NULL;
721   d->oom_preallocated = NULL;
722 }
723
724 dbus_bool_t
725 bus_connection_add_owned_service (DBusConnection *connection,
726                                   BusService     *service)
727 {
728   BusConnectionData *d;
729
730   d = BUS_CONNECTION_DATA (connection);
731   _dbus_assert (d != NULL);
732
733   if (!_dbus_list_append (&d->services_owned,
734                           service))
735     return FALSE;
736
737   return TRUE;
738 }
739
740 void
741 bus_connection_remove_owned_service (DBusConnection *connection,
742                                      BusService     *service)
743 {
744   BusConnectionData *d;
745
746   d = BUS_CONNECTION_DATA (connection);
747   _dbus_assert (d != NULL);
748
749   _dbus_list_remove_last (&d->services_owned, service);
750 }
751
752 dbus_bool_t
753 bus_connection_set_name (DBusConnection   *connection,
754                          const DBusString *name)
755 {
756   BusConnectionData *d;
757   
758   d = BUS_CONNECTION_DATA (connection);
759   _dbus_assert (d != NULL);
760   _dbus_assert (d->name == NULL);
761
762   if (!_dbus_string_copy_data (name, &d->name))
763     return FALSE;
764
765   _dbus_assert (d->name != NULL);
766   
767   _dbus_verbose ("Name %s assigned to %p\n", d->name, connection);
768   
769   return TRUE;
770 }
771
772 const char *
773 bus_connection_get_name (DBusConnection *connection)
774 {
775   BusConnectionData *d;
776   
777   d = BUS_CONNECTION_DATA (connection);
778   _dbus_assert (d != NULL);
779   
780   return d->name;
781 }
782
783 typedef struct
784 {
785   BusTransaction *transaction;
786   DBusMessage    *message;
787   DBusPreallocatedSend *preallocated;
788 } MessageToSend;
789
790 struct BusTransaction
791 {
792   DBusList *connections;
793   BusContext *context;
794 };
795
796 static void
797 message_to_send_free (DBusConnection *connection,
798                       MessageToSend  *to_send)
799 {
800   if (to_send->message)
801     dbus_message_unref (to_send->message);
802
803   if (to_send->preallocated)
804     dbus_connection_free_preallocated_send (connection, to_send->preallocated);
805
806   dbus_free (to_send);
807 }
808
809 BusTransaction*
810 bus_transaction_new (BusContext *context)
811 {
812   BusTransaction *transaction;
813
814   transaction = dbus_new0 (BusTransaction, 1);
815   if (transaction == NULL)
816     return NULL;
817
818   transaction->context = context;
819   
820   return transaction;
821 }
822
823 BusContext*
824 bus_transaction_get_context (BusTransaction  *transaction)
825 {
826   return transaction->context;
827 }
828
829 BusConnections*
830 bus_transaction_get_connections (BusTransaction  *transaction)
831 {
832   return bus_context_get_connections (transaction->context);
833 }
834
835 dbus_bool_t
836 bus_transaction_send_message (BusTransaction *transaction,
837                               DBusConnection *connection,
838                               DBusMessage    *message)
839 {
840   MessageToSend *to_send;
841   BusConnectionData *d;
842   DBusList *link;
843
844   _dbus_verbose ("  trying to add message %s to transaction%s\n",
845                  dbus_message_get_name (message),
846                  dbus_connection_get_is_connected (connection) ?
847                  "" : " (disconnected)");
848
849   _dbus_assert (dbus_message_get_sender (message) != NULL);
850   
851   if (!dbus_connection_get_is_connected (connection))
852     return TRUE; /* silently ignore disconnected connections */
853   
854   d = BUS_CONNECTION_DATA (connection);
855   _dbus_assert (d != NULL);
856   
857   to_send = dbus_new (MessageToSend, 1);
858   if (to_send == NULL)
859     {
860       return FALSE;
861     }
862
863   to_send->preallocated = dbus_connection_preallocate_send (connection);
864   if (to_send->preallocated == NULL)
865     {
866       dbus_free (to_send);
867       return FALSE;
868     }  
869   
870   dbus_message_ref (message);
871   to_send->message = message;
872   to_send->transaction = transaction;
873
874   _dbus_verbose ("about to prepend message\n");
875   
876   if (!_dbus_list_prepend (&d->transaction_messages, to_send))
877     {
878       message_to_send_free (connection, to_send);
879       return FALSE;
880     }
881
882   _dbus_verbose ("prepended message\n");
883   
884   /* See if we already had this connection in the list
885    * for this transaction. If we have a pending message,
886    * then we should already be in transaction->connections
887    */
888   link = _dbus_list_get_first_link (&d->transaction_messages);
889   _dbus_assert (link->data == to_send);
890   link = _dbus_list_get_next_link (&d->transaction_messages, link);
891   while (link != NULL)
892     {
893       MessageToSend *m = link->data;
894       DBusList *next = _dbus_list_get_next_link (&d->transaction_messages, link);
895       
896       if (m->transaction == transaction)
897         break;
898         
899       link = next;
900     }
901
902   if (link == NULL)
903     {
904       if (!_dbus_list_prepend (&transaction->connections, connection))
905         {
906           _dbus_list_remove (&d->transaction_messages, to_send);
907           message_to_send_free (connection, to_send);
908           return FALSE;
909         }
910     }
911
912   return TRUE;
913 }
914
915 static void
916 connection_cancel_transaction (DBusConnection *connection,
917                                BusTransaction *transaction)
918 {
919   DBusList *link;
920   BusConnectionData *d;
921   
922   d = BUS_CONNECTION_DATA (connection);
923   _dbus_assert (d != NULL);
924   
925   link = _dbus_list_get_first_link (&d->transaction_messages);
926   while (link != NULL)
927     {
928       MessageToSend *m = link->data;
929       DBusList *next = _dbus_list_get_next_link (&d->transaction_messages, link);
930       
931       if (m->transaction == transaction)
932         {
933           _dbus_list_remove_link (&d->transaction_messages,
934                                   link);
935           
936           message_to_send_free (connection, m);
937         }
938         
939       link = next;
940     }
941 }
942
943 void
944 bus_transaction_cancel_and_free (BusTransaction *transaction)
945 {
946   DBusConnection *connection;
947
948   _dbus_verbose ("TRANSACTION: cancelled\n");
949   
950   while ((connection = _dbus_list_pop_first (&transaction->connections)))
951     connection_cancel_transaction (connection, transaction);
952
953   _dbus_assert (transaction->connections == NULL);
954
955   dbus_free (transaction);
956 }
957
958 static void
959 connection_execute_transaction (DBusConnection *connection,
960                                 BusTransaction *transaction)
961 {
962   DBusList *link;
963   BusConnectionData *d;
964   
965   d = BUS_CONNECTION_DATA (connection);
966   _dbus_assert (d != NULL);
967
968   /* Send the queue in order (FIFO) */
969   link = _dbus_list_get_last_link (&d->transaction_messages);
970   while (link != NULL)
971     {
972       MessageToSend *m = link->data;
973       DBusList *prev = _dbus_list_get_prev_link (&d->transaction_messages, link);
974       
975       if (m->transaction == transaction)
976         {
977           _dbus_list_remove_link (&d->transaction_messages,
978                                   link);
979
980           _dbus_assert (dbus_message_get_sender (m->message) != NULL);
981           
982           dbus_connection_send_preallocated (connection,
983                                              m->preallocated,
984                                              m->message,
985                                              NULL);
986
987           m->preallocated = NULL; /* so we don't double-free it */
988           
989           message_to_send_free (connection, m);
990         }
991         
992       link = prev;
993     }
994 }
995
996 void
997 bus_transaction_execute_and_free (BusTransaction *transaction)
998 {
999   /* For each connection in transaction->connections
1000    * send the messages
1001    */
1002   DBusConnection *connection;
1003
1004   _dbus_verbose ("TRANSACTION: executing\n");
1005   
1006   while ((connection = _dbus_list_pop_first (&transaction->connections)))
1007     connection_execute_transaction (connection, transaction);
1008
1009   _dbus_assert (transaction->connections == NULL);
1010
1011   dbus_free (transaction);
1012 }
1013
1014 static void
1015 bus_connection_remove_transactions (DBusConnection *connection)
1016 {
1017   MessageToSend *to_send;
1018   BusConnectionData *d;
1019   
1020   d = BUS_CONNECTION_DATA (connection);
1021   _dbus_assert (d != NULL);
1022   
1023   while ((to_send = _dbus_list_get_first (&d->transaction_messages)))
1024     {
1025       /* only has an effect for the first MessageToSend listing this transaction */
1026       _dbus_list_remove (&to_send->transaction->connections,
1027                          connection);
1028
1029       _dbus_list_remove (&d->transaction_messages, to_send);
1030       message_to_send_free (connection, to_send);
1031     }
1032 }
1033
1034 /**
1035  * Converts the DBusError to a message reply
1036  */
1037 dbus_bool_t
1038 bus_transaction_send_error_reply (BusTransaction  *transaction,
1039                                   DBusConnection  *connection,
1040                                   const DBusError *error,
1041                                   DBusMessage     *in_reply_to)
1042 {
1043   DBusMessage *reply;
1044   
1045   _dbus_assert (error != NULL);
1046   _DBUS_ASSERT_ERROR_IS_SET (error);
1047   
1048   reply = dbus_message_new_error_reply (in_reply_to,
1049                                         error->name,
1050                                         error->message);
1051   if (reply == NULL)
1052     return FALSE;
1053
1054   if (!dbus_message_set_sender (reply, DBUS_SERVICE_DBUS) ||
1055       !bus_transaction_send_message (transaction, connection, reply))
1056     {
1057       dbus_message_unref (reply);
1058       return FALSE;
1059     }
1060
1061   dbus_message_unref (reply);
1062   
1063   return TRUE;
1064 }