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