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