2003-02-20 Alexander Larsson <alexl@redhat.com>
[platform/upstream/dbus.git] / dbus / dbus-connection.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-connection.c DBusConnection object
3  *
4  * Copyright (C) 2002, 2003  Red Hat Inc.
5  *
6  * Licensed under the Academic Free License version 1.2
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
24 #include "dbus-connection.h"
25 #include "dbus-list.h"
26 #include "dbus-timeout.h"
27 #include "dbus-transport.h"
28 #include "dbus-watch.h"
29 #include "dbus-connection-internal.h"
30 #include "dbus-list.h"
31 #include "dbus-hash.h"
32 #include "dbus-message-internal.h"
33 #include "dbus-message-handler.h"
34 #include "dbus-threads.h"
35 #include "dbus-protocol.h"
36
37 /**
38  * @defgroup DBusConnection DBusConnection
39  * @ingroup  DBus
40  * @brief Connection to another application
41  *
42  * A DBusConnection represents a connection to another
43  * application. Messages can be sent and received via this connection.
44  *
45  * The connection maintains a queue of incoming messages and a queue
46  * of outgoing messages. dbus_connection_pop_message() and friends
47  * can be used to read incoming messages from the queue.
48  * Outgoing messages are automatically discarded as they are
49  * written to the network.
50  *
51  * In brief a DBusConnection is a message queue associated with some
52  * message transport mechanism such as a socket.
53  * 
54  */
55
56 /**
57  * @defgroup DBusConnectionInternals DBusConnection implementation details
58  * @ingroup  DBusInternals
59  * @brief Implementation details of DBusConnection
60  *
61  * @{
62  */
63
64 /** default timeout value when waiting for a message reply */
65 #define DEFAULT_TIMEOUT_VALUE (15 * 1000)
66
67 static dbus_bool_t _dbus_modify_sigpipe = TRUE;
68
69 /** Opaque typedef for DBusDataSlot */
70 typedef struct DBusDataSlot DBusDataSlot;
71 /** DBusDataSlot is used to store application data on the connection */
72 struct DBusDataSlot
73 {
74   void *data;                      /**< The application data */
75   DBusFreeFunction free_data_func; /**< Free the application data */
76 };
77
78 /**
79  * Implementation details of DBusConnection. All fields are private.
80  */
81 struct DBusConnection
82 {
83   int refcount; /**< Reference count. */
84
85   DBusMutex *mutex; /**< Lock on the entire DBusConnection */
86
87   dbus_bool_t dispatch_acquired; /**< Protects dispatch_message */
88   DBusCondVar *dispatch_cond;    /**< Protects dispatch_message */
89
90   dbus_bool_t io_path_acquired;  /**< Protects transport io path */
91   DBusCondVar *io_path_cond;     /**< Protects transport io path */
92   
93   DBusList *outgoing_messages; /**< Queue of messages we need to send, send the end of the list first. */
94   DBusList *incoming_messages; /**< Queue of messages we have received, end of the list received most recently. */
95
96   DBusMessage *message_borrowed; /**< True if the first incoming message has been borrowed */
97   DBusCondVar *message_returned_cond; /**< Used with dbus_connection_borrow_message() */
98   
99   int n_outgoing;              /**< Length of outgoing queue. */
100   int n_incoming;              /**< Length of incoming queue. */
101   
102   DBusTransport *transport;    /**< Object that sends/receives messages over network. */
103   DBusWatchList *watches;      /**< Stores active watches. */
104   DBusTimeoutList *timeouts;   /**< Stores active timeouts. */
105   
106   DBusHashTable *handler_table; /**< Table of registered DBusMessageHandler */
107   DBusList *filter_list;        /**< List of filters. */
108   DBusDataSlot *data_slots;        /**< Data slots */
109   int           n_slots; /**< Slots allocated so far. */
110
111   DBusHashTable *pending_replies;  /**< Hash of message serials and their message handlers. */  
112   DBusCounter *connection_counter; /**< Counter that we decrement when finalized */
113   
114   int client_serial;            /**< Client serial. Increments each time a message is sent  */
115   DBusList *disconnect_message_link; /**< Preallocated list node for queueing the disconnection message */
116 };
117
118 typedef struct
119 {
120   DBusConnection *connection;
121   DBusMessageHandler *handler;
122   DBusTimeout *timeout;
123   int serial;
124
125   DBusList *timeout_link; /* Preallocated timeout response */
126   
127   dbus_bool_t timeout_added;
128   dbus_bool_t connection_added;
129 } ReplyHandlerData;
130
131 static void reply_handler_data_free (ReplyHandlerData *data);
132
133 static void _dbus_connection_free_data_slots_nolock (DBusConnection *connection);
134 static void _dbus_connection_remove_timeout_locked (DBusConnection *connection,
135                                                     DBusTimeout    *timeout);
136
137 /**
138  * Acquires the connection lock.
139  *
140  * @param connection the connection.
141  */
142 void
143 _dbus_connection_lock (DBusConnection *connection)
144 {
145   dbus_mutex_lock (connection->mutex);
146 }
147
148 /**
149  * Releases the connection lock.
150  *
151  * @param connection the connection.
152  */
153 void
154 _dbus_connection_unlock (DBusConnection *connection)
155 {
156   dbus_mutex_unlock (connection->mutex);
157 }
158
159
160 /**
161  * Adds a message to the incoming message queue, returning #FALSE
162  * if there's insufficient memory to queue the message.
163  *
164  * @param connection the connection.
165  * @param message the message to queue.
166  * @returns #TRUE on success.
167  */
168 dbus_bool_t
169 _dbus_connection_queue_received_message (DBusConnection *connection,
170                                          DBusMessage    *message)
171 {
172   ReplyHandlerData *reply_handler_data;
173   dbus_int32_t reply_serial;
174   
175   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
176   
177   if (!_dbus_list_append (&connection->incoming_messages,
178                           message))
179     return FALSE;
180
181   /* If this is a reply we're waiting on, remove timeout for it */
182   reply_serial = _dbus_message_get_reply_serial (message);
183   if (reply_serial != -1)
184     {
185       reply_handler_data = _dbus_hash_table_lookup_int (connection->pending_replies,
186                                                         reply_serial);
187       if (reply_handler_data != NULL)
188         {
189           if (reply_handler_data->timeout_added)
190             _dbus_connection_remove_timeout_locked (connection,
191                                                     reply_handler_data->timeout);
192           reply_handler_data->timeout_added = FALSE;
193         }
194     }
195   
196   dbus_message_ref (message);
197   connection->n_incoming += 1;
198
199   _dbus_verbose ("Incoming message %p added to queue, %d incoming\n",
200                  message, connection->n_incoming);
201   
202   return TRUE;
203 }
204
205 /**
206  * Adds a link + message to the incoming message queue.
207  * Can't fail. Takes ownership of both link and message.
208  *
209  * @param connection the connection.
210  * @param link the list node and message to queue.
211  *
212  * @todo This needs to wake up the mainloop if it is in
213  * a poll/select and this is a multithreaded app.
214  */
215 static void
216 _dbus_connection_queue_synthesized_message_link (DBusConnection *connection,
217                                                  DBusList *link)
218 {
219   _dbus_list_append_link (&connection->incoming_messages, link);
220
221   connection->n_incoming += 1;
222
223   _dbus_verbose ("Incoming synthesized message %p added to queue, %d incoming\n",
224                  link->data, connection->n_incoming);
225 }
226
227
228 /**
229  * Checks whether there are messages in the outgoing message queue.
230  *
231  * @param connection the connection.
232  * @returns #TRUE if the outgoing queue is non-empty.
233  */
234 dbus_bool_t
235 _dbus_connection_have_messages_to_send (DBusConnection *connection)
236 {
237   return connection->outgoing_messages != NULL;
238 }
239
240 /**
241  * Gets the next outgoing message. The message remains in the
242  * queue, and the caller does not own a reference to it.
243  *
244  * @param connection the connection.
245  * @returns the message to be sent.
246  */ 
247 DBusMessage*
248 _dbus_connection_get_message_to_send (DBusConnection *connection)
249 {
250   return _dbus_list_get_last (&connection->outgoing_messages);
251 }
252
253 /**
254  * Notifies the connection that a message has been sent, so the
255  * message can be removed from the outgoing queue.
256  *
257  * @param connection the connection.
258  * @param message the message that was sent.
259  */
260 void
261 _dbus_connection_message_sent (DBusConnection *connection,
262                                DBusMessage    *message)
263 {
264   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
265   _dbus_assert (message == _dbus_list_get_last (&connection->outgoing_messages));
266   
267   _dbus_list_pop_last (&connection->outgoing_messages);
268   dbus_message_unref (message);
269   
270   connection->n_outgoing -= 1;
271
272   _dbus_verbose ("Message %p removed from outgoing queue, %d left to send\n",
273                  message, connection->n_outgoing);
274   
275   if (connection->n_outgoing == 0)
276     _dbus_transport_messages_pending (connection->transport,
277                                       connection->n_outgoing);  
278 }
279
280 /**
281  * Adds a watch using the connection's DBusAddWatchFunction if
282  * available. Otherwise records the watch to be added when said
283  * function is available. Also re-adds the watch if the
284  * DBusAddWatchFunction changes. May fail due to lack of memory.
285  *
286  * @param connection the connection.
287  * @param watch the watch to add.
288  * @returns #TRUE on success.
289  */
290 dbus_bool_t
291 _dbus_connection_add_watch (DBusConnection *connection,
292                             DBusWatch      *watch)
293 {
294   if (connection->watches) /* null during finalize */
295     return _dbus_watch_list_add_watch (connection->watches,
296                                        watch);
297   else
298     return FALSE;
299 }
300
301 /**
302  * Removes a watch using the connection's DBusRemoveWatchFunction
303  * if available. It's an error to call this function on a watch
304  * that was not previously added.
305  *
306  * @param connection the connection.
307  * @param watch the watch to remove.
308  */
309 void
310 _dbus_connection_remove_watch (DBusConnection *connection,
311                                DBusWatch      *watch)
312 {
313   if (connection->watches) /* null during finalize */
314     _dbus_watch_list_remove_watch (connection->watches,
315                                    watch);
316 }
317
318 /**
319  * Adds a timeout using the connection's DBusAddTimeoutFunction if
320  * available. Otherwise records the timeout to be added when said
321  * function is available. Also re-adds the timeout if the
322  * DBusAddTimeoutFunction changes. May fail due to lack of memory.
323  *
324  * @param connection the connection.
325  * @param timeout the timeout to add.
326  * @returns #TRUE on success.
327  */
328 dbus_bool_t
329 _dbus_connection_add_timeout (DBusConnection *connection,
330                               DBusTimeout    *timeout)
331 {
332  if (connection->timeouts) /* null during finalize */
333     return _dbus_timeout_list_add_timeout (connection->timeouts,
334                                            timeout);
335   else
336     return FALSE;  
337 }
338
339 /**
340  * Removes a timeout using the connection's DBusRemoveTimeoutFunction
341  * if available. It's an error to call this function on a timeout
342  * that was not previously added.
343  *
344  * @param connection the connection.
345  * @param timeout the timeout to remove.
346  */
347 void
348 _dbus_connection_remove_timeout (DBusConnection *connection,
349                                  DBusTimeout    *timeout)
350 {
351   if (connection->timeouts) /* null during finalize */
352     _dbus_timeout_list_remove_timeout (connection->timeouts,
353                                        timeout);
354 }
355
356 static void
357 _dbus_connection_remove_timeout_locked (DBusConnection *connection,
358                                         DBusTimeout    *timeout)
359 {
360   dbus_mutex_lock (connection->mutex);
361   _dbus_connection_remove_timeout (connection, timeout);
362   dbus_mutex_unlock (connection->mutex);
363 }
364
365
366 /**
367  * Tells the connection that the transport has been disconnected.
368  * Results in posting a disconnect message on the incoming message
369  * queue.  Only has an effect the first time it's called.
370  *
371  * @param connection the connection
372  */
373 void
374 _dbus_connection_notify_disconnected (DBusConnection *connection)
375 {
376   if (connection->disconnect_message_link)
377     {
378       /* We haven't sent the disconnect message already */
379       _dbus_connection_queue_synthesized_message_link (connection,
380                                                        connection->disconnect_message_link);
381       connection->disconnect_message_link = NULL;
382     }
383 }
384
385
386 /**
387  * Acquire the transporter I/O path. This must be done before
388  * doing any I/O in the transporter. May sleep and drop the
389  * connection mutex while waiting for the I/O path.
390  *
391  * @param connection the connection.
392  * @param timeout_milliseconds maximum blocking time, or -1 for no limit.
393  * @returns TRUE if the I/O path was acquired.
394  */
395 static dbus_bool_t
396 _dbus_connection_acquire_io_path (DBusConnection *connection,
397                                   int timeout_milliseconds)
398 {
399   dbus_bool_t res = TRUE;
400   if (timeout_milliseconds != -1) 
401     res = dbus_condvar_wait_timeout (connection->io_path_cond,
402                                      connection->mutex,
403                                      timeout_milliseconds);
404   else
405     dbus_condvar_wait (connection->io_path_cond, connection->mutex);
406
407   if (res)
408     {
409       _dbus_assert (!connection->io_path_acquired);
410
411       connection->io_path_acquired = TRUE;
412     }
413   
414   return res;
415 }
416
417 /**
418  * Release the I/O path when you're done with it. Only call
419  * after you've acquired the I/O. Wakes up at most one thread
420  * currently waiting to acquire the I/O path.
421  *
422  * @param connection the connection.
423  */
424 static void
425 _dbus_connection_release_io_path (DBusConnection *connection)
426 {
427   _dbus_assert (connection->io_path_acquired);
428
429   connection->io_path_acquired = FALSE;
430   dbus_condvar_wake_one (connection->io_path_cond);
431 }
432
433
434 /**
435  * Queues incoming messages and sends outgoing messages for this
436  * connection, optionally blocking in the process. Each call to
437  * _dbus_connection_do_iteration() will call select() or poll() one
438  * time and then read or write data if possible.
439  *
440  * The purpose of this function is to be able to flush outgoing
441  * messages or queue up incoming messages without returning
442  * control to the application and causing reentrancy weirdness.
443  *
444  * The flags parameter allows you to specify whether to
445  * read incoming messages, write outgoing messages, or both,
446  * and whether to block if no immediate action is possible.
447  *
448  * The timeout_milliseconds parameter does nothing unless the
449  * iteration is blocking.
450  *
451  * If there are no outgoing messages and DBUS_ITERATION_DO_READING
452  * wasn't specified, then it's impossible to block, even if
453  * you specify DBUS_ITERATION_BLOCK; in that case the function
454  * returns immediately.
455  * 
456  * @param connection the connection.
457  * @param flags iteration flags.
458  * @param timeout_milliseconds maximum blocking time, or -1 for no limit.
459  */
460 void
461 _dbus_connection_do_iteration (DBusConnection *connection,
462                                unsigned int    flags,
463                                int             timeout_milliseconds)
464 {
465   if (connection->n_outgoing == 0)
466     flags &= ~DBUS_ITERATION_DO_WRITING;
467
468   if (_dbus_connection_acquire_io_path (connection,
469                                         (flags & DBUS_ITERATION_BLOCK)?timeout_milliseconds:0))
470     {
471       _dbus_transport_do_iteration (connection->transport,
472                                     flags, timeout_milliseconds);
473       _dbus_connection_release_io_path (connection);
474     }
475 }
476
477 /**
478  * Creates a new connection for the given transport.  A transport
479  * represents a message stream that uses some concrete mechanism, such
480  * as UNIX domain sockets. May return #NULL if insufficient
481  * memory exists to create the connection.
482  *
483  * @param transport the transport.
484  * @returns the new connection, or #NULL on failure.
485  */
486 DBusConnection*
487 _dbus_connection_new_for_transport (DBusTransport *transport)
488 {
489   DBusConnection *connection;
490   DBusWatchList *watch_list;
491   DBusTimeoutList *timeout_list;
492   DBusHashTable *handler_table, *pending_replies;
493   DBusMutex *mutex;
494   DBusCondVar *message_returned_cond;
495   DBusCondVar *dispatch_cond;
496   DBusCondVar *io_path_cond;
497   DBusList *disconnect_link;
498   DBusMessage *disconnect_message;
499
500   watch_list = NULL;
501   connection = NULL;
502   handler_table = NULL;
503   pending_replies = NULL;
504   timeout_list = NULL;
505   mutex = NULL;
506   message_returned_cond = NULL;
507   dispatch_cond = NULL;
508   io_path_cond = NULL;
509   disconnect_link = NULL;
510   disconnect_message = NULL;
511   
512   watch_list = _dbus_watch_list_new ();
513   if (watch_list == NULL)
514     goto error;
515
516   timeout_list = _dbus_timeout_list_new ();
517   if (timeout_list == NULL)
518     goto error;
519   
520   handler_table =
521     _dbus_hash_table_new (DBUS_HASH_STRING,
522                           dbus_free, NULL);
523   if (handler_table == NULL)
524     goto error;
525
526   pending_replies =
527     _dbus_hash_table_new (DBUS_HASH_INT,
528                           NULL, (DBusFreeFunction)reply_handler_data_free);
529   if (pending_replies == NULL)
530     goto error;
531   
532   connection = dbus_new0 (DBusConnection, 1);
533   if (connection == NULL)
534     goto error;
535
536   mutex = dbus_mutex_new ();
537   if (mutex == NULL)
538     goto error;
539   
540   message_returned_cond = dbus_condvar_new ();
541   if (message_returned_cond == NULL)
542     goto error;
543   
544   dispatch_cond = dbus_condvar_new ();
545   if (dispatch_cond == NULL)
546     goto error;
547   
548   io_path_cond = dbus_condvar_new ();
549   if (io_path_cond == NULL)
550     goto error;
551
552   disconnect_message = dbus_message_new (NULL, DBUS_MESSAGE_LOCAL_DISCONNECT);
553   if (disconnect_message == NULL)
554     goto error;
555
556   disconnect_link = _dbus_list_alloc_link (disconnect_message);
557   if (disconnect_link == NULL)
558     goto error;
559
560   if (_dbus_modify_sigpipe)
561     _dbus_disable_sigpipe ();
562   
563   connection->refcount = 1;
564   connection->mutex = mutex;
565   connection->dispatch_cond = dispatch_cond;
566   connection->io_path_cond = io_path_cond;
567   connection->message_returned_cond = message_returned_cond;
568   connection->transport = transport;
569   connection->watches = watch_list;
570   connection->timeouts = timeout_list;
571   connection->handler_table = handler_table;
572   connection->pending_replies = pending_replies;
573   connection->filter_list = NULL;
574
575   connection->data_slots = NULL;
576   connection->n_slots = 0;
577   connection->client_serial = 1;
578
579   connection->disconnect_message_link = disconnect_link;
580   
581   _dbus_transport_ref (transport);
582   _dbus_transport_set_connection (transport, connection);
583   
584   return connection;
585   
586  error:
587   if (disconnect_message != NULL)
588     dbus_message_unref (disconnect_message);
589   
590   if (disconnect_link != NULL)
591     _dbus_list_free_link (disconnect_link);
592   
593   if (io_path_cond != NULL)
594     dbus_condvar_free (io_path_cond);
595   
596   if (dispatch_cond != NULL)
597     dbus_condvar_free (dispatch_cond);
598   
599   if (message_returned_cond != NULL)
600     dbus_condvar_free (message_returned_cond);
601   
602   if (mutex != NULL)
603     dbus_mutex_free (mutex);
604
605   if (connection != NULL)
606     dbus_free (connection);
607
608   if (handler_table)
609     _dbus_hash_table_unref (handler_table);
610
611   if (pending_replies)
612     _dbus_hash_table_unref (pending_replies);
613   
614   if (watch_list)
615     _dbus_watch_list_free (watch_list);
616
617   if (timeout_list)
618     _dbus_timeout_list_free (timeout_list);
619   
620   return NULL;
621 }
622
623 static dbus_int32_t
624 _dbus_connection_get_next_client_serial (DBusConnection *connection)
625 {
626   int serial;
627
628   serial = connection->client_serial++;
629
630   if (connection->client_serial < 0)
631     connection->client_serial = 1;
632   
633   return serial;
634 }
635
636 /**
637  * Used to notify a connection when a DBusMessageHandler is
638  * destroyed, so the connection can drop any reference
639  * to the handler. This is a private function, but still
640  * takes the connection lock. Don't call it with the lock held.
641  *
642  * @todo needs to check in pending_replies too.
643  * 
644  * @param connection the connection
645  * @param handler the handler
646  */
647 void
648 _dbus_connection_handler_destroyed_locked (DBusConnection     *connection,
649                                            DBusMessageHandler *handler)
650 {
651   DBusHashIter iter;
652   DBusList *link;
653
654   dbus_mutex_lock (connection->mutex);
655   
656   _dbus_hash_iter_init (connection->handler_table, &iter);
657   while (_dbus_hash_iter_next (&iter))
658     {
659       DBusMessageHandler *h = _dbus_hash_iter_get_value (&iter);
660
661       if (h == handler)
662         _dbus_hash_iter_remove_entry (&iter);
663     }
664
665   link = _dbus_list_get_first_link (&connection->filter_list);
666   while (link != NULL)
667     {
668       DBusMessageHandler *h = link->data;
669       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
670
671       if (h == handler)
672         _dbus_list_remove_link (&connection->filter_list,
673                                 link);
674       
675       link = next;
676     }
677   dbus_mutex_unlock (connection->mutex);
678 }
679
680 /**
681  * Adds the counter used to count the number of open connections.
682  * Increments the counter by one, and saves it to be decremented
683  * again when this connection is finalized.
684  *
685  * @param connection a #DBusConnection
686  * @param counter counter that tracks number of connections
687  */
688 void
689 _dbus_connection_set_connection_counter (DBusConnection *connection,
690                                          DBusCounter    *counter)
691 {
692   _dbus_assert (connection->connection_counter == NULL);
693   
694   connection->connection_counter = counter;
695   _dbus_counter_ref (connection->connection_counter);
696   _dbus_counter_adjust (connection->connection_counter, 1);
697 }
698
699 /** @} */
700
701 /**
702  * @addtogroup DBusConnection
703  *
704  * @{
705  */
706
707 /**
708  * Opens a new connection to a remote address.
709  *
710  * @todo specify what the address parameter is. Right now
711  * it's just the name of a UNIX domain socket. It should be
712  * something more complex that encodes which transport to use.
713  *
714  * If the open fails, the function returns #NULL, and provides
715  * a reason for the failure in the result parameter. Pass
716  * #NULL for the result parameter if you aren't interested
717  * in the reason for failure.
718  * 
719  * @param address the address.
720  * @param result address where a result code can be returned.
721  * @returns new connection, or #NULL on failure.
722  */
723 DBusConnection*
724 dbus_connection_open (const char     *address,
725                       DBusResultCode *result)
726 {
727   DBusConnection *connection;
728   DBusTransport *transport;
729   
730   transport = _dbus_transport_open (address, result);
731   if (transport == NULL)
732     return NULL;
733   
734   connection = _dbus_connection_new_for_transport (transport);
735
736   _dbus_transport_unref (transport);
737   
738   if (connection == NULL)
739     {
740       dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
741       return NULL;
742     }
743   
744   return connection;
745 }
746
747 /**
748  * Increments the reference count of a DBusConnection.
749  *
750  * @param connection the connection.
751  */
752 void
753 dbus_connection_ref (DBusConnection *connection)
754 {
755   dbus_mutex_lock (connection->mutex);
756   _dbus_assert (connection->refcount > 0);
757
758   connection->refcount += 1;
759   dbus_mutex_unlock (connection->mutex);
760 }
761
762 /**
763  * Increments the reference count of a DBusConnection.
764  * Requires that the caller already holds the connection lock.
765  *
766  * @param connection the connection.
767  */
768 void
769 _dbus_connection_ref_unlocked (DBusConnection *connection)
770 {
771   _dbus_assert (connection->refcount > 0);
772   connection->refcount += 1;
773 }
774
775
776 /* This is run without the mutex held, but after the last reference
777  * to the connection has been dropped we should have no thread-related
778  * problems
779  */
780 static void
781 _dbus_connection_last_unref (DBusConnection *connection)
782 {
783   DBusHashIter iter;
784   DBusList *link;
785
786   _dbus_assert (!_dbus_transport_get_is_connected (connection->transport));
787   
788   if (connection->connection_counter != NULL)
789     {
790       /* subtract ourselves from the counter */
791       _dbus_counter_adjust (connection->connection_counter, - 1);
792       _dbus_counter_unref (connection->connection_counter);
793       connection->connection_counter = NULL;
794     }
795   
796   _dbus_watch_list_free (connection->watches);
797   connection->watches = NULL;
798   
799   _dbus_timeout_list_free (connection->timeouts);
800   connection->timeouts = NULL;
801   
802   _dbus_connection_free_data_slots_nolock (connection);
803   
804   _dbus_hash_iter_init (connection->handler_table, &iter);
805   while (_dbus_hash_iter_next (&iter))
806     {
807       DBusMessageHandler *h = _dbus_hash_iter_get_value (&iter);
808       
809       _dbus_message_handler_remove_connection (h, connection);
810     }
811   
812   link = _dbus_list_get_first_link (&connection->filter_list);
813   while (link != NULL)
814     {
815       DBusMessageHandler *h = link->data;
816       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
817       
818       _dbus_message_handler_remove_connection (h, connection);
819       
820       link = next;
821     }
822
823   _dbus_hash_table_unref (connection->handler_table);
824   connection->handler_table = NULL;
825
826   _dbus_hash_table_unref (connection->pending_replies);
827   connection->pending_replies = NULL;
828   
829   _dbus_list_clear (&connection->filter_list);
830   
831   _dbus_list_foreach (&connection->outgoing_messages,
832                       (DBusForeachFunction) dbus_message_unref,
833                       NULL);
834   _dbus_list_clear (&connection->outgoing_messages);
835   
836   _dbus_list_foreach (&connection->incoming_messages,
837                       (DBusForeachFunction) dbus_message_unref,
838                       NULL);
839   _dbus_list_clear (&connection->incoming_messages);
840   
841   _dbus_transport_unref (connection->transport);
842
843   if (connection->disconnect_message_link)
844     {
845       DBusMessage *message = connection->disconnect_message_link->data;
846       dbus_message_unref (message);
847       _dbus_list_free_link (connection->disconnect_message_link);
848     }
849   
850   dbus_condvar_free (connection->dispatch_cond);
851   dbus_condvar_free (connection->io_path_cond);
852   dbus_condvar_free (connection->message_returned_cond);
853   
854   dbus_mutex_free (connection->mutex);
855   
856   dbus_free (connection);
857 }
858
859 /**
860  * Decrements the reference count of a DBusConnection, and finalizes
861  * it if the count reaches zero.  It is a bug to drop the last reference
862  * to a connection that has not been disconnected.
863  *
864  * @param connection the connection.
865  */
866 void
867 dbus_connection_unref (DBusConnection *connection)
868 {
869   dbus_bool_t last_unref;
870   
871   dbus_mutex_lock (connection->mutex);
872   
873   _dbus_assert (connection != NULL);
874   _dbus_assert (connection->refcount > 0);
875
876   connection->refcount -= 1;
877   last_unref = (connection->refcount == 0);
878
879   dbus_mutex_unlock (connection->mutex);
880
881   if (last_unref)
882     _dbus_connection_last_unref (connection);
883 }
884
885 /**
886  * Closes the connection, so no further data can be sent or received.
887  * Any further attempts to send data will result in errors.  This
888  * function does not affect the connection's reference count.  It's
889  * safe to disconnect a connection more than once; all calls after the
890  * first do nothing. It's impossible to "reconnect" a connection, a
891  * new connection must be created.
892  *
893  * @param connection the connection.
894  */
895 void
896 dbus_connection_disconnect (DBusConnection *connection)
897 {
898   dbus_mutex_lock (connection->mutex);
899   _dbus_transport_disconnect (connection->transport);
900   dbus_mutex_unlock (connection->mutex);
901 }
902
903 /**
904  * Gets whether the connection is currently connected.  All
905  * connections are connected when they are opened.  A connection may
906  * become disconnected when the remote application closes its end, or
907  * exits; a connection may also be disconnected with
908  * dbus_connection_disconnect().
909  *
910  * @param connection the connection.
911  * @returns #TRUE if the connection is still alive.
912  */
913 dbus_bool_t
914 dbus_connection_get_is_connected (DBusConnection *connection)
915 {
916   dbus_bool_t res;
917   
918   dbus_mutex_lock (connection->mutex);
919   res = _dbus_transport_get_is_connected (connection->transport);
920   dbus_mutex_unlock (connection->mutex);
921   
922   return res;
923 }
924
925 /**
926  * Gets whether the connection was authenticated. (Note that
927  * if the connection was authenticated then disconnected,
928  * this function still returns #TRUE)
929  *
930  * @param connection the connection
931  * @returns #TRUE if the connection was ever authenticated
932  */
933 dbus_bool_t
934 dbus_connection_get_is_authenticated (DBusConnection *connection)
935 {
936   dbus_bool_t res;
937   
938   dbus_mutex_lock (connection->mutex);
939   res = _dbus_transport_get_is_authenticated (connection->transport);
940   dbus_mutex_unlock (connection->mutex);
941   
942   return res;
943 }
944
945 /**
946  * Adds a message to the outgoing message queue. Does not block to
947  * write the message to the network; that happens asynchronously. to
948  * force the message to be written, call dbus_connection_flush().
949  *
950  * If the function fails, it returns #FALSE and returns the
951  * reason for failure via the result parameter.
952  * The result parameter can be #NULL if you aren't interested
953  * in the reason for the failure.
954  * 
955  * @param connection the connection.
956  * @param message the message to write.
957  * @param client_serial return location for client serial.
958  * @param result address where result code can be placed.
959  * @returns #TRUE on success.
960  */
961 dbus_bool_t
962 dbus_connection_send_message (DBusConnection *connection,
963                               DBusMessage    *message,
964                               dbus_int32_t   *client_serial,                          
965                               DBusResultCode *result)
966
967 {
968   dbus_int32_t serial;
969
970   dbus_mutex_lock (connection->mutex);
971
972   if (!_dbus_list_prepend (&connection->outgoing_messages,
973                            message))
974     {
975       dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
976       dbus_mutex_unlock (connection->mutex);
977       return FALSE;
978     }
979
980   dbus_message_ref (message);
981   connection->n_outgoing += 1;
982
983   _dbus_verbose ("Message %p added to outgoing queue, %d pending to send\n",
984                  message, connection->n_outgoing);
985
986   if (_dbus_message_get_client_serial (message) == -1)
987     {
988       serial = _dbus_connection_get_next_client_serial (connection);
989       _dbus_message_set_client_serial (message, serial);
990     }
991   
992   if (client_serial)
993     *client_serial = _dbus_message_get_client_serial (message);
994   
995   _dbus_message_lock (message);
996
997   if (connection->n_outgoing == 1)
998     _dbus_transport_messages_pending (connection->transport,
999                                       connection->n_outgoing);
1000
1001   dbus_mutex_unlock (connection->mutex);
1002   
1003   return TRUE;
1004 }
1005
1006 static void
1007 reply_handler_timeout (void *data)
1008 {
1009   DBusConnection *connection;
1010   ReplyHandlerData *reply_handler_data = data;
1011
1012   connection = reply_handler_data->connection;
1013   
1014   dbus_mutex_lock (connection->mutex);
1015   if (reply_handler_data->timeout_link)
1016     {
1017       _dbus_connection_queue_synthesized_message_link (connection,
1018                                                        reply_handler_data->timeout_link);
1019       reply_handler_data->timeout_link = NULL;
1020     }
1021
1022   _dbus_connection_remove_timeout (connection,
1023                                    reply_handler_data->timeout);
1024   reply_handler_data->timeout_added = FALSE;
1025   
1026   dbus_mutex_unlock (connection->mutex);
1027 }
1028
1029 static void
1030 reply_handler_data_free (ReplyHandlerData *data)
1031 {
1032   if (!data)
1033     return;
1034
1035   if (data->timeout_added)
1036     _dbus_connection_remove_timeout_locked (data->connection,
1037                                             data->timeout);
1038
1039   if (data->connection_added)
1040     _dbus_message_handler_remove_connection (data->handler,
1041                                              data->connection);
1042
1043   if (data->timeout_link)
1044     {
1045       dbus_message_unref ((DBusMessage *)data->timeout_link->data);
1046       _dbus_list_free_link (data->timeout_link);
1047     }
1048   
1049   dbus_message_handler_unref (data->handler);
1050   
1051   dbus_free (data);
1052 }
1053
1054 /**
1055  * Queues a message to send, as with dbus_connection_send_message(),
1056  * but also sets up a DBusMessageHandler to receive a reply to the
1057  * message. If no reply is received in the given timeout_milliseconds,
1058  * expires the pending reply and sends the DBusMessageHandler a
1059  * synthetic error reply (generated in-process, not by the remote
1060  * application) indicating that a timeout occurred.
1061  *
1062  * Reply handlers see their replies after message filters see them,
1063  * but before message handlers added with
1064  * dbus_connection_register_handler() see them, regardless of the
1065  * reply message's name. Reply handlers are only handed a single
1066  * message as a reply, after one reply has been seen the handler is
1067  * removed. If a filter filters out the reply before the handler sees
1068  * it, the reply is immediately timed out and a timeout error reply is
1069  * generated. If a filter removes the timeout error reply then the
1070  * reply handler will never be called. Filters should not do this.
1071  * 
1072  * If #NULL is passed for the reply_handler, the timeout reply will
1073  * still be generated and placed into the message queue, but no
1074  * specific message handler will receive the reply.
1075  *
1076  * If -1 is passed for the timeout, a sane default timeout is used. -1
1077  * is typically the best value for the timeout for this reason, unless
1078  * you want a very short or very long timeout.  There is no way to
1079  * avoid a timeout entirely, other than passing INT_MAX for the
1080  * timeout to postpone it indefinitely.
1081  * 
1082  * @param connection the connection
1083  * @param message the message to send
1084  * @param reply_handler message handler expecting the reply, or #NULL
1085  * @param timeout_milliseconds timeout in milliseconds or -1 for default
1086  * @param result return location for result code
1087  * @returns #TRUE if the message is successfully queued, #FALSE if no memory.
1088  *
1089  * @todo this function isn't implemented because we need message serials
1090  * and other slightly more rich DBusMessage implementation in order to
1091  * implement it. The basic idea will be to keep a hash of serials we're
1092  * expecting a reply to, and also to add a way to tell GLib or Qt to
1093  * install a timeout. Then install a timeout which is the shortest
1094  * timeout of any pending reply.
1095  *
1096  */
1097 dbus_bool_t
1098 dbus_connection_send_message_with_reply (DBusConnection     *connection,
1099                                          DBusMessage        *message,
1100                                          DBusMessageHandler *reply_handler,
1101                                          int                 timeout_milliseconds,
1102                                          DBusResultCode     *result)
1103 {
1104   DBusTimeout *timeout;
1105   ReplyHandlerData *data;
1106   DBusMessage *reply;
1107   DBusList *reply_link;
1108   dbus_int32_t serial = -1;
1109   
1110   if (timeout_milliseconds == -1)
1111     timeout_milliseconds = DEFAULT_TIMEOUT_VALUE;
1112
1113   data = dbus_new0 (ReplyHandlerData, 1);
1114
1115   if (!data)
1116     {
1117       dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
1118       return FALSE;
1119     }
1120   
1121   timeout = _dbus_timeout_new (timeout_milliseconds, reply_handler_timeout,
1122                                data, NULL);
1123
1124   if (!timeout)
1125     {
1126       reply_handler_data_free (data);
1127       dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
1128       return FALSE;
1129     }
1130
1131   dbus_mutex_lock (connection->mutex);
1132   
1133   /* Add timeout */
1134   if (!_dbus_connection_add_timeout (connection, timeout))
1135     {
1136       reply_handler_data_free (data);
1137       _dbus_timeout_unref (timeout);
1138       dbus_mutex_unlock (connection->mutex);
1139       
1140       dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
1141       return FALSE;
1142     }
1143
1144   /* The connection now owns the reference to the timeout. */
1145   _dbus_timeout_unref (timeout);
1146   
1147   data->timeout_added = TRUE;
1148   data->timeout = timeout;
1149   data->connection = connection;
1150   
1151   if (!_dbus_message_handler_add_connection (reply_handler, connection))
1152     {
1153       dbus_mutex_unlock (connection->mutex);
1154       reply_handler_data_free (data);
1155       
1156       dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
1157       return FALSE;
1158     }
1159   data->connection_added = TRUE;
1160   
1161   /* Assign a serial to the message */
1162   if (_dbus_message_get_client_serial (message) == -1)
1163     {
1164       serial = _dbus_connection_get_next_client_serial (connection);
1165       _dbus_message_set_client_serial (message, serial);
1166     }
1167
1168   data->handler = reply_handler;
1169   data->serial = serial;
1170
1171   dbus_message_handler_ref (reply_handler);
1172
1173   reply = dbus_message_new_error_reply (message, DBUS_ERROR_NO_REPLY,
1174                                         "No reply within specified time");
1175   if (!reply)
1176     {
1177       dbus_mutex_unlock (connection->mutex);
1178       reply_handler_data_free (data);
1179       
1180       dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
1181       return FALSE;
1182     }
1183
1184   reply_link = _dbus_list_alloc_link (reply);
1185   if (!reply)
1186     {
1187       dbus_mutex_unlock (connection->mutex);
1188       dbus_message_unref (reply);
1189       reply_handler_data_free (data);
1190       
1191       dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
1192       return FALSE;
1193     }
1194
1195   data->timeout_link = reply_link;
1196   
1197   /* Insert the serial in the pending replies hash. */
1198   if (!_dbus_hash_table_insert_int (connection->pending_replies, serial, data))
1199     {
1200       dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
1201       dbus_mutex_unlock (connection->mutex);
1202       reply_handler_data_free (data);
1203       
1204       return FALSE;
1205     }
1206
1207   dbus_mutex_unlock (connection->mutex);
1208   
1209   if (!dbus_connection_send_message (connection, message, NULL, result))
1210     {
1211       /* This will free the handler data too */
1212       _dbus_hash_table_remove_int (connection->pending_replies, serial);
1213       return FALSE;
1214     }
1215
1216   dbus_set_result (result, DBUS_RESULT_SUCCESS);  
1217   return TRUE;
1218 }
1219
1220 /**
1221  * Sends a message and blocks a certain time period while waiting for a reply.
1222  * This function does not dispatch any message handlers until the main loop
1223  * has been reached. This function is used to do non-reentrant "method calls."
1224  * If a reply is received, it is returned, and removed from the incoming
1225  * message queue. If it is not received, #NULL is returned and the
1226  * result is set to #DBUS_RESULT_NO_REPLY. If something else goes
1227  * wrong, result is set to whatever is appropriate, such as
1228  * #DBUS_RESULT_NO_MEMORY.
1229  *
1230  * @todo I believe if we get EINTR or otherwise interrupt the
1231  * do_iteration call in here, we won't block the required length of
1232  * time. I think there probably has to be a loop: "while (!timeout_elapsed)
1233  * { check_for_reply_in_queue(); iterate_with_remaining_timeout(); }"
1234  *
1235  * @param connection the connection
1236  * @param message the message to send
1237  * @param timeout_milliseconds timeout in milliseconds or -1 for default
1238  * @param result return location for result code
1239  * @returns the message that is the reply or #NULL with an error code if the
1240  * function fails.
1241  */
1242 DBusMessage *
1243 dbus_connection_send_message_with_reply_and_block (DBusConnection     *connection,
1244                                                    DBusMessage        *message,
1245                                                    int                 timeout_milliseconds,
1246                                                    DBusResultCode     *result)
1247 {
1248   dbus_int32_t client_serial;
1249   DBusList *link;
1250
1251   if (timeout_milliseconds == -1)
1252     timeout_milliseconds = DEFAULT_TIMEOUT_VALUE;
1253   
1254   if (!dbus_connection_send_message (connection, message, &client_serial, result))
1255     return NULL;
1256
1257   /* Flush message queue */
1258   dbus_connection_flush (connection);
1259
1260   dbus_mutex_lock (connection->mutex);
1261   
1262   /* Now we wait... */
1263   /* THREAD TODO: This is busted. What if a dispatch_message or pop_message
1264    * gets the message before we do?
1265    */
1266   _dbus_connection_do_iteration (connection,
1267                                  DBUS_ITERATION_DO_READING |
1268                                  DBUS_ITERATION_BLOCK,
1269                                  timeout_milliseconds);
1270
1271   /* Check if we've gotten a reply */
1272   link = _dbus_list_get_first_link (&connection->incoming_messages);
1273
1274   while (link != NULL)
1275     {
1276       DBusMessage *reply = link->data;
1277
1278       if (_dbus_message_get_reply_serial (reply) == client_serial)
1279         {
1280           _dbus_list_remove (&connection->incoming_messages, link);
1281           dbus_message_ref (message);
1282
1283           if (result)
1284             *result = DBUS_RESULT_SUCCESS;
1285           
1286           dbus_mutex_unlock (connection->mutex);
1287           return reply;
1288         }
1289       link = _dbus_list_get_next_link (&connection->incoming_messages, link);
1290     }
1291
1292   if (result)
1293     *result = DBUS_RESULT_NO_REPLY;
1294
1295   dbus_mutex_unlock (connection->mutex);
1296
1297   return NULL;
1298 }
1299
1300 /**
1301  * Blocks until the outgoing message queue is empty.
1302  *
1303  * @param connection the connection.
1304  */
1305 void
1306 dbus_connection_flush (DBusConnection *connection)
1307 {
1308   dbus_mutex_lock (connection->mutex);
1309   while (connection->n_outgoing > 0)
1310     _dbus_connection_do_iteration (connection,
1311                                    DBUS_ITERATION_DO_WRITING |
1312                                    DBUS_ITERATION_BLOCK,
1313                                    -1);
1314   dbus_mutex_unlock (connection->mutex);
1315 }
1316
1317 /**
1318  * Gets the number of messages in the incoming message queue.
1319  *
1320  * @param connection the connection.
1321  * @returns the number of messages in the queue.
1322  */
1323 int
1324 dbus_connection_get_n_messages (DBusConnection *connection)
1325 {
1326   int res;
1327
1328   dbus_mutex_lock (connection->mutex);
1329   res = connection->n_incoming;
1330   dbus_mutex_unlock (connection->mutex);
1331   return res;
1332 }
1333
1334
1335 /* Call with mutex held. Will drop it while waiting and re-acquire
1336  * before returning
1337  */
1338 static void
1339 _dbus_connection_wait_for_borrowed (DBusConnection *connection)
1340 {
1341   _dbus_assert (connection->message_borrowed != NULL);
1342
1343   while (connection->message_borrowed != NULL)
1344     dbus_condvar_wait (connection->message_returned_cond, connection->mutex);
1345 }
1346
1347 /**
1348  * Returns the first-received message from the incoming message queue,
1349  * leaving it in the queue. If the queue is empty, returns #NULL.
1350  * 
1351  * The caller does not own a reference to the returned message, and must
1352  * either return it using dbus_connection_return_message or keep it after
1353  * calling dbus_connection_steal_borrowed_message. No one can get at the
1354  * message while its borrowed, so return it as quickly as possible and
1355  * don't keep a reference to it after returning it. If you need to keep
1356  * the message, make a copy of it.
1357  *
1358  * @param connection the connection.
1359  * @returns next message in the incoming queue.
1360  */
1361 DBusMessage*
1362 dbus_connection_borrow_message  (DBusConnection *connection)
1363 {
1364   DBusMessage *message;
1365
1366   dbus_mutex_lock (connection->mutex);
1367
1368   if (connection->message_borrowed != NULL)
1369     _dbus_connection_wait_for_borrowed (connection);
1370   
1371   message = _dbus_list_get_first (&connection->incoming_messages);
1372
1373   if (message) 
1374     connection->message_borrowed = message;
1375   
1376   dbus_mutex_unlock (connection->mutex);
1377   return message;
1378 }
1379
1380 /**
1381  * @todo docs
1382  */
1383 void
1384 dbus_connection_return_message (DBusConnection *connection,
1385                                 DBusMessage    *message)
1386 {
1387   dbus_mutex_lock (connection->mutex);
1388   
1389   _dbus_assert (message == connection->message_borrowed);
1390   
1391   connection->message_borrowed = NULL;
1392   dbus_condvar_wake_all (connection->message_returned_cond);
1393   
1394   dbus_mutex_unlock (connection->mutex);
1395 }
1396
1397 /**
1398  * @todo docs
1399  */
1400 void
1401 dbus_connection_steal_borrowed_message (DBusConnection *connection,
1402                                         DBusMessage    *message)
1403 {
1404   DBusMessage *pop_message;
1405   
1406   dbus_mutex_lock (connection->mutex);
1407  
1408   _dbus_assert (message == connection->message_borrowed);
1409
1410   pop_message = _dbus_list_pop_first (&connection->incoming_messages);
1411   _dbus_assert (message == pop_message);
1412   
1413   connection->n_incoming -= 1;
1414  
1415   _dbus_verbose ("Incoming message %p stolen from queue, %d incoming\n",
1416                  message, connection->n_incoming);
1417  
1418   connection->message_borrowed = NULL;
1419   dbus_condvar_wake_all (connection->message_returned_cond);
1420   
1421   dbus_mutex_unlock (connection->mutex);
1422 }
1423
1424
1425 /* See dbus_connection_pop_message, but requires the caller to own
1426  * the lock before calling. May drop the lock while running.
1427  */
1428 static DBusMessage*
1429 _dbus_connection_pop_message_unlocked (DBusConnection *connection)
1430 {
1431   if (connection->message_borrowed != NULL)
1432     _dbus_connection_wait_for_borrowed (connection);
1433   
1434   if (connection->n_incoming > 0)
1435     {
1436       DBusMessage *message;
1437
1438       message = _dbus_list_pop_first (&connection->incoming_messages);
1439       connection->n_incoming -= 1;
1440
1441       _dbus_verbose ("Incoming message %p removed from queue, %d incoming\n",
1442                      message, connection->n_incoming);
1443
1444       return message;
1445     }
1446   else
1447     return NULL;
1448 }
1449
1450
1451 /**
1452  * Returns the first-received message from the incoming message queue,
1453  * removing it from the queue. The caller owns a reference to the
1454  * returned message. If the queue is empty, returns #NULL.
1455  *
1456  * @param connection the connection.
1457  * @returns next message in the incoming queue.
1458  */
1459 DBusMessage*
1460 dbus_connection_pop_message (DBusConnection *connection)
1461 {
1462   DBusMessage *message;
1463   dbus_mutex_lock (connection->mutex);
1464
1465   message = _dbus_connection_pop_message_unlocked (connection);
1466   
1467   dbus_mutex_unlock (connection->mutex);
1468   
1469   return message;
1470 }
1471
1472 /**
1473  * Acquire the dispatcher. This must be done before dispatching
1474  * messages in order to guarantee the right order of
1475  * message delivery. May sleep and drop the connection mutex
1476  * while waiting for the dispatcher.
1477  *
1478  * @param connection the connection.
1479  */
1480 static void
1481 _dbus_connection_acquire_dispatch (DBusConnection *connection)
1482 {
1483   dbus_condvar_wait (connection->dispatch_cond, connection->mutex);
1484   _dbus_assert (!connection->dispatch_acquired);
1485
1486   connection->dispatch_acquired = TRUE;
1487 }
1488
1489 /**
1490  * Release the dispatcher when you're done with it. Only call
1491  * after you've acquired the dispatcher. Wakes up at most one
1492  * thread currently waiting to acquire the dispatcher.
1493  *
1494  * @param connection the connection.
1495  */
1496 static void
1497 _dbus_connection_release_dispatch (DBusConnection *connection)
1498 {
1499   _dbus_assert (connection->dispatch_acquired);
1500
1501   connection->dispatch_acquired = FALSE;
1502   dbus_condvar_wake_one (connection->dispatch_cond);
1503 }
1504
1505 static void
1506 _dbus_connection_failed_pop (DBusConnection *connection,
1507                              DBusList *message_link)
1508 {
1509   _dbus_list_prepend_link (&connection->incoming_messages,
1510                            message_link);
1511   connection->n_incoming += 1;
1512 }
1513
1514 /**
1515  * Pops the first-received message from the current incoming message
1516  * queue, runs any handlers for it, then unrefs the message.
1517  *
1518  * @param connection the connection
1519  * @returns #TRUE if the queue is not empty after dispatch
1520  */
1521 dbus_bool_t
1522 dbus_connection_dispatch_message (DBusConnection *connection)
1523 {
1524   DBusMessageHandler *handler;
1525   DBusMessage *message;
1526   DBusList *link, *filter_list_copy, *message_link;
1527   DBusHandlerResult result;
1528   ReplyHandlerData *reply_handler_data;
1529   const char *name;
1530   dbus_int32_t reply_serial;
1531
1532   /* Preallocate link so we can put the message back on failure */
1533   message_link = _dbus_list_alloc_link (NULL);
1534   if (message_link == NULL)
1535     return FALSE;
1536   
1537   dbus_mutex_lock (connection->mutex);
1538
1539   /* We need to ref the connection since the callback could potentially
1540    * drop the last ref to it */
1541   _dbus_connection_ref_unlocked (connection);
1542
1543   _dbus_connection_acquire_dispatch (connection);
1544   
1545   /* This call may drop the lock during the execution (if waiting for
1546    * borrowed messages to be returned) but the order of message
1547    * dispatch if several threads call dispatch_message is still
1548    * protected by the lock, since only one will get the lock, and that
1549    * one will finish the message dispatching
1550    */
1551   message = _dbus_connection_pop_message_unlocked (connection);
1552   if (message == NULL)
1553     {
1554       _dbus_connection_release_dispatch (connection);
1555       dbus_mutex_unlock (connection->mutex);
1556       dbus_connection_unref (connection);
1557       return FALSE;
1558     }
1559   
1560   message_link->data = message;
1561   
1562   result = DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
1563
1564   reply_serial = _dbus_message_get_reply_serial (message);
1565   reply_handler_data = _dbus_hash_table_lookup_int (connection->pending_replies,
1566                                                     reply_serial);
1567   
1568   if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
1569     {
1570       _dbus_connection_release_dispatch (connection);
1571       dbus_mutex_unlock (connection->mutex);
1572       _dbus_connection_failed_pop (connection, message_link);
1573       dbus_connection_unref (connection);
1574       return FALSE;
1575     }
1576   
1577   _dbus_list_foreach (&filter_list_copy,
1578                       (DBusForeachFunction)dbus_message_handler_ref,
1579                       NULL);
1580
1581   /* We're still protected from dispatch_message reentrancy here
1582    * since we acquired the dispatcher
1583    */
1584   dbus_mutex_unlock (connection->mutex);
1585   
1586   link = _dbus_list_get_first_link (&filter_list_copy);
1587   while (link != NULL)
1588     {
1589       DBusMessageHandler *handler = link->data;
1590       DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
1591
1592       result = _dbus_message_handler_handle_message (handler, connection,
1593                                                      message);
1594
1595       if (result == DBUS_HANDLER_RESULT_REMOVE_MESSAGE)
1596         break;
1597
1598       link = next;
1599     }
1600
1601   _dbus_list_foreach (&filter_list_copy,
1602                       (DBusForeachFunction)dbus_message_handler_unref,
1603                       NULL);
1604   _dbus_list_clear (&filter_list_copy);
1605   
1606   dbus_mutex_lock (connection->mutex);
1607
1608   /* Did a reply we were waiting on get filtered? */
1609   if (reply_handler_data && result == DBUS_HANDLER_RESULT_REMOVE_MESSAGE)
1610     {
1611       /* Queue the timeout immediately! */
1612       if (reply_handler_data->timeout_link)
1613         {
1614           _dbus_connection_queue_synthesized_message_link (connection,
1615                                                            reply_handler_data->timeout_link);
1616           reply_handler_data->timeout_link = NULL;
1617         }
1618       else
1619         {
1620           /* We already queued the timeout? Then it was filtered! */
1621           _dbus_warn ("The timeout error with reply serial %d was filtered, so the reply handler will never be called.\n", reply_serial);
1622         }
1623     }
1624   
1625   if (result == DBUS_HANDLER_RESULT_REMOVE_MESSAGE)
1626     goto out;
1627
1628   if (reply_handler_data)
1629     {
1630       dbus_mutex_unlock (connection->mutex);
1631       result = _dbus_message_handler_handle_message (reply_handler_data->handler,
1632                                                      connection, message);
1633       reply_handler_data_free (reply_handler_data);
1634       dbus_mutex_lock (connection->mutex);
1635       goto out;
1636     }
1637   
1638   name = dbus_message_get_name (message);
1639   if (name != NULL)
1640     {
1641       handler = _dbus_hash_table_lookup_string (connection->handler_table,
1642                                                 name);
1643       if (handler != NULL)
1644         {
1645           /* We're still protected from dispatch_message reentrancy here
1646            * since we acquired the dispatcher */
1647           dbus_mutex_unlock (connection->mutex);
1648           result = _dbus_message_handler_handle_message (handler, connection,
1649                                                          message);
1650           dbus_mutex_lock (connection->mutex);
1651           if (result == DBUS_HANDLER_RESULT_REMOVE_MESSAGE)
1652             goto out;
1653         }
1654     }
1655
1656  out:
1657   _dbus_connection_release_dispatch (connection);
1658   dbus_mutex_unlock (connection->mutex);
1659   _dbus_list_free_link (message_link);
1660   dbus_connection_unref (connection);
1661   dbus_message_unref (message);
1662   
1663   return connection->n_incoming > 0;
1664 }
1665
1666 /**
1667  * Sets the watch functions for the connection. These functions are
1668  * responsible for making the application's main loop aware of file
1669  * descriptors that need to be monitored for events, using select() or
1670  * poll(). When using Qt, typically the DBusAddWatchFunction would
1671  * create a QSocketNotifier. When using GLib, the DBusAddWatchFunction
1672  * could call g_io_add_watch(), or could be used as part of a more
1673  * elaborate GSource.
1674  *
1675  * The DBusWatch can be queried for the file descriptor to watch using
1676  * dbus_watch_get_fd(), and for the events to watch for using
1677  * dbus_watch_get_flags(). The flags returned by
1678  * dbus_watch_get_flags() will only contain DBUS_WATCH_READABLE and
1679  * DBUS_WATCH_WRITABLE, never DBUS_WATCH_HANGUP or DBUS_WATCH_ERROR;
1680  * all watches implicitly include a watch for hangups, errors, and
1681  * other exceptional conditions.
1682  *
1683  * Once a file descriptor becomes readable or writable, or an exception
1684  * occurs, dbus_connection_handle_watch() should be called to
1685  * notify the connection of the file descriptor's condition.
1686  *
1687  * dbus_connection_handle_watch() cannot be called during the
1688  * DBusAddWatchFunction, as the connection will not be ready to handle
1689  * that watch yet.
1690  * 
1691  * It is not allowed to reference a DBusWatch after it has been passed
1692  * to remove_function.
1693  * 
1694  * @param connection the connection.
1695  * @param add_function function to begin monitoring a new descriptor.
1696  * @param remove_function function to stop monitoring a descriptor.
1697  * @param data data to pass to add_function and remove_function.
1698  * @param free_data_function function to be called to free the data.
1699  */
1700 void
1701 dbus_connection_set_watch_functions (DBusConnection              *connection,
1702                                      DBusAddWatchFunction         add_function,
1703                                      DBusRemoveWatchFunction      remove_function,
1704                                      void                        *data,
1705                                      DBusFreeFunction             free_data_function)
1706 {
1707   dbus_mutex_lock (connection->mutex);
1708   /* ref connection for slightly better reentrancy */
1709   _dbus_connection_ref_unlocked (connection);
1710   
1711   _dbus_watch_list_set_functions (connection->watches,
1712                                   add_function, remove_function,
1713                                   data, free_data_function);
1714   
1715   dbus_mutex_unlock (connection->mutex);
1716   /* drop our paranoid refcount */
1717   dbus_connection_unref (connection);
1718 }
1719
1720 /**
1721  * Sets the timeout functions for the connection. These functions are
1722  * responsible for making the application's main loop aware of timeouts.
1723  * When using Qt, typically the DBusAddTimeoutFunction would create a
1724  * QTimer. When using GLib, the DBusAddTimeoutFunction would call
1725  * g_timeout_add.
1726  *
1727  * The DBusTimeout can be queried for the timer interval using
1728  * dbus_timeout_get_interval.
1729  *
1730  * Once a timeout occurs, dbus_timeout_handle should be called to invoke
1731  * the timeout's callback.
1732  *
1733  * @param connection the connection.
1734  * @param add_function function to add a timeout.
1735  * @param remove_function function to remove a timeout.
1736  * @param data data to pass to add_function and remove_function.
1737  * @param free_data_function function to be called to free the data.
1738  */
1739 void
1740 dbus_connection_set_timeout_functions   (DBusConnection            *connection,
1741                                          DBusAddTimeoutFunction     add_function,
1742                                          DBusRemoveTimeoutFunction  remove_function,
1743                                          void                      *data,
1744                                          DBusFreeFunction           free_data_function)
1745 {
1746   dbus_mutex_lock (connection->mutex);
1747   /* ref connection for slightly better reentrancy */
1748   _dbus_connection_ref_unlocked (connection);
1749   
1750   _dbus_timeout_list_set_functions (connection->timeouts,
1751                                     add_function, remove_function,
1752                                     data, free_data_function);
1753   
1754   dbus_mutex_unlock (connection->mutex);
1755   /* drop our paranoid refcount */
1756   dbus_connection_unref (connection);  
1757 }
1758
1759 /**
1760  * Called to notify the connection when a previously-added watch
1761  * is ready for reading or writing, or has an exception such
1762  * as a hangup.
1763  *
1764  * @param connection the connection.
1765  * @param watch the watch.
1766  * @param condition the current condition of the file descriptors being watched.
1767  */
1768 void
1769 dbus_connection_handle_watch (DBusConnection              *connection,
1770                               DBusWatch                   *watch,
1771                               unsigned int                 condition)
1772 {
1773   dbus_mutex_lock (connection->mutex);
1774   _dbus_connection_acquire_io_path (connection, -1);
1775   _dbus_transport_handle_watch (connection->transport,
1776                                 watch, condition);
1777   _dbus_connection_release_io_path (connection);
1778   dbus_mutex_unlock (connection->mutex);
1779 }
1780
1781 /**
1782  * Adds a message filter. Filters are handlers that are run on
1783  * all incoming messages, prior to the normal handlers
1784  * registered with dbus_connection_register_handler().
1785  * Filters are run in the order that they were added.
1786  * The same handler can be added as a filter more than once, in
1787  * which case it will be run more than once.
1788  * Filters added during a filter callback won't be run on the
1789  * message being processed.
1790  *
1791  * @param connection the connection
1792  * @param handler the handler
1793  * @returns #TRUE on success, #FALSE if not enough memory.
1794  */
1795 dbus_bool_t
1796 dbus_connection_add_filter (DBusConnection      *connection,
1797                             DBusMessageHandler  *handler)
1798 {
1799   dbus_mutex_lock (connection->mutex);
1800   if (!_dbus_message_handler_add_connection (handler, connection))
1801     {
1802       dbus_mutex_unlock (connection->mutex);
1803       return FALSE;
1804     }
1805
1806   if (!_dbus_list_append (&connection->filter_list,
1807                           handler))
1808     {
1809       _dbus_message_handler_remove_connection (handler, connection);
1810       dbus_mutex_unlock (connection->mutex);
1811       return FALSE;
1812     }
1813
1814   dbus_mutex_unlock (connection->mutex);
1815   return TRUE;
1816 }
1817
1818 /**
1819  * Removes a previously-added message filter. It is a programming
1820  * error to call this function for a handler that has not
1821  * been added as a filter. If the given handler was added
1822  * more than once, only one instance of it will be removed
1823  * (the most recently-added instance).
1824  *
1825  * @param connection the connection
1826  * @param handler the handler to remove
1827  *
1828  */
1829 void
1830 dbus_connection_remove_filter (DBusConnection      *connection,
1831                                DBusMessageHandler  *handler)
1832 {
1833   dbus_mutex_lock (connection->mutex);
1834   if (!_dbus_list_remove_last (&connection->filter_list, handler))
1835     {
1836       _dbus_warn ("Tried to remove a DBusConnection filter that had not been added\n");
1837       dbus_mutex_unlock (connection->mutex);
1838       return;
1839     }
1840
1841   _dbus_message_handler_remove_connection (handler, connection);
1842
1843   dbus_mutex_unlock (connection->mutex);
1844 }
1845
1846 /**
1847  * Registers a handler for a list of message names. A single handler
1848  * can be registered for any number of message names, but each message
1849  * name can only have one handler at a time. It's not allowed to call
1850  * this function with the name of a message that already has a
1851  * handler. If the function returns #FALSE, the handlers were not
1852  * registered due to lack of memory.
1853  * 
1854  * @param connection the connection
1855  * @param handler the handler
1856  * @param messages_to_handle the messages to handle
1857  * @param n_messages the number of message names in messages_to_handle
1858  * @returns #TRUE on success, #FALSE if no memory or another handler already exists
1859  * 
1860  **/
1861 dbus_bool_t
1862 dbus_connection_register_handler (DBusConnection     *connection,
1863                                   DBusMessageHandler *handler,
1864                                   const char        **messages_to_handle,
1865                                   int                 n_messages)
1866 {
1867   int i;
1868
1869   dbus_mutex_lock (connection->mutex);
1870   i = 0;
1871   while (i < n_messages)
1872     {
1873       DBusHashIter iter;
1874       char *key;
1875
1876       key = _dbus_strdup (messages_to_handle[i]);
1877       if (key == NULL)
1878         goto failed;
1879       
1880       if (!_dbus_hash_iter_lookup (connection->handler_table,
1881                                    key, TRUE,
1882                                    &iter))
1883         {
1884           dbus_free (key);
1885           goto failed;
1886         }
1887
1888       if (_dbus_hash_iter_get_value (&iter) != NULL)
1889         {
1890           _dbus_warn ("Bug in application: attempted to register a second handler for %s\n",
1891                       messages_to_handle[i]);
1892           dbus_free (key); /* won't have replaced the old key with the new one */
1893           goto failed;
1894         }
1895
1896       if (!_dbus_message_handler_add_connection (handler, connection))
1897         {
1898           _dbus_hash_iter_remove_entry (&iter);
1899           /* key has freed on nuking the entry */
1900           goto failed;
1901         }
1902       
1903       _dbus_hash_iter_set_value (&iter, handler);
1904
1905       ++i;
1906     }
1907   
1908   dbus_mutex_unlock (connection->mutex);
1909   return TRUE;
1910   
1911  failed:
1912   /* unregister everything registered so far,
1913    * so we don't fail partially
1914    */
1915   dbus_connection_unregister_handler (connection,
1916                                       handler,
1917                                       messages_to_handle,
1918                                       i);
1919
1920   dbus_mutex_unlock (connection->mutex);
1921   return FALSE;
1922 }
1923
1924 /**
1925  * Unregisters a handler for a list of message names. The handlers
1926  * must have been previously registered.
1927  *
1928  * @param connection the connection
1929  * @param handler the handler
1930  * @param messages_to_handle the messages to handle
1931  * @param n_messages the number of message names in messages_to_handle
1932  * 
1933  **/
1934 void
1935 dbus_connection_unregister_handler (DBusConnection     *connection,
1936                                     DBusMessageHandler *handler,
1937                                     const char        **messages_to_handle,
1938                                     int                 n_messages)
1939 {
1940   int i;
1941
1942   dbus_mutex_lock (connection->mutex);
1943   i = 0;
1944   while (i < n_messages)
1945     {
1946       DBusHashIter iter;
1947
1948       if (!_dbus_hash_iter_lookup (connection->handler_table,
1949                                    (char*) messages_to_handle[i], FALSE,
1950                                    &iter))
1951         {
1952           _dbus_warn ("Bug in application: attempted to unregister handler for %s which was not registered\n",
1953                       messages_to_handle[i]);
1954         }
1955       else if (_dbus_hash_iter_get_value (&iter) != handler)
1956         {
1957           _dbus_warn ("Bug in application: attempted to unregister handler for %s which was registered by a different handler\n",
1958                       messages_to_handle[i]);
1959         }
1960       else
1961         {
1962           _dbus_hash_iter_remove_entry (&iter);
1963           _dbus_message_handler_remove_connection (handler, connection);
1964         }
1965
1966       ++i;
1967     }
1968
1969   dbus_mutex_unlock (connection->mutex);
1970 }
1971
1972 static int *allocated_slots = NULL;
1973 static int  n_allocated_slots = 0;
1974 static int  n_used_slots = 0;
1975 static DBusMutex *allocated_slots_lock = NULL;
1976
1977 /**
1978  * Initialize the mutex used for #DBusConnecton data
1979  * slot reservations.
1980  *
1981  * @returns the mutex
1982  */
1983 DBusMutex *
1984 _dbus_allocated_slots_init_lock (void)
1985 {
1986   allocated_slots_lock = dbus_mutex_new ();
1987   return allocated_slots_lock;
1988 }
1989
1990
1991 /**
1992  * Allocates an integer ID to be used for storing application-specific
1993  * data on any DBusConnection. The allocated ID may then be used
1994  * with dbus_connection_set_data() and dbus_connection_get_data().
1995  * If allocation fails, -1 is returned. Again, the allocated
1996  * slot is global, i.e. all DBusConnection objects will
1997  * have a slot with the given integer ID reserved.
1998  *
1999  * @returns -1 on failure, otherwise the data slot ID
2000  */
2001 int
2002 dbus_connection_allocate_data_slot (void)
2003 {
2004   int slot;
2005   
2006   if (!dbus_mutex_lock (allocated_slots_lock))
2007     return -1;
2008
2009   if (n_used_slots < n_allocated_slots)
2010     {
2011       slot = 0;
2012       while (slot < n_allocated_slots)
2013         {
2014           if (allocated_slots[slot] < 0)
2015             {
2016               allocated_slots[slot] = slot;
2017               n_used_slots += 1;
2018               break;
2019             }
2020           ++slot;
2021         }
2022
2023       _dbus_assert (slot < n_allocated_slots);
2024     }
2025   else
2026     {
2027       int *tmp;
2028       
2029       slot = -1;
2030       tmp = dbus_realloc (allocated_slots,
2031                           sizeof (int) * (n_allocated_slots + 1));
2032       if (tmp == NULL)
2033         goto out;
2034
2035       allocated_slots = tmp;
2036       slot = n_allocated_slots;
2037       n_allocated_slots += 1;
2038       n_used_slots += 1;
2039       allocated_slots[slot] = slot;
2040     }
2041
2042   _dbus_assert (slot >= 0);
2043   _dbus_assert (slot < n_allocated_slots);
2044   
2045  out:
2046   dbus_mutex_unlock (allocated_slots_lock);
2047   return slot;
2048 }
2049
2050 /**
2051  * Deallocates a global ID for connection data slots.
2052  * dbus_connection_get_data() and dbus_connection_set_data()
2053  * may no longer be used with this slot.
2054  * Existing data stored on existing DBusConnection objects
2055  * will be freed when the connection is finalized,
2056  * but may not be retrieved (and may only be replaced
2057  * if someone else reallocates the slot).
2058  *
2059  * @param slot the slot to deallocate
2060  */
2061 void
2062 dbus_connection_free_data_slot (int slot)
2063 {
2064   dbus_mutex_lock (allocated_slots_lock);
2065
2066   _dbus_assert (slot < n_allocated_slots);
2067   _dbus_assert (allocated_slots[slot] == slot);
2068   
2069   allocated_slots[slot] = -1;
2070   n_used_slots -= 1;
2071
2072   if (n_used_slots == 0)
2073     {
2074       dbus_free (allocated_slots);
2075       allocated_slots = NULL;
2076       n_allocated_slots = 0;
2077     }
2078   
2079   dbus_mutex_unlock (allocated_slots_lock);
2080 }
2081
2082 /**
2083  * Stores a pointer on a DBusConnection, along
2084  * with an optional function to be used for freeing
2085  * the data when the data is set again, or when
2086  * the connection is finalized. The slot number
2087  * must have been allocated with dbus_connection_allocate_data_slot().
2088  *
2089  * @param connection the connection
2090  * @param slot the slot number
2091  * @param data the data to store
2092  * @param free_data_func finalizer function for the data
2093  * @returns #TRUE if there was enough memory to store the data
2094  */
2095 dbus_bool_t
2096 dbus_connection_set_data (DBusConnection   *connection,
2097                           int               slot,
2098                           void             *data,
2099                           DBusFreeFunction  free_data_func)
2100 {
2101   DBusFreeFunction old_free_func;
2102   void *old_data;
2103   
2104   dbus_mutex_lock (connection->mutex);
2105   _dbus_assert (slot < n_allocated_slots);
2106   _dbus_assert (allocated_slots[slot] == slot);
2107   
2108   if (slot >= connection->n_slots)
2109     {
2110       DBusDataSlot *tmp;
2111       int i;
2112       
2113       tmp = dbus_realloc (connection->data_slots,
2114                           sizeof (DBusDataSlot) * (slot + 1));
2115       if (tmp == NULL)
2116         {
2117           dbus_mutex_unlock (connection->mutex);
2118           return FALSE;
2119         }
2120       
2121       connection->data_slots = tmp;
2122       i = connection->n_slots;
2123       connection->n_slots = slot + 1;
2124       while (i < connection->n_slots)
2125         {
2126           connection->data_slots[i].data = NULL;
2127           connection->data_slots[i].free_data_func = NULL;
2128           ++i;
2129         }
2130     }
2131
2132   _dbus_assert (slot < connection->n_slots);
2133
2134   old_data = connection->data_slots[slot].data;
2135   old_free_func = connection->data_slots[slot].free_data_func;
2136
2137   connection->data_slots[slot].data = data;
2138   connection->data_slots[slot].free_data_func = free_data_func;
2139
2140   dbus_mutex_unlock (connection->mutex);
2141
2142   /* Do the actual free outside the connection lock */
2143   if (old_free_func)
2144     (* old_free_func) (old_data);
2145
2146   return TRUE;
2147 }
2148
2149 /**
2150  * Retrieves data previously set with dbus_connection_set_data().
2151  * The slot must still be allocated (must not have been freed).
2152  *
2153  * @param connection the connection
2154  * @param slot the slot to get data from
2155  * @returns the data, or #NULL if not found
2156  */
2157 void*
2158 dbus_connection_get_data (DBusConnection   *connection,
2159                           int               slot)
2160 {
2161   void *res;
2162   
2163   dbus_mutex_lock (connection->mutex);
2164   
2165   _dbus_assert (slot < n_allocated_slots);
2166   _dbus_assert (allocated_slots[slot] == slot);
2167
2168   if (slot >= connection->n_slots)
2169     res = NULL;
2170   else
2171     res = connection->data_slots[slot].data; 
2172
2173   dbus_mutex_unlock (connection->mutex);
2174
2175   return res;
2176 }
2177
2178 /**
2179  * This function sets a global flag for whether dbus_connection_new()
2180  * will set SIGPIPE behavior to SIG_IGN.
2181  *
2182  * @param will_modify_sigpipe #TRUE to allow sigpipe to be set to SIG_IGN
2183  */
2184 void
2185 dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe)
2186 {
2187   _dbus_modify_sigpipe = will_modify_sigpipe;
2188 }
2189
2190 /* This must be called with the connection lock not held to avoid
2191  * holding it over the free_data callbacks, so it can basically
2192  * only be called at last unref
2193  */
2194 static void
2195 _dbus_connection_free_data_slots_nolock (DBusConnection *connection)
2196 {
2197   int i;
2198
2199   i = 0;
2200   while (i < connection->n_slots)
2201     {
2202       if (connection->data_slots[i].free_data_func)
2203         (* connection->data_slots[i].free_data_func) (connection->data_slots[i].data);
2204       connection->data_slots[i].data = NULL;
2205       connection->data_slots[i].free_data_func = NULL;
2206       ++i;
2207     }
2208
2209   dbus_free (connection->data_slots);
2210   connection->data_slots = NULL;
2211   connection->n_slots = 0;
2212 }
2213
2214 /**
2215  * Specifies the maximum size message this connection is allowed to
2216  * receive. Larger messages will result in disconnecting the
2217  * connection.
2218  * 
2219  * @param connection a #DBusConnection
2220  * @param size maximum message size the connection can receive, in bytes
2221  */
2222 void
2223 dbus_connection_set_max_message_size (DBusConnection *connection,
2224                                       long            size)
2225 {
2226   dbus_mutex_lock (connection->mutex);
2227   _dbus_transport_set_max_message_size (connection->transport,
2228                                         size);
2229   dbus_mutex_unlock (connection->mutex);
2230 }
2231
2232 /**
2233  * Gets the value set by dbus_connection_set_max_message_size().
2234  *
2235  * @param connection the connection
2236  * @returns the max size of a single message
2237  */
2238 long
2239 dbus_connection_get_max_message_size (DBusConnection *connection)
2240 {
2241   long res;
2242   dbus_mutex_lock (connection->mutex);
2243   res = _dbus_transport_get_max_message_size (connection->transport);
2244   dbus_mutex_unlock (connection->mutex);
2245   return res;
2246 }
2247
2248 /**
2249  * Sets the maximum total number of bytes that can be used for all messages
2250  * received on this connection. Messages count toward the maximum until
2251  * they are finalized. When the maximum is reached, the connection will
2252  * not read more data until some messages are finalized.
2253  *
2254  * The semantics of the maximum are: if outstanding messages are
2255  * already above the maximum, additional messages will not be read.
2256  * The semantics are not: if the next message would cause us to exceed
2257  * the maximum, we don't read it. The reason is that we don't know the
2258  * size of a message until after we read it.
2259  *
2260  * Thus, the max live messages size can actually be exceeded
2261  * by up to the maximum size of a single message.
2262  * 
2263  * Also, if we read say 1024 bytes off the wire in a single read(),
2264  * and that contains a half-dozen small messages, we may exceed the
2265  * size max by that amount. But this should be inconsequential.
2266  *
2267  * @param connection the connection
2268  * @param size the maximum size in bytes of all outstanding messages
2269  */
2270 void
2271 dbus_connection_set_max_live_messages_size (DBusConnection *connection,
2272                                             long            size)
2273 {
2274   dbus_mutex_lock (connection->mutex);
2275   _dbus_transport_set_max_live_messages_size (connection->transport,
2276                                               size);
2277   dbus_mutex_unlock (connection->mutex);
2278 }
2279
2280 /**
2281  * Gets the value set by dbus_connection_set_max_live_messages_size().
2282  *
2283  * @param connection the connection
2284  * @returns the max size of all live messages
2285  */
2286 long
2287 dbus_connection_get_max_live_messages_size (DBusConnection *connection)
2288 {
2289   long res;
2290   dbus_mutex_lock (connection->mutex);
2291   res = _dbus_transport_get_max_live_messages_size (connection->transport);
2292   dbus_mutex_unlock (connection->mutex);
2293   return res;
2294 }
2295
2296 /** @} */