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