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