2003-01-18 Havoc Pennington <hp@pobox.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  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-transport.h"
27 #include "dbus-watch.h"
28 #include "dbus-connection-internal.h"
29 #include "dbus-list.h"
30 #include "dbus-hash.h"
31 #include "dbus-message-internal.h"
32 #include "dbus-threads.h"
33
34 /**
35  * @defgroup DBusConnection DBusConnection
36  * @ingroup  DBus
37  * @brief Connection to another application
38  *
39  * A DBusConnection represents a connection to another
40  * application. Messages can be sent and received via this connection.
41  *
42  * The connection maintains a queue of incoming messages and a queue
43  * of outgoing messages. dbus_connection_pop_message() and friends
44  * can be used to read incoming messages from the queue.
45  * Outgoing messages are automatically discarded as they are
46  * written to the network.
47  *
48  * In brief a DBusConnection is a message queue associated with some
49  * message transport mechanism such as a socket.
50  * 
51  */
52
53 /**
54  * @defgroup DBusConnectionInternals DBusConnection implementation details
55  * @ingroup  DBusInternals
56  * @brief Implementation details of DBusConnection
57  *
58  * @{
59  */
60
61 /** Opaque typedef for DBusDataSlot */
62 typedef struct DBusDataSlot DBusDataSlot;
63 /** DBusDataSlot is used to store application data on the connection */
64 struct DBusDataSlot
65 {
66   void *data;                      /**< The application data */
67   DBusFreeFunction free_data_func; /**< Free the application data */
68 };
69
70 /**
71  * Implementation details of DBusConnection. All fields are private.
72  */
73 struct DBusConnection
74 {
75   int refcount; /**< Reference count. */
76
77   DBusList *outgoing_messages; /**< Queue of messages we need to send, send the end of the list first. */
78   DBusList *incoming_messages; /**< Queue of messages we have received, end of the list received most recently. */
79
80   int n_outgoing;              /**< Length of outgoing queue. */
81   int n_incoming;              /**< Length of incoming queue. */
82   
83   DBusTransport *transport;    /**< Object that sends/receives messages over network. */
84   DBusWatchList *watches;      /**< Stores active watches. */
85   
86   DBusDisconnectFunction disconnect_function;      /**< Callback on disconnect. */
87   void *disconnect_data;                           /**< Data for disconnect callback. */
88   DBusFreeFunction disconnect_free_data_function;  /**< Free function for disconnect callback data. */
89   DBusHashTable *handler_table; /**< Table of registered DBusMessageHandler */
90   DBusList *filter_list;        /**< List of filters. */
91   int filters_serial;           /**< Increments when the list of filters is changed. */
92   int handlers_serial;          /**< Increments when the handler table is changed. */
93   DBusDataSlot *data_slots;        /**< Data slots */
94   int           n_slots; /**< Slots allocated so far. */
95
96   int client_serial;            /**< Client serial. Increments each time a message is sent  */
97   unsigned int disconnect_notified : 1; /**< Already called disconnect_function */
98 };
99
100 static void _dbus_connection_free_data_slots (DBusConnection *connection);
101
102 /**
103  * Adds a message to the incoming message queue, returning #FALSE
104  * if there's insufficient memory to queue the message.
105  *
106  * @param connection the connection.
107  * @param message the message to queue.
108  * @returns #TRUE on success.
109  */
110 dbus_bool_t
111 _dbus_connection_queue_received_message (DBusConnection *connection,
112                                          DBusMessage    *message)
113 {
114   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
115   
116   if (!_dbus_list_append (&connection->incoming_messages,
117                           message))
118     return FALSE;
119   
120   dbus_message_ref (message);
121   connection->n_incoming += 1;
122
123   _dbus_verbose ("Incoming message %p added to queue, %d incoming\n",
124                  message, connection->n_incoming);
125   
126   return TRUE;
127 }
128
129 /**
130  * Checks whether there are messages in the outgoing message queue.
131  *
132  * @param connection the connection.
133  * @returns #TRUE if the outgoing queue is non-empty.
134  */
135 dbus_bool_t
136 _dbus_connection_have_messages_to_send (DBusConnection *connection)
137 {
138   return connection->outgoing_messages != NULL;
139 }
140
141 /**
142  * Gets the next outgoing message. The message remains in the
143  * queue, and the caller does not own a reference to it.
144  *
145  * @param connection the connection.
146  * @returns the message to be sent.
147  */ 
148 DBusMessage*
149 _dbus_connection_get_message_to_send (DBusConnection *connection)
150 {
151   return _dbus_list_get_last (&connection->outgoing_messages);
152 }
153
154 /**
155  * Notifies the connection that a message has been sent, so the
156  * message can be removed from the outgoing queue.
157  *
158  * @param connection the connection.
159  * @param message the message that was sent.
160  */
161 void
162 _dbus_connection_message_sent (DBusConnection *connection,
163                                DBusMessage    *message)
164 {
165   _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
166   _dbus_assert (message == _dbus_list_get_last (&connection->outgoing_messages));
167   
168   _dbus_list_pop_last (&connection->outgoing_messages);
169   dbus_message_unref (message);
170   
171   connection->n_outgoing -= 1;
172
173   _dbus_verbose ("Message %p removed from outgoing queue, %d left to send\n",
174                  message, connection->n_outgoing);
175   
176   if (connection->n_outgoing == 0)
177     _dbus_transport_messages_pending (connection->transport,
178                                       connection->n_outgoing);  
179 }
180
181 /**
182  * Adds a watch using the connection's DBusAddWatchFunction if
183  * available. Otherwise records the watch to be added when said
184  * function is available. Also re-adds the watch if the
185  * DBusAddWatchFunction changes. May fail due to lack of memory.
186  *
187  * @param connection the connection.
188  * @param watch the watch to add.
189  * @returns #TRUE on success.
190  */
191 dbus_bool_t
192 _dbus_connection_add_watch (DBusConnection *connection,
193                             DBusWatch      *watch)
194 {
195   if (connection->watches) /* null during finalize */
196     return _dbus_watch_list_add_watch (connection->watches,
197                                        watch);
198   else
199     return FALSE;
200 }
201
202 /**
203  * Removes a watch using the connection's DBusRemoveWatchFunction
204  * if available. It's an error to call this function on a watch
205  * that was not previously added.
206  *
207  * @param connection the connection.
208  * @param watch the watch to remove.
209  */
210 void
211 _dbus_connection_remove_watch (DBusConnection *connection,
212                                DBusWatch      *watch)
213 {
214   if (connection->watches) /* null during finalize */
215     _dbus_watch_list_remove_watch (connection->watches,
216                                    watch);
217 }
218
219 /**
220  * Tells the connection that the transport has been disconnected.
221  * Results in calling the application disconnect callback.
222  * Only has an effect the first time it's called.
223  *
224  * @param connection the connection
225  */
226 void
227 _dbus_connection_notify_disconnected (DBusConnection *connection)
228 {
229   if (connection->disconnect_function != NULL &&
230       !connection->disconnect_notified)
231     {
232       connection->disconnect_notified = TRUE;
233       dbus_connection_ref (connection);
234       (* connection->disconnect_function) (connection,
235                                            connection->disconnect_data);
236       dbus_connection_unref (connection);
237     }
238 }
239
240 /**
241  * Queues incoming messages and sends outgoing messages for this
242  * connection, optionally blocking in the process. Each call to
243  * _dbus_connection_do_iteration() will call select() or poll() one
244  * time and then read or write data if possible.
245  *
246  * The purpose of this function is to be able to flush outgoing
247  * messages or queue up incoming messages without returning
248  * control to the application and causing reentrancy weirdness.
249  *
250  * The flags parameter allows you to specify whether to
251  * read incoming messages, write outgoing messages, or both,
252  * and whether to block if no immediate action is possible.
253  *
254  * The timeout_milliseconds parameter does nothing unless the
255  * iteration is blocking.
256  *
257  * If there are no outgoing messages and DBUS_ITERATION_DO_READING
258  * wasn't specified, then it's impossible to block, even if
259  * you specify DBUS_ITERATION_BLOCK; in that case the function
260  * returns immediately.
261  * 
262  * @param connection the connection.
263  * @param flags iteration flags.
264  * @param timeout_milliseconds maximum blocking time, or -1 for no limit.
265  */
266 void
267 _dbus_connection_do_iteration (DBusConnection *connection,
268                                unsigned int    flags,
269                                int             timeout_milliseconds)
270 {
271   if (connection->n_outgoing == 0)
272     flags &= ~DBUS_ITERATION_DO_WRITING;
273   
274   _dbus_transport_do_iteration (connection->transport,
275                                 flags, timeout_milliseconds);
276 }
277
278 /**
279  * Creates a new connection for the given transport.  A transport
280  * represents a message stream that uses some concrete mechanism, such
281  * as UNIX domain sockets. May return #NULL if insufficient
282  * memory exists to create the connection.
283  *
284  * @param transport the transport.
285  * @returns the new connection, or #NULL on failure.
286  */
287 DBusConnection*
288 _dbus_connection_new_for_transport (DBusTransport *transport)
289 {
290   DBusConnection *connection;
291   DBusWatchList *watch_list;
292   DBusHashTable *handler_table;
293   
294   watch_list = NULL;
295   connection = NULL;
296   handler_table = NULL;
297   
298   watch_list = _dbus_watch_list_new ();
299   if (watch_list == NULL)
300     goto error;
301
302   handler_table =
303     _dbus_hash_table_new (DBUS_HASH_STRING,
304                           dbus_free, NULL);
305   if (handler_table == NULL)
306     goto error;
307   
308   connection = dbus_new0 (DBusConnection, 1);
309   if (connection == NULL)
310     goto error;
311   
312   connection->refcount = 1;
313   connection->transport = transport;
314   connection->watches = watch_list;
315   connection->handler_table = handler_table;
316   connection->filter_list = NULL;
317
318   connection->data_slots = NULL;
319   connection->n_slots = 0;
320   connection->client_serial = 1;
321   connection->disconnect_notified = FALSE;
322   
323   _dbus_transport_ref (transport);
324   _dbus_transport_set_connection (transport, connection);
325   
326   return connection;
327   
328  error:
329
330   if (connection != NULL)
331     dbus_free (connection);
332
333   if (handler_table)
334     _dbus_hash_table_unref (handler_table);
335   
336   if (watch_list)
337     _dbus_watch_list_free (watch_list);
338   
339   return NULL;
340 }
341
342 static dbus_int32_t
343 _dbus_connection_get_next_client_serial (DBusConnection *connection)
344 {
345   int serial;
346
347   serial = connection->client_serial++;
348
349   if (connection->client_serial < 0)
350     connection->client_serial = 1;
351   
352   return serial;
353 }
354
355 /**
356  * Used to notify a connection when a DBusMessageHandler is
357  * destroyed, so the connection can drop any reference
358  * to the handler.
359  *
360  * @param connection the connection
361  * @param handler the handler
362  */
363 void
364 _dbus_connection_handler_destroyed (DBusConnection     *connection,
365                                     DBusMessageHandler *handler)
366 {
367   DBusHashIter iter;
368   DBusList *link;
369
370   _dbus_hash_iter_init (connection->handler_table, &iter);
371   while (_dbus_hash_iter_next (&iter))
372     {
373       DBusMessageHandler *h = _dbus_hash_iter_get_value (&iter);
374
375       if (h == handler)
376         _dbus_hash_iter_remove_entry (&iter);
377     }
378
379   link = _dbus_list_get_first_link (&connection->filter_list);
380   while (link != NULL)
381     {
382       DBusMessageHandler *h = link->data;
383       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
384
385       if (h == handler)
386         _dbus_list_remove_link (&connection->filter_list,
387                                 link);
388       
389       link = next;
390     }
391 }
392
393 /** @} */
394
395 /**
396  * @addtogroup DBusConnection
397  *
398  * @{
399  */
400
401 /**
402  * Opens a new connection to a remote address.
403  *
404  * @todo specify what the address parameter is. Right now
405  * it's just the name of a UNIX domain socket. It should be
406  * something more complex that encodes which transport to use.
407  *
408  * If the open fails, the function returns #NULL, and provides
409  * a reason for the failure in the result parameter. Pass
410  * #NULL for the result parameter if you aren't interested
411  * in the reason for failure.
412  * 
413  * @param address the address.
414  * @param result address where a result code can be returned.
415  * @returns new connection, or #NULL on failure.
416  */
417 DBusConnection*
418 dbus_connection_open (const char     *address,
419                       DBusResultCode *result)
420 {
421   DBusConnection *connection;
422   DBusTransport *transport;
423   
424   transport = _dbus_transport_open (address, result);
425   if (transport == NULL)
426     return NULL;
427   
428   connection = _dbus_connection_new_for_transport (transport);
429
430   _dbus_transport_unref (transport);
431   
432   if (connection == NULL)
433     {
434       dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
435       return NULL;
436     }
437   
438   return connection;
439 }
440
441 /**
442  * Increments the reference count of a DBusConnection.
443  *
444  * @param connection the connection.
445  */
446 void
447 dbus_connection_ref (DBusConnection *connection)
448 {
449   connection->refcount += 1;
450 }
451
452 /**
453  * Decrements the reference count of a DBusConnection, and finalizes
454  * it if the count reaches zero.  If a connection is still connected
455  * when it's finalized, it will be disconnected (that is, associated
456  * file handles will be closed).
457  *
458  * @param connection the connection.
459  */
460 void
461 dbus_connection_unref (DBusConnection *connection)
462 {
463   _dbus_assert (connection != NULL);
464   _dbus_assert (connection->refcount > 0);
465   
466   connection->refcount -= 1;
467   if (connection->refcount == 0)
468     {
469       DBusHashIter iter;
470       DBusList *link;
471
472       dbus_connection_disconnect (connection);
473       
474       /* free disconnect data as a side effect */
475       dbus_connection_set_disconnect_function (connection,
476                                                NULL, NULL, NULL);
477
478       _dbus_watch_list_free (connection->watches);
479       connection->watches = NULL;
480
481       _dbus_connection_free_data_slots (connection);
482       
483       _dbus_hash_iter_init (connection->handler_table, &iter);
484       while (_dbus_hash_iter_next (&iter))
485         {
486           DBusMessageHandler *h = _dbus_hash_iter_get_value (&iter);
487           
488           _dbus_message_handler_remove_connection (h, connection);
489         }
490
491       link = _dbus_list_get_first_link (&connection->filter_list);
492       while (link != NULL)
493         {
494           DBusMessageHandler *h = link->data;
495           DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
496           
497           _dbus_message_handler_remove_connection (h, connection);
498           
499           link = next;
500         }
501       
502       _dbus_hash_table_unref (connection->handler_table);
503       connection->handler_table = NULL;
504
505       _dbus_list_clear (&connection->filter_list);
506       
507       _dbus_list_foreach (&connection->outgoing_messages,
508                           (DBusForeachFunction) dbus_message_unref,
509                           NULL);
510       _dbus_list_clear (&connection->outgoing_messages);
511
512       _dbus_list_foreach (&connection->incoming_messages,
513                           (DBusForeachFunction) dbus_message_unref,
514                           NULL);
515       _dbus_list_clear (&connection->incoming_messages);
516       
517       _dbus_transport_unref (connection->transport);
518       
519       dbus_free (connection);
520     }
521 }
522
523 /**
524  * Closes the connection, so no further data can be sent or received.
525  * Any further attempts to send data will result in errors.  This
526  * function does not affect the connection's reference count.  It's
527  * safe to disconnect a connection more than once; all calls after the
528  * first do nothing. It's impossible to "reconnect" a connection, a
529  * new connection must be created.
530  *
531  * @param connection the connection.
532  */
533 void
534 dbus_connection_disconnect (DBusConnection *connection)
535 {
536   _dbus_transport_disconnect (connection->transport);
537 }
538
539 /**
540  * Gets whether the connection is currently connected.  All
541  * connections are connected when they are opened.  A connection may
542  * become disconnected when the remote application closes its end, or
543  * exits; a connection may also be disconnected with
544  * dbus_connection_disconnect().
545  *
546  * @param connection the connection.
547  * @returns #TRUE if the connection is still alive.
548  */
549 dbus_bool_t
550 dbus_connection_get_is_connected (DBusConnection *connection)
551 {
552   return _dbus_transport_get_is_connected (connection->transport);
553 }
554
555 /**
556  * Adds a message to the outgoing message queue. Does not block to
557  * write the message to the network; that happens asynchronously. to
558  * force the message to be written, call dbus_connection_flush().
559  *
560  * If the function fails, it returns #FALSE and returns the
561  * reason for failure via the result parameter.
562  * The result parameter can be #NULL if you aren't interested
563  * in the reason for the failure.
564  * 
565  * @param connection the connection.
566  * @param message the message to write.
567  * @param result address where result code can be placed.
568  * @returns #TRUE on success.
569  */
570 dbus_bool_t
571 dbus_connection_send_message (DBusConnection *connection,
572                               DBusMessage    *message,
573                               DBusResultCode *result)
574 {  
575   if (!_dbus_list_prepend (&connection->outgoing_messages,
576                            message))
577     {
578       dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
579       return FALSE;
580     }
581
582   dbus_message_ref (message);
583   connection->n_outgoing += 1;
584
585   _dbus_verbose ("Message %p added to outgoing queue, %d pending to send\n",
586                  message, connection->n_outgoing);
587
588   _dbus_message_set_client_serial (message, _dbus_connection_get_next_client_serial (connection));
589   _dbus_message_lock (message);
590   
591   if (connection->n_outgoing == 1)
592     _dbus_transport_messages_pending (connection->transport,
593                                       connection->n_outgoing);
594
595   return TRUE;
596 }
597
598 /**
599  * Queues a message to send, as with dbus_connection_send_message(),
600  * but also sets up a DBusMessageHandler to receive a reply to the
601  * message. If no reply is received in the given timeout_milliseconds,
602  * expires the pending reply and sends the DBusMessageHandler a
603  * synthetic error reply (generated in-process, not by the remote
604  * application) indicating that a timeout occurred.
605  *
606  * Reply handlers see their replies after message filters see them,
607  * but before message handlers added with
608  * dbus_connection_register_handler() see them, regardless of the
609  * reply message's name. Reply handlers are only handed a single
610  * message as a reply, after a reply has been seen the handler is
611  * removed. If a filter filters out the reply before the handler sees
612  * it, the handler is not removed but the timeout will immediately
613  * fire again. If a filter was dumb and kept removing the timeout
614  * reply then we'd get in an infinite loop.
615  * 
616  * If #NULL is passed for the reply_handler, the timeout reply will
617  * still be generated and placed into the message queue, but no
618  * specific message handler will receive the reply.
619  *
620  * If -1 is passed for the timeout, a sane default timeout is used. -1
621  * is typically the best value for the timeout for this reason, unless
622  * you want a very short or very long timeout.  There is no way to
623  * avoid a timeout entirely, other than passing INT_MAX for the
624  * timeout to postpone it indefinitely.
625  * 
626  * @param connection the connection
627  * @param message the message to send
628  * @param reply_handler message handler expecting the reply, or #NULL
629  * @param timeout_milliseconds timeout in milliseconds or -1 for default
630  * @param result return location for result code
631  * @returns #TRUE if the message is successfully queued, #FALSE if no memory.
632  *
633  * @todo this function isn't implemented because we need message serials
634  * and other slightly more rich DBusMessage implementation in order to
635  * implement it. The basic idea will be to keep a hash of serials we're
636  * expecting a reply to, and also to add a way to tell GLib or Qt to
637  * install a timeout. Then install a timeout which is the shortest
638  * timeout of any pending reply.
639  *
640  * @todo implement non-reentrant "block for reply" variant.  i.e. send
641  * a message, block until we get a reply, then pull reply out of
642  * message queue and return it, *without dispatching any handlers for
643  * any other messages* - used for non-reentrant "method calls" We can
644  * block properly for this using _dbus_connection_do_iteration().
645  * 
646  */
647 dbus_bool_t
648 dbus_connection_send_message_with_reply (DBusConnection     *connection,
649                                          DBusMessage        *message,
650                                          DBusMessageHandler *reply_handler,
651                                          int                 timeout_milliseconds,
652                                          DBusResultCode     *result)
653 {
654   /* FIXME */
655   return dbus_connection_send_message (connection, message, result);
656 }
657
658 /**
659  * Blocks until the outgoing message queue is empty.
660  *
661  * @param connection the connection.
662  */
663 void
664 dbus_connection_flush (DBusConnection *connection)
665 {
666   while (connection->n_outgoing > 0)
667     _dbus_connection_do_iteration (connection,
668                                    DBUS_ITERATION_DO_WRITING |
669                                    DBUS_ITERATION_BLOCK,
670                                    -1);
671 }
672
673 /**
674  * Gets the number of messages in the incoming message queue.
675  *
676  * @param connection the connection.
677  * @returns the number of messages in the queue.
678  */
679 int
680 dbus_connection_get_n_messages (DBusConnection *connection)
681 {
682   return connection->n_incoming;
683 }
684
685 /**
686  * Returns the first-received message from the incoming message queue,
687  * leaving it in the queue. The caller does not own a reference to the
688  * returned message. If the queue is empty, returns #NULL.
689  *
690  * @param connection the connection.
691  * @returns next message in the incoming queue.
692  */
693 DBusMessage*
694 dbus_connection_peek_message  (DBusConnection *connection)
695 {
696   return _dbus_list_get_first (&connection->incoming_messages);
697 }
698
699 /**
700  * Returns the first-received message from the incoming message queue,
701  * removing it from the queue. The caller owns a reference to the
702  * returned message. If the queue is empty, returns #NULL.
703  *
704  * @param connection the connection.
705  * @returns next message in the incoming queue.
706  */
707 DBusMessage*
708 dbus_connection_pop_message (DBusConnection *connection)
709 {
710   if (connection->n_incoming > 0)
711     {
712       DBusMessage *message;
713
714       message = _dbus_list_pop_first (&connection->incoming_messages);
715       connection->n_incoming -= 1;
716
717       _dbus_verbose ("Incoming message %p removed from queue, %d incoming\n",
718                      message, connection->n_incoming);
719
720       return message;
721     }
722   else
723     return NULL;
724 }
725
726 /**
727  * Pops the first-received message from the current incoming message
728  * queue, runs any handlers for it, then unrefs the message.
729  *
730  * @param connection the connection
731  * @returns #TRUE if the queue is not empty after dispatch
732  *
733  * @todo this function is not properly robust against reentrancy,
734  * that is, if handlers are added/removed while dispatching
735  * a message, things will get messed up.
736  */
737 dbus_bool_t
738 dbus_connection_dispatch_message (DBusConnection *connection)
739 {
740   DBusMessage *message;
741   int filter_serial;
742   int handler_serial;
743   DBusList *link;
744   DBusHandlerResult result;
745   const char *name;
746   
747   dbus_connection_ref (connection);
748   
749   message = dbus_connection_pop_message (connection);
750   if (message == NULL)
751     {
752       dbus_connection_unref (connection);
753       return FALSE;
754     }
755
756   filter_serial = connection->filters_serial;
757   handler_serial = connection->handlers_serial;
758
759   result = DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
760   
761   link = _dbus_list_get_first_link (&connection->filter_list);
762   while (link != NULL)
763     {
764       DBusMessageHandler *handler = link->data;
765       DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
766       
767       result = _dbus_message_handler_handle_message (handler, connection,
768                                                      message);
769
770       if (result == DBUS_HANDLER_RESULT_REMOVE_MESSAGE)
771         goto out;
772
773       if (filter_serial != connection->filters_serial)
774         {
775           _dbus_warn ("Message filters added or removed while dispatching filters - not currently supported!\n");
776           goto out;
777         }
778       
779       link = next;
780     }
781
782   name = dbus_message_get_name (message);
783   if (name != NULL)
784     {
785       DBusMessageHandler *handler;
786       
787       handler = _dbus_hash_table_lookup_string (connection->handler_table,
788                                                 name);
789       if (handler != NULL)
790         {
791
792           result = _dbus_message_handler_handle_message (handler, connection,
793                                                          message);
794       
795           if (result == DBUS_HANDLER_RESULT_REMOVE_MESSAGE)
796             goto out;
797           
798           if (handler_serial != connection->handlers_serial)
799             {
800               _dbus_warn ("Message handlers added or removed while dispatching handlers - not currently supported!\n");
801               goto out;
802             }
803         }
804     }
805
806  out:
807   dbus_connection_unref (connection);
808   dbus_message_unref (message);
809   
810   return connection->n_incoming > 0;
811 }
812
813 /**
814  * Sets the disconnect handler function for the connection.
815  * Will be called exactly once, when the connection is
816  * disconnected.
817  * 
818  * @param connection the connection.
819  * @param disconnect_function the disconnect handler.
820  * @param data data to pass to the disconnect handler.
821  * @param free_data_function function to be called to free the data.
822  */
823 void
824 dbus_connection_set_disconnect_function  (DBusConnection              *connection,
825                                           DBusDisconnectFunction       disconnect_function,
826                                           void                        *data,
827                                           DBusFreeFunction             free_data_function)
828 {
829   if (connection->disconnect_free_data_function != NULL)
830     (* connection->disconnect_free_data_function) (connection->disconnect_data);
831
832   connection->disconnect_function = disconnect_function;
833   connection->disconnect_data = data;
834   connection->disconnect_free_data_function = free_data_function;
835 }
836
837 /**
838  * Sets the watch functions for the connection. These functions are
839  * responsible for making the application's main loop aware of file
840  * descriptors that need to be monitored for events, using select() or
841  * poll(). When using Qt, typically the DBusAddWatchFunction would
842  * create a QSocketNotifier. When using GLib, the DBusAddWatchFunction
843  * could call g_io_add_watch(), or could be used as part of a more
844  * elaborate GSource.
845  *
846  * The DBusWatch can be queried for the file descriptor to watch using
847  * dbus_watch_get_fd(), and for the events to watch for using
848  * dbus_watch_get_flags(). The flags returned by
849  * dbus_watch_get_flags() will only contain DBUS_WATCH_READABLE and
850  * DBUS_WATCH_WRITABLE, never DBUS_WATCH_HANGUP or DBUS_WATCH_ERROR;
851  * all watches implicitly include a watch for hangups, errors, and
852  * other exceptional conditions.
853  *
854  * Once a file descriptor becomes readable or writable, or an exception
855  * occurs, dbus_connection_handle_watch() should be called to
856  * notify the connection of the file descriptor's condition.
857  *
858  * dbus_connection_handle_watch() cannot be called during the
859  * DBusAddWatchFunction, as the connection will not be ready to handle
860  * that watch yet.
861  * 
862  * It is not allowed to reference a DBusWatch after it has been passed
863  * to remove_function.
864  * 
865  * @param connection the connection.
866  * @param add_function function to begin monitoring a new descriptor.
867  * @param remove_function function to stop monitoring a descriptor.
868  * @param data data to pass to add_function and remove_function.
869  * @param free_data_function function to be called to free the data.
870  */
871 void
872 dbus_connection_set_watch_functions (DBusConnection              *connection,
873                                      DBusAddWatchFunction         add_function,
874                                      DBusRemoveWatchFunction      remove_function,
875                                      void                        *data,
876                                      DBusFreeFunction             free_data_function)
877 {
878   /* ref connection for slightly better reentrancy */
879   dbus_connection_ref (connection);
880   
881   _dbus_watch_list_set_functions (connection->watches,
882                                   add_function, remove_function,
883                                   data, free_data_function);
884   
885   /* drop our paranoid refcount */
886   dbus_connection_unref (connection);
887 }
888
889 /**
890  * Called to notify the connection when a previously-added watch
891  * is ready for reading or writing, or has an exception such
892  * as a hangup.
893  *
894  * @param connection the connection.
895  * @param watch the watch.
896  * @param condition the current condition of the file descriptors being watched.
897  */
898 void
899 dbus_connection_handle_watch (DBusConnection              *connection,
900                               DBusWatch                   *watch,
901                               unsigned int                 condition)
902 {
903   _dbus_transport_handle_watch (connection->transport,
904                                 watch, condition);
905 }
906
907 /**
908  * Adds a message filter. Filters are handlers that are run on
909  * all incoming messages, prior to the normal handlers
910  * registered with dbus_connection_register_handler().
911  * Filters are run in the order that they were added.
912  * The same handler can be added as a filter more than once, in
913  * which case it will be run more than once.
914  *
915  * @param connection the connection
916  * @param handler the handler
917  * @returns #TRUE on success, #FALSE if not enough memory.
918  */
919 dbus_bool_t
920 dbus_connection_add_filter (DBusConnection      *connection,
921                             DBusMessageHandler  *handler)
922 {
923   if (!_dbus_message_handler_add_connection (handler, connection))
924     return FALSE;
925
926   if (!_dbus_list_append (&connection->filter_list,
927                           handler))
928     {
929       _dbus_message_handler_remove_connection (handler, connection);
930       return FALSE;
931     }
932
933   connection->filters_serial += 1;
934   
935   return TRUE;
936 }
937
938 /**
939  * Removes a previously-added message filter. It is a programming
940  * error to call this function for a handler that has not
941  * been added as a filter. If the given handler was added
942  * more than once, only one instance of it will be removed
943  * (the most recently-added instance).
944  *
945  * @param connection the connection
946  * @param handler the handler to remove
947  *
948  */
949 void
950 dbus_connection_remove_filter (DBusConnection      *connection,
951                                DBusMessageHandler  *handler)
952 {
953   if (!_dbus_list_remove_last (&connection->filter_list, handler))
954     {
955       _dbus_warn ("Tried to remove a DBusConnection filter that had not been added\n");
956       return;
957     }
958
959   _dbus_message_handler_remove_connection (handler, connection);
960
961   connection->filters_serial += 1;
962 }
963
964 /**
965  * Registers a handler for a list of message names. A single handler
966  * can be registered for any number of message names, but each message
967  * name can only have one handler at a time. It's not allowed to call
968  * this function with the name of a message that already has a
969  * handler. If the function returns #FALSE, the handlers were not
970  * registered due to lack of memory.
971  * 
972  * @param connection the connection
973  * @param handler the handler
974  * @param messages_to_handle the messages to handle
975  * @param n_messages the number of message names in messages_to_handle
976  * @returns #TRUE on success, #FALSE if no memory or another handler already exists
977  * 
978  **/
979 dbus_bool_t
980 dbus_connection_register_handler (DBusConnection     *connection,
981                                   DBusMessageHandler *handler,
982                                   const char        **messages_to_handle,
983                                   int                 n_messages)
984 {
985   int i;
986
987   i = 0;
988   while (i < n_messages)
989     {
990       DBusHashIter iter;
991       char *key;
992
993       key = _dbus_strdup (messages_to_handle[i]);
994       if (key == NULL)
995         goto failed;
996       
997       if (!_dbus_hash_iter_lookup (connection->handler_table,
998                                    key, TRUE,
999                                    &iter))
1000         {
1001           dbus_free (key);
1002           goto failed;
1003         }
1004
1005       if (_dbus_hash_iter_get_value (&iter) != NULL)
1006         {
1007           _dbus_warn ("Bug in application: attempted to register a second handler for %s\n",
1008                       messages_to_handle[i]);
1009           dbus_free (key); /* won't have replaced the old key with the new one */
1010           goto failed;
1011         }
1012
1013       if (!_dbus_message_handler_add_connection (handler, connection))
1014         {
1015           _dbus_hash_iter_remove_entry (&iter);
1016           /* key has freed on nuking the entry */
1017           goto failed;
1018         }
1019       
1020       _dbus_hash_iter_set_value (&iter, handler);
1021
1022       connection->handlers_serial += 1;
1023       
1024       ++i;
1025     }
1026   
1027   return TRUE;
1028   
1029  failed:
1030   /* unregister everything registered so far,
1031    * so we don't fail partially
1032    */
1033   dbus_connection_unregister_handler (connection,
1034                                       handler,
1035                                       messages_to_handle,
1036                                       i);
1037
1038   return FALSE;
1039 }
1040
1041 /**
1042  * Unregisters a handler for a list of message names. The handlers
1043  * must have been previously registered.
1044  *
1045  * @param connection the connection
1046  * @param handler the handler
1047  * @param messages_to_handle the messages to handle
1048  * @param n_messages the number of message names in messages_to_handle
1049  * 
1050  **/
1051 void
1052 dbus_connection_unregister_handler (DBusConnection     *connection,
1053                                     DBusMessageHandler *handler,
1054                                     const char        **messages_to_handle,
1055                                     int                 n_messages)
1056 {
1057   int i;
1058
1059   i = 0;
1060   while (i < n_messages)
1061     {
1062       DBusHashIter iter;
1063
1064       if (!_dbus_hash_iter_lookup (connection->handler_table,
1065                                    (char*) messages_to_handle[i], FALSE,
1066                                    &iter))
1067         {
1068           _dbus_warn ("Bug in application: attempted to unregister handler for %s which was not registered\n",
1069                       messages_to_handle[i]);
1070         }
1071       else if (_dbus_hash_iter_get_value (&iter) != handler)
1072         {
1073           _dbus_warn ("Bug in application: attempted to unregister handler for %s which was registered by a different handler\n",
1074                       messages_to_handle[i]);
1075         }
1076       else
1077         {
1078           _dbus_hash_iter_remove_entry (&iter);
1079           _dbus_message_handler_remove_connection (handler, connection);
1080         }
1081
1082       ++i;
1083     }
1084
1085   connection->handlers_serial += 1;
1086 }
1087
1088 static int *allocated_slots = NULL;
1089 static int  n_allocated_slots = 0;
1090 static int  n_used_slots = 0;
1091 static DBusStaticMutex allocated_slots_lock = DBUS_STATIC_MUTEX_INIT;
1092
1093 /**
1094  * Allocates an integer ID to be used for storing application-specific
1095  * data on any DBusConnection. The allocated ID may then be used
1096  * with dbus_connection_set_data() and dbus_connection_get_data().
1097  * If allocation fails, -1 is returned.
1098  *
1099  * @returns -1 on failure, otherwise the data slot ID
1100  */
1101 int
1102 dbus_connection_allocate_data_slot (void)
1103 {
1104   int slot;
1105   
1106   if (!dbus_static_mutex_lock (&allocated_slots_lock))
1107     return -1;
1108
1109   if (n_used_slots < n_allocated_slots)
1110     {
1111       slot = 0;
1112       while (slot < n_allocated_slots)
1113         {
1114           if (allocated_slots[slot] < 0)
1115             {
1116               allocated_slots[slot] = slot;
1117               n_used_slots += 1;
1118               break;
1119             }
1120           ++slot;
1121         }
1122
1123       _dbus_assert (slot < n_allocated_slots);
1124     }
1125   else
1126     {
1127       int *tmp;
1128       
1129       slot = -1;
1130       tmp = dbus_realloc (allocated_slots,
1131                           sizeof (int) * (n_allocated_slots + 1));
1132       if (tmp == NULL)
1133         goto out;
1134
1135       allocated_slots = tmp;
1136       slot = n_allocated_slots;
1137       n_allocated_slots += 1;
1138       n_used_slots += 1;
1139       allocated_slots[slot] = slot;
1140     }
1141
1142   _dbus_assert (slot >= 0);
1143   _dbus_assert (slot < n_allocated_slots);
1144   
1145  out:
1146   dbus_static_mutex_unlock (&allocated_slots_lock);
1147   return slot;
1148 }
1149
1150 /**
1151  * Deallocates a global ID for connection data slots.
1152  * dbus_connection_get_data() and dbus_connection_set_data()
1153  * may no longer be used with this slot.
1154  * Existing data stored on existing DBusConnection objects
1155  * will be freed when the connection is finalized,
1156  * but may not be retrieved (and may only be replaced
1157  * if someone else reallocates the slot).
1158  *
1159  * @param slot the slot to deallocate
1160  */
1161 void
1162 dbus_connection_free_data_slot (int slot)
1163 {
1164   dbus_static_mutex_lock (&allocated_slots_lock);
1165
1166   _dbus_assert (slot < n_allocated_slots);
1167   _dbus_assert (allocated_slots[slot] == slot);
1168   
1169   allocated_slots[slot] = -1;
1170   n_used_slots -= 1;
1171
1172   if (n_used_slots == 0)
1173     {
1174       dbus_free (allocated_slots);
1175       allocated_slots = NULL;
1176       n_allocated_slots = 0;
1177     }
1178   
1179   dbus_static_mutex_unlock (&allocated_slots_lock);
1180 }
1181
1182 /**
1183  * Stores a pointer on a DBusConnection, along
1184  * with an optional function to be used for freeing
1185  * the data when the data is set again, or when
1186  * the connection is finalized. The slot number
1187  * must have been allocated with dbus_connection_allocate_data_slot().
1188  *
1189  * @param connection the connection
1190  * @param slot the slot number
1191  * @param data the data to store
1192  * @param free_data_func finalizer function for the data
1193  * @returns #TRUE if there was enough memory to store the data
1194  */
1195 dbus_bool_t
1196 dbus_connection_set_data (DBusConnection   *connection,
1197                           int               slot,
1198                           void             *data,
1199                           DBusFreeFunction  free_data_func)
1200 {
1201   _dbus_assert (slot < n_allocated_slots);
1202   _dbus_assert (allocated_slots[slot] == slot);
1203   
1204   if (slot >= connection->n_slots)
1205     {
1206       DBusDataSlot *tmp;
1207       int i;
1208       
1209       tmp = dbus_realloc (connection->data_slots,
1210                           sizeof (DBusDataSlot) * (slot + 1));
1211       if (tmp == NULL)
1212         return FALSE;
1213       
1214       connection->data_slots = tmp;
1215       i = connection->n_slots;
1216       connection->n_slots = slot + 1;
1217       while (i < connection->n_slots)
1218         {
1219           connection->data_slots[i].data = NULL;
1220           connection->data_slots[i].free_data_func = NULL;
1221           ++i;
1222         }
1223     }
1224
1225   _dbus_assert (slot < connection->n_slots);
1226   
1227   if (connection->data_slots[slot].free_data_func)
1228     (* connection->data_slots[slot].free_data_func) (connection->data_slots[slot].data);
1229
1230   connection->data_slots[slot].data = data;
1231   connection->data_slots[slot].free_data_func = free_data_func;
1232
1233   return TRUE;
1234 }
1235
1236 /**
1237  * Retrieves data previously set with dbus_connection_set_data().
1238  * The slot must still be allocated (must not have been freed).
1239  *
1240  * @param connection the connection
1241  * @param slot the slot to get data from
1242  * @returns the data, or #NULL if not found
1243  */
1244 void*
1245 dbus_connection_get_data (DBusConnection   *connection,
1246                           int               slot)
1247 {
1248   _dbus_assert (slot < n_allocated_slots);
1249   _dbus_assert (allocated_slots[slot] == slot);
1250
1251   if (slot >= connection->n_slots)
1252     return NULL;
1253
1254   return connection->data_slots[slot].data;
1255 }
1256
1257 static void
1258 _dbus_connection_free_data_slots (DBusConnection *connection)
1259 {
1260   int i;
1261
1262   i = 0;
1263   while (i < connection->n_slots)
1264     {
1265       if (connection->data_slots[i].free_data_func)
1266         (* connection->data_slots[i].free_data_func) (connection->data_slots[i].data);
1267       connection->data_slots[i].data = NULL;
1268       connection->data_slots[i].free_data_func = NULL;
1269       ++i;
1270     }
1271
1272   dbus_free (connection->data_slots);
1273   connection->data_slots = NULL;
1274   connection->n_slots = 0;
1275 }
1276
1277 /** @} */