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