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