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