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