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