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