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