Revert all changes since a36d4918a6f646e085
[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 connection_watch_callback (DBusWatch     *watch,
299                            unsigned int   condition,
300                            void          *data)
301 {
302  /* FIXME this can be done in dbus-mainloop.c
303   * if the code in activation.c for the babysitter
304   * watch handler is fixed.
305   */
306   
307 #if 0
308   _dbus_verbose ("Calling handle_watch\n");
309 #endif
310   return dbus_watch_handle (watch, condition);
311 }
312
313 static dbus_bool_t
314 add_connection_watch (DBusWatch      *watch,
315                       void           *data)
316 {
317   DBusConnection *connection = data;
318
319   return _dbus_loop_add_watch (connection_get_loop (connection),
320                                watch, connection_watch_callback, connection,
321                                NULL);
322 }
323
324 static void
325 remove_connection_watch (DBusWatch      *watch,
326                          void           *data)
327 {
328   DBusConnection *connection = data;
329   
330   _dbus_loop_remove_watch (connection_get_loop (connection),
331                            watch, connection_watch_callback, connection);
332 }
333
334 static void
335 connection_timeout_callback (DBusTimeout   *timeout,
336                              void          *data)
337 {
338   /* DBusConnection *connection = data; */
339
340   /* can return FALSE on OOM but we just let it fire again later */
341   dbus_timeout_handle (timeout);
342 }
343
344 static dbus_bool_t
345 add_connection_timeout (DBusTimeout    *timeout,
346                         void           *data)
347 {
348   DBusConnection *connection = data;
349   
350   return _dbus_loop_add_timeout (connection_get_loop (connection),
351                                  timeout, connection_timeout_callback, connection, NULL);
352 }
353
354 static void
355 remove_connection_timeout (DBusTimeout    *timeout,
356                            void           *data)
357 {
358   DBusConnection *connection = data;
359   
360   _dbus_loop_remove_timeout (connection_get_loop (connection),
361                              timeout, connection_timeout_callback, connection);
362 }
363
364 static void
365 dispatch_status_function (DBusConnection    *connection,
366                           DBusDispatchStatus new_status,
367                           void              *data)
368 {
369   DBusLoop *loop = data;
370   
371   if (new_status != DBUS_DISPATCH_COMPLETE)
372     {
373       while (!_dbus_loop_queue_dispatch (loop, connection))
374         _dbus_wait_for_memory ();
375     }
376 }
377
378 static dbus_bool_t
379 allow_unix_user_function (DBusConnection *connection,
380                           unsigned long   uid,
381                           void           *data)
382 {
383   BusConnectionData *d;
384     
385   d = BUS_CONNECTION_DATA (connection);
386
387   _dbus_assert (d != NULL);
388   
389   return bus_context_allow_unix_user (d->connections->context, uid);
390 }
391
392 static void
393 free_connection_data (void *data)
394 {
395   BusConnectionData *d = data;
396
397   /* services_owned should be NULL since we should be disconnected */
398   _dbus_assert (d->services_owned == NULL);
399   _dbus_assert (d->n_services_owned == 0);
400   /* similarly */
401   _dbus_assert (d->transaction_messages == NULL);
402
403   if (d->oom_preallocated)
404     dbus_connection_free_preallocated_send (d->connection, d->oom_preallocated);
405
406   if (d->oom_message)
407     dbus_message_unref (d->oom_message);
408
409   if (d->policy)
410     bus_client_policy_unref (d->policy);
411
412   if (d->selinux_id)
413     bus_selinux_id_unref (d->selinux_id);
414   
415   dbus_free (d->cached_loginfo_string);
416   
417   dbus_free (d->name);
418   
419   dbus_free (d);
420 }
421
422 static void
423 call_timeout_callback (DBusTimeout   *timeout,
424                        void          *data)
425 {
426   /* can return FALSE on OOM but we just let it fire again later */
427   dbus_timeout_handle (timeout);
428 }
429
430 BusConnections*
431 bus_connections_new (BusContext *context)
432 {
433   BusConnections *connections;
434
435   if (!dbus_connection_allocate_data_slot (&connection_data_slot))
436     goto failed_0;
437
438   connections = dbus_new0 (BusConnections, 1);
439   if (connections == NULL)
440     goto failed_1;
441
442   connections->completed_by_user = _dbus_hash_table_new (DBUS_HASH_UINTPTR,
443                                                          NULL, NULL);
444   if (connections->completed_by_user == NULL)
445     goto failed_2;
446
447   connections->expire_timeout = _dbus_timeout_new (100, /* irrelevant */
448                                                    expire_incomplete_timeout,
449                                                    connections, NULL);
450   if (connections->expire_timeout == NULL)
451     goto failed_3;
452
453   _dbus_timeout_set_enabled (connections->expire_timeout, FALSE);
454
455   connections->pending_replies = bus_expire_list_new (bus_context_get_loop (context),
456                                                       bus_context_get_reply_timeout (context),
457                                                       bus_pending_reply_expired,
458                                                       connections);
459   if (connections->pending_replies == NULL)
460     goto failed_4;
461   
462   if (!_dbus_loop_add_timeout (bus_context_get_loop (context),
463                                connections->expire_timeout,
464                                call_timeout_callback, NULL, NULL))
465     goto failed_5;
466   
467   connections->refcount = 1;
468   connections->context = context;
469   
470   return connections;
471
472  failed_5:
473   bus_expire_list_free (connections->pending_replies);
474  failed_4:
475   _dbus_timeout_unref (connections->expire_timeout);
476  failed_3:
477   _dbus_hash_table_unref (connections->completed_by_user);
478  failed_2:
479   dbus_free (connections);
480  failed_1:
481   dbus_connection_free_data_slot (&connection_data_slot);
482  failed_0:
483   return NULL;
484 }
485
486 BusConnections *
487 bus_connections_ref (BusConnections *connections)
488 {
489   _dbus_assert (connections->refcount > 0);
490   connections->refcount += 1;
491
492   return connections;
493 }
494
495 void
496 bus_connections_unref (BusConnections *connections)
497 {
498   _dbus_assert (connections->refcount > 0);
499   connections->refcount -= 1;
500   if (connections->refcount == 0)
501     {
502       /* drop all incomplete */
503       while (connections->incomplete != NULL)
504         {
505           DBusConnection *connection;
506
507           connection = connections->incomplete->data;
508
509           dbus_connection_ref (connection);
510           dbus_connection_close (connection);
511           bus_connection_disconnected (connection);
512           dbus_connection_unref (connection);
513         }
514
515       _dbus_assert (connections->n_incomplete == 0);
516       
517       /* drop all real connections */
518       while (connections->completed != NULL)
519         {
520           DBusConnection *connection;
521
522           connection = connections->completed->data;
523
524           dbus_connection_ref (connection);
525           dbus_connection_close (connection);
526           bus_connection_disconnected (connection);
527           dbus_connection_unref (connection);
528         }
529
530       _dbus_assert (connections->n_completed == 0);
531
532       bus_expire_list_free (connections->pending_replies);
533       
534       _dbus_loop_remove_timeout (bus_context_get_loop (connections->context),
535                                  connections->expire_timeout,
536                                  call_timeout_callback, NULL);
537       
538       _dbus_timeout_unref (connections->expire_timeout);
539       
540       _dbus_hash_table_unref (connections->completed_by_user);
541       
542       dbus_free (connections);
543
544       dbus_connection_free_data_slot (&connection_data_slot);
545     }
546 }
547
548 /* Used for logging */
549 static dbus_bool_t
550 cache_peer_loginfo_string (BusConnectionData *d, 
551                            DBusConnection    *connection)
552 {
553   DBusString loginfo_buf;
554   unsigned long uid;
555   unsigned long pid;
556   char *windows_sid;
557   dbus_bool_t prev_added;
558
559   if (!_dbus_string_init (&loginfo_buf))
560     return FALSE;
561   
562   prev_added = FALSE;
563   if (dbus_connection_get_unix_user (connection, &uid))
564     {
565       if (!_dbus_string_append_printf (&loginfo_buf, "uid=%ld", uid))
566         goto oom;
567       else
568         prev_added = TRUE;
569     }
570
571   if (dbus_connection_get_unix_process_id (connection, &pid))
572     {
573       if (prev_added)
574         {
575           if (!_dbus_string_append_byte (&loginfo_buf, ' '))
576             goto oom;
577         }
578       if (!_dbus_string_append_printf (&loginfo_buf, "pid=%ld comm=\"", pid))
579         goto oom;
580       /* Ignore errors here; we may not have permissions to read the
581        * proc file. */
582       _dbus_command_for_pid (pid, &loginfo_buf, MAX_LOG_COMMAND_LEN, NULL);
583       if (!_dbus_string_append_byte (&loginfo_buf, '"'))
584         goto oom;
585     }
586
587   if (dbus_connection_get_windows_user (connection, &windows_sid))
588     {
589       dbus_bool_t did_append;
590       did_append = _dbus_string_append_printf (&loginfo_buf,
591                                                "sid=\"%s\" ", windows_sid);
592       dbus_free (windows_sid);
593       if (!did_append)
594         goto oom;
595     }
596
597   if (!_dbus_string_steal_data (&loginfo_buf, &(d->cached_loginfo_string)))
598     goto oom;
599
600   _dbus_string_free (&loginfo_buf); 
601
602   return TRUE;
603 oom:
604    _dbus_string_free (&loginfo_buf);
605    return FALSE;
606 }
607
608 dbus_bool_t
609 bus_connections_setup_connection (BusConnections *connections,
610                                   DBusConnection *connection)
611 {
612
613   BusConnectionData *d;
614   dbus_bool_t retval;
615   DBusError error;
616
617   
618   d = dbus_new0 (BusConnectionData, 1);
619   
620   if (d == NULL)
621     return FALSE;
622
623   d->connections = connections;
624   d->connection = connection;
625   
626   _dbus_get_current_time (&d->connection_tv_sec,
627                           &d->connection_tv_usec);
628   
629   _dbus_assert (connection_data_slot >= 0);
630   
631   if (!dbus_connection_set_data (connection,
632                                  connection_data_slot,
633                                  d, free_connection_data))
634     {
635       dbus_free (d);
636       return FALSE;
637     }
638
639   dbus_connection_set_route_peer_messages (connection, TRUE);
640   
641   retval = FALSE;
642
643   dbus_error_init (&error);
644   d->selinux_id = bus_selinux_init_connection_id (connection,
645                                                   &error);
646   if (dbus_error_is_set (&error))
647     {
648       /* This is a bit bogus because we pretend all errors
649        * are OOM; this is done because we know that in bus.c
650        * an OOM error disconnects the connection, which is
651        * the same thing we want on any other error.
652        */
653       dbus_error_free (&error);
654       goto out;
655     }
656
657   if (!dbus_connection_set_watch_functions (connection,
658                                             add_connection_watch,
659                                             remove_connection_watch,
660                                             NULL,
661                                             connection,
662                                             NULL))
663     goto out;
664   
665   if (!dbus_connection_set_timeout_functions (connection,
666                                               add_connection_timeout,
667                                               remove_connection_timeout,
668                                               NULL,
669                                               connection, NULL))
670     goto out;
671
672   /* For now we don't need to set a Windows user function because
673    * there are no policies in the config file controlling what
674    * Windows users can connect. The default 'same user that owns the
675    * bus can connect' behavior of DBusConnection is fine on Windows.
676    */
677   dbus_connection_set_unix_user_function (connection,
678                                           allow_unix_user_function,
679                                           NULL, NULL);
680
681   dbus_connection_set_dispatch_status_function (connection,
682                                                 dispatch_status_function,
683                                                 bus_context_get_loop (connections->context),
684                                                 NULL);
685
686   d->link_in_connection_list = _dbus_list_alloc_link (connection);
687   if (d->link_in_connection_list == NULL)
688     goto out;
689   
690   /* Setup the connection with the dispatcher */
691   if (!bus_dispatch_add_connection (connection))
692     goto out;
693
694   if (dbus_connection_get_dispatch_status (connection) != DBUS_DISPATCH_COMPLETE)
695     {
696       if (!_dbus_loop_queue_dispatch (bus_context_get_loop (connections->context), connection))
697         {
698           bus_dispatch_remove_connection (connection);
699           goto out;
700         }
701     }
702
703   _dbus_list_append_link (&connections->incomplete, d->link_in_connection_list);
704   connections->n_incomplete += 1;
705   
706   dbus_connection_ref (connection);
707
708   /* Note that we might disconnect ourselves here, but it only takes
709    * effect on return to the main loop. We call this to free up
710    * expired connections if possible, and to queue the timeout for our
711    * own expiration.
712    */
713   bus_connections_expire_incomplete (connections);
714   
715   /* And we might also disconnect ourselves here, but again it
716    * only takes effect on return to main loop.
717    */
718   if (connections->n_incomplete >
719       bus_context_get_max_incomplete_connections (connections->context))
720     {
721       _dbus_verbose ("Number of incomplete connections exceeds max, dropping oldest one\n");
722       
723       _dbus_assert (connections->incomplete != NULL);
724       /* Disconnect the oldest unauthenticated connection.  FIXME
725        * would it be more secure to drop a *random* connection?  This
726        * algorithm seems to mean that if someone can create new
727        * connections quickly enough, they can keep anyone else from
728        * completing authentication. But random may or may not really
729        * help with that, a more elaborate solution might be required.
730        */
731       dbus_connection_close (connections->incomplete->data);
732     }
733   
734   retval = TRUE;
735
736  out:
737   if (!retval)
738     {
739       if (d->selinux_id)
740         bus_selinux_id_unref (d->selinux_id);
741       d->selinux_id = NULL;
742       
743       if (!dbus_connection_set_watch_functions (connection,
744                                                 NULL, NULL, NULL,
745                                                 connection,
746                                                 NULL))
747         _dbus_assert_not_reached ("setting watch functions to NULL failed");
748       
749       if (!dbus_connection_set_timeout_functions (connection,
750                                                   NULL, NULL, NULL,
751                                                   connection,
752                                                   NULL))
753         _dbus_assert_not_reached ("setting timeout functions to NULL failed");
754
755       dbus_connection_set_unix_user_function (connection,
756                                               NULL, NULL, NULL);
757
758       dbus_connection_set_windows_user_function (connection,
759                                                  NULL, NULL, NULL);
760       
761       dbus_connection_set_dispatch_status_function (connection,
762                                                     NULL, NULL, NULL);
763
764       if (d->link_in_connection_list != NULL)
765         {
766           _dbus_assert (d->link_in_connection_list->next == NULL);
767           _dbus_assert (d->link_in_connection_list->prev == NULL);
768           _dbus_list_free_link (d->link_in_connection_list);
769           d->link_in_connection_list = NULL;
770         }
771       
772       if (!dbus_connection_set_data (connection,
773                                      connection_data_slot,
774                                      NULL, NULL))
775         _dbus_assert_not_reached ("failed to set connection data to null");
776
777       /* "d" has now been freed */
778     }
779   
780   return retval;
781 }
782
783 void
784 bus_connections_expire_incomplete (BusConnections *connections)
785 {    
786   int next_interval;
787
788   next_interval = -1;
789   
790   if (connections->incomplete != NULL)
791     {
792       long tv_sec, tv_usec;
793       DBusList *link;
794       int auth_timeout;
795       
796       _dbus_get_current_time (&tv_sec, &tv_usec);
797       auth_timeout = bus_context_get_auth_timeout (connections->context);
798   
799       link = _dbus_list_get_first_link (&connections->incomplete);
800       while (link != NULL)
801         {
802           DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link);
803           DBusConnection *connection;
804           BusConnectionData *d;
805           double elapsed;
806       
807           connection = link->data;
808       
809           d = BUS_CONNECTION_DATA (connection);
810       
811           _dbus_assert (d != NULL);
812       
813           elapsed = ELAPSED_MILLISECONDS_SINCE (d->connection_tv_sec,
814                                                 d->connection_tv_usec,
815                                                 tv_sec, tv_usec);
816
817           if (elapsed >= (double) auth_timeout)
818             {
819               _dbus_verbose ("Timing out authentication for connection %p\n", connection);
820               dbus_connection_close (connection);
821             }
822           else
823             {
824               /* We can end the loop, since the connections are in oldest-first order */
825               next_interval = ((double)auth_timeout) - elapsed;
826               _dbus_verbose ("Connection %p authentication expires in %d milliseconds\n",
827                              connection, next_interval);
828           
829               break;
830             }
831       
832           link = next;
833         }
834     }
835
836   bus_expire_timeout_set_interval (connections->expire_timeout,
837                                    next_interval);
838 }
839
840 static dbus_bool_t
841 expire_incomplete_timeout (void *data)
842 {
843   BusConnections *connections = data;
844
845   _dbus_verbose ("Running\n");
846   
847   /* note that this may remove the timeout */
848   bus_connections_expire_incomplete (connections);
849
850   return TRUE;
851 }
852
853 dbus_bool_t
854 bus_connection_get_unix_groups  (DBusConnection   *connection,
855                                  unsigned long   **groups,
856                                  int              *n_groups,
857                                  DBusError        *error)
858 {
859   BusConnectionData *d;
860   unsigned long uid;
861   
862   d = BUS_CONNECTION_DATA (connection);
863
864   _dbus_assert (d != NULL);
865
866   *groups = NULL;
867   *n_groups = 0;
868
869   if (dbus_connection_get_unix_user (connection, &uid))
870     {
871       if (!_dbus_unix_groups_from_uid (uid, groups, n_groups))
872         {
873           _dbus_verbose ("Did not get any groups for UID %lu\n",
874                          uid);
875           return FALSE;
876         }
877       else
878         {
879           _dbus_verbose ("Got %d groups for UID %lu\n",
880                          *n_groups, uid);
881           return TRUE;
882         }
883     }
884   else
885     return TRUE; /* successfully got 0 groups */
886 }
887
888 dbus_bool_t
889 bus_connection_is_in_unix_group (DBusConnection *connection,
890                                  unsigned long   gid)
891 {
892   int i;
893   unsigned long *group_ids;
894   int n_group_ids;
895
896   if (!bus_connection_get_unix_groups (connection, &group_ids, &n_group_ids,
897                                        NULL))
898     return FALSE;
899
900   i = 0;
901   while (i < n_group_ids)
902     {
903       if (group_ids[i] == gid)
904         {
905           dbus_free (group_ids);
906           return TRUE;
907         }
908       ++i;
909     }
910
911   dbus_free (group_ids);
912   return FALSE;
913 }
914
915 const char *
916 bus_connection_get_loginfo (DBusConnection        *connection)
917 {
918   BusConnectionData *d;
919     
920   d = BUS_CONNECTION_DATA (connection);
921
922   if (!bus_connection_is_active (connection))
923     return "inactive";
924   return d->cached_loginfo_string;  
925 }
926
927 BusClientPolicy*
928 bus_connection_get_policy (DBusConnection *connection)
929 {
930   BusConnectionData *d;
931     
932   d = BUS_CONNECTION_DATA (connection);
933
934   _dbus_assert (d != NULL);
935   _dbus_assert (d->policy != NULL);
936   
937   return d->policy;
938 }
939
940 static dbus_bool_t
941 foreach_active (BusConnections               *connections,
942                 BusConnectionForeachFunction  function,
943                 void                         *data)
944 {
945   DBusList *link;
946   
947   link = _dbus_list_get_first_link (&connections->completed);
948   while (link != NULL)
949     {
950       DBusConnection *connection = link->data;
951       DBusList *next = _dbus_list_get_next_link (&connections->completed, link);
952
953       if (!(* function) (connection, data))
954         return FALSE;
955       
956       link = next;
957     }
958
959   return TRUE;
960 }
961
962 static dbus_bool_t
963 foreach_inactive (BusConnections               *connections,
964                   BusConnectionForeachFunction  function,
965                   void                         *data)
966 {
967   DBusList *link;
968   
969   link = _dbus_list_get_first_link (&connections->incomplete);
970   while (link != NULL)
971     {
972       DBusConnection *connection = link->data;
973       DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link);
974
975       if (!(* function) (connection, data))
976         return FALSE;
977       
978       link = next;
979     }
980
981   return TRUE;
982 }
983
984 /**
985  * Calls function on each active connection; if the function returns
986  * #FALSE, stops iterating. Active connections are authenticated
987  * and have sent a Hello message.
988  *
989  * @param connections the connections object
990  * @param function the function
991  * @param data data to pass to it as a second arg
992  */
993 void
994 bus_connections_foreach_active (BusConnections               *connections,
995                                 BusConnectionForeachFunction  function,
996                                 void                         *data)
997 {
998   foreach_active (connections, function, data);
999 }
1000
1001 /**
1002  * Calls function on each connection; if the function returns
1003  * #FALSE, stops iterating.
1004  *
1005  * @param connections the connections object
1006  * @param function the function
1007  * @param data data to pass to it as a second arg
1008  */
1009 void
1010 bus_connections_foreach (BusConnections               *connections,
1011                          BusConnectionForeachFunction  function,
1012                          void                         *data)
1013 {
1014   if (!foreach_active (connections, function, data))
1015     return;
1016
1017   foreach_inactive (connections, function, data);
1018 }
1019
1020 BusContext*
1021 bus_connections_get_context (BusConnections *connections)
1022 {
1023   return connections->context;
1024 }
1025
1026 /*
1027  * This is used to avoid covering the same connection twice when
1028  * traversing connections. Note that it assumes we will
1029  * bus_connection_mark_stamp() each connection at least once per
1030  * INT_MAX increments of the global stamp, or wraparound would break
1031  * things.
1032  */
1033 void
1034 bus_connections_increment_stamp (BusConnections *connections)
1035 {
1036   connections->stamp += 1;
1037 }
1038
1039 /* Mark connection with current stamp, return TRUE if it
1040  * didn't already have that stamp
1041  */
1042 dbus_bool_t
1043 bus_connection_mark_stamp (DBusConnection *connection)
1044 {
1045   BusConnectionData *d;
1046   
1047   d = BUS_CONNECTION_DATA (connection);
1048   
1049   _dbus_assert (d != NULL);
1050
1051   if (d->stamp == d->connections->stamp)
1052     return FALSE;
1053   else
1054     {
1055       d->stamp = d->connections->stamp;
1056       return TRUE;
1057     }
1058 }
1059
1060 BusContext*
1061 bus_connection_get_context (DBusConnection *connection)
1062 {
1063   BusConnectionData *d;
1064
1065   d = BUS_CONNECTION_DATA (connection);
1066
1067   _dbus_assert (d != NULL);
1068
1069   return d->connections->context;
1070 }
1071
1072 BusConnections*
1073 bus_connection_get_connections (DBusConnection *connection)
1074 {
1075   BusConnectionData *d;
1076     
1077   d = BUS_CONNECTION_DATA (connection);
1078
1079   _dbus_assert (d != NULL);
1080
1081   return d->connections;
1082 }
1083
1084 BusRegistry*
1085 bus_connection_get_registry (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_registry (d->connections->context);
1094 }
1095
1096 BusActivation*
1097 bus_connection_get_activation (DBusConnection *connection)
1098 {
1099   BusConnectionData *d;
1100
1101   d = BUS_CONNECTION_DATA (connection);
1102
1103   _dbus_assert (d != NULL);
1104
1105   return bus_context_get_activation (d->connections->context);
1106 }
1107
1108 BusMatchmaker*
1109 bus_connection_get_matchmaker (DBusConnection *connection)
1110 {
1111   BusConnectionData *d;
1112
1113   d = BUS_CONNECTION_DATA (connection);
1114
1115   _dbus_assert (d != NULL);
1116
1117   return bus_context_get_matchmaker (d->connections->context);
1118 }
1119
1120 BusSELinuxID*
1121 bus_connection_get_selinux_id (DBusConnection *connection)
1122 {
1123   BusConnectionData *d;
1124
1125   d = BUS_CONNECTION_DATA (connection);
1126
1127   _dbus_assert (d != NULL);
1128
1129   return d->selinux_id;
1130 }
1131
1132 /**
1133  * Checks whether the connection is registered with the message bus.
1134  *
1135  * @param connection the connection
1136  * @returns #TRUE if we're an active message bus participant
1137  */
1138 dbus_bool_t
1139 bus_connection_is_active (DBusConnection *connection)
1140 {
1141   BusConnectionData *d;
1142
1143   d = BUS_CONNECTION_DATA (connection);
1144   
1145   return d != NULL && d->name != NULL;
1146 }
1147
1148 dbus_bool_t
1149 bus_connection_preallocate_oom_error (DBusConnection *connection)
1150 {
1151   DBusMessage *message;
1152   DBusPreallocatedSend *preallocated;
1153   BusConnectionData *d;
1154
1155   d = BUS_CONNECTION_DATA (connection);  
1156
1157   _dbus_assert (d != NULL);
1158
1159   if (d->oom_preallocated != NULL)
1160     return TRUE;
1161   
1162   preallocated = dbus_connection_preallocate_send (connection);
1163   if (preallocated == NULL)
1164     return FALSE;
1165
1166   message = dbus_message_new (DBUS_MESSAGE_TYPE_ERROR);
1167
1168   if (message == NULL)
1169     {
1170       dbus_connection_free_preallocated_send (connection, preallocated);
1171       return FALSE;
1172     }
1173
1174   /* d->name may be NULL, but that is OK */
1175   if (!dbus_message_set_error_name (message, DBUS_ERROR_NO_MEMORY) ||
1176       !dbus_message_set_destination (message, d->name) ||
1177       !dbus_message_set_sender (message,
1178                                 DBUS_SERVICE_DBUS))
1179     {
1180       dbus_connection_free_preallocated_send (connection, preallocated);
1181       dbus_message_unref (message);
1182       return FALSE;
1183     }
1184   
1185   /* set reply serial to placeholder value just so space is already allocated
1186    * for it.
1187    */
1188   if (!dbus_message_set_reply_serial (message, 14))
1189     {
1190       dbus_connection_free_preallocated_send (connection, preallocated);
1191       dbus_message_unref (message);
1192       return FALSE;
1193     }
1194
1195   d->oom_message = message;
1196   d->oom_preallocated = preallocated;
1197   
1198   return TRUE;
1199 }
1200
1201 void
1202 bus_connection_send_oom_error (DBusConnection *connection,
1203                                DBusMessage    *in_reply_to)
1204 {
1205   BusConnectionData *d;
1206
1207   d = BUS_CONNECTION_DATA (connection);  
1208
1209   _dbus_assert (d != NULL);  
1210   _dbus_assert (d->oom_message != NULL);
1211
1212   /* should always succeed since we set it to a placeholder earlier */
1213   if (!dbus_message_set_reply_serial (d->oom_message,
1214                                       dbus_message_get_serial (in_reply_to)))
1215     _dbus_assert_not_reached ("Failed to set reply serial for preallocated oom message");
1216
1217   _dbus_assert (dbus_message_get_sender (d->oom_message) != NULL);
1218   
1219   dbus_connection_send_preallocated (connection, d->oom_preallocated,
1220                                      d->oom_message, NULL);
1221
1222   dbus_message_unref (d->oom_message);
1223   d->oom_message = NULL;
1224   d->oom_preallocated = NULL;
1225 }
1226
1227 void
1228 bus_connection_add_match_rule_link (DBusConnection *connection,
1229                                     DBusList       *link)
1230 {
1231   BusConnectionData *d;
1232
1233   d = BUS_CONNECTION_DATA (connection);
1234   _dbus_assert (d != NULL);
1235
1236   _dbus_list_append_link (&d->match_rules, link);
1237
1238   d->n_match_rules += 1;
1239 }
1240
1241 dbus_bool_t
1242 bus_connection_add_match_rule (DBusConnection *connection,
1243                                BusMatchRule   *rule)
1244 {
1245     DBusList *link;
1246
1247   link = _dbus_list_alloc_link (rule);
1248
1249   if (link == NULL)
1250     return FALSE;
1251
1252   bus_connection_add_match_rule_link (connection, link);
1253
1254   return TRUE;
1255 }
1256
1257 void
1258 bus_connection_remove_match_rule (DBusConnection *connection,
1259                                   BusMatchRule   *rule)
1260 {
1261   BusConnectionData *d;
1262
1263   d = BUS_CONNECTION_DATA (connection);
1264   _dbus_assert (d != NULL);
1265
1266   _dbus_list_remove_last (&d->match_rules, rule);
1267
1268   d->n_match_rules -= 1;
1269   _dbus_assert (d->n_match_rules >= 0);
1270 }
1271
1272 int
1273 bus_connection_get_n_match_rules (DBusConnection *connection)
1274 {
1275   BusConnectionData *d;
1276
1277   d = BUS_CONNECTION_DATA (connection);
1278   _dbus_assert (d != NULL);
1279   
1280   return d->n_match_rules;
1281 }
1282
1283 void
1284 bus_connection_add_owned_service_link (DBusConnection *connection,
1285                                        DBusList       *link)
1286 {
1287   BusConnectionData *d;
1288
1289   d = BUS_CONNECTION_DATA (connection);
1290   _dbus_assert (d != NULL);
1291
1292   _dbus_list_append_link (&d->services_owned, link);
1293
1294   d->n_services_owned += 1;
1295 }
1296
1297 dbus_bool_t
1298 bus_connection_add_owned_service (DBusConnection *connection,
1299                                   BusService     *service)
1300 {
1301   DBusList *link;
1302
1303   link = _dbus_list_alloc_link (service);
1304
1305   if (link == NULL)
1306     return FALSE;
1307
1308   bus_connection_add_owned_service_link (connection, link);
1309
1310   return TRUE;
1311 }
1312
1313 void
1314 bus_connection_remove_owned_service (DBusConnection *connection,
1315                                      BusService     *service)
1316 {
1317   BusConnectionData *d;
1318
1319   d = BUS_CONNECTION_DATA (connection);
1320   _dbus_assert (d != NULL);
1321
1322   _dbus_list_remove_last (&d->services_owned, service);
1323
1324   d->n_services_owned -= 1;
1325   _dbus_assert (d->n_services_owned >= 0);
1326 }
1327
1328 int
1329 bus_connection_get_n_services_owned (DBusConnection *connection)
1330 {
1331   BusConnectionData *d;
1332
1333   d = BUS_CONNECTION_DATA (connection);
1334   _dbus_assert (d != NULL);
1335   
1336   return d->n_services_owned;
1337 }
1338
1339 dbus_bool_t
1340 bus_connection_complete (DBusConnection   *connection,
1341                          const DBusString *name,
1342                          DBusError        *error)
1343 {
1344   BusConnectionData *d;
1345   unsigned long uid;
1346   
1347   d = BUS_CONNECTION_DATA (connection);
1348   _dbus_assert (d != NULL);
1349   _dbus_assert (d->name == NULL);
1350   _dbus_assert (d->policy == NULL);
1351
1352   _dbus_assert (!bus_connection_is_active (connection));
1353   
1354   if (!_dbus_string_copy_data (name, &d->name))
1355     {
1356       BUS_SET_OOM (error);
1357       return FALSE;
1358     }
1359
1360   _dbus_assert (d->name != NULL);
1361   
1362   _dbus_verbose ("Name %s assigned to %p\n", d->name, connection);
1363
1364   d->policy = bus_context_create_client_policy (d->connections->context,
1365                                                 connection,
1366                                                 error);
1367
1368   /* we may have a NULL policy on OOM or error getting list of
1369    * groups for a user. In the latter case we don't handle it so
1370    * well currently, as it will just keep failing over and over.
1371    */
1372
1373   if (d->policy == NULL)
1374     {
1375       _dbus_verbose ("Failed to create security policy for connection %p\n",
1376                      connection);
1377       _DBUS_ASSERT_ERROR_IS_SET (error);
1378       dbus_free (d->name);
1379       d->name = NULL;
1380       return FALSE;
1381     }
1382   
1383   if (dbus_connection_get_unix_user (connection, &uid))
1384     {
1385       if (!adjust_connections_for_uid (d->connections,
1386                                        uid, 1))
1387         goto fail;
1388     }
1389
1390   /* Create and cache a string which holds information about the 
1391    * peer process; used for logging purposes.
1392    */
1393   if (!cache_peer_loginfo_string (d, connection))
1394     goto fail;
1395
1396   /* Now the connection is active, move it between lists */
1397   _dbus_list_unlink (&d->connections->incomplete,
1398                      d->link_in_connection_list);
1399   d->connections->n_incomplete -= 1;
1400   _dbus_list_append_link (&d->connections->completed,
1401                           d->link_in_connection_list);
1402   d->connections->n_completed += 1;
1403
1404   _dbus_assert (d->connections->n_incomplete >= 0);
1405   _dbus_assert (d->connections->n_completed > 0);
1406
1407   /* See if we can remove the timeout */
1408   bus_connections_expire_incomplete (d->connections);
1409
1410   _dbus_assert (bus_connection_is_active (connection));
1411   
1412   return TRUE;
1413 fail:
1414   BUS_SET_OOM (error);
1415   dbus_free (d->name);
1416   d->name = NULL;
1417   if (d->policy)
1418     bus_client_policy_unref (d->policy);
1419   d->policy = NULL;
1420   return FALSE;
1421 }
1422
1423 const char *
1424 bus_connection_get_name (DBusConnection *connection)
1425 {
1426   BusConnectionData *d;
1427   
1428   d = BUS_CONNECTION_DATA (connection);
1429   _dbus_assert (d != NULL);
1430   
1431   return d->name;
1432 }
1433
1434 /**
1435  * Check whether completing the passed-in connection would
1436  * exceed limits, and if so set error and return #FALSE
1437  */
1438 dbus_bool_t
1439 bus_connections_check_limits (BusConnections  *connections,
1440                               DBusConnection  *requesting_completion,
1441                               DBusError       *error)
1442 {
1443   BusConnectionData *d;
1444   unsigned long uid;
1445   
1446   d = BUS_CONNECTION_DATA (requesting_completion);
1447   _dbus_assert (d != NULL);
1448
1449   _dbus_assert (d->name == NULL);
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 }