Merge remote-tracking branch 'wjt/arg0namespace' into arg0namespace-24317
[platform/upstream/dbus.git] / dbus / dbus-server.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-server.c DBusServer object
3  *
4  * Copyright (C) 2002, 2003, 2004, 2005 Red Hat Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */ 
23
24 #include <config.h>
25 #include "dbus-server.h"
26 #include "dbus-server-unix.h"
27 #include "dbus-server-socket.h"
28 #include "dbus-string.h"
29 #ifdef DBUS_BUILD_TESTS
30 #include "dbus-server-debug-pipe.h"
31 #endif
32 #include "dbus-address.h"
33 #include "dbus-protocol.h"
34
35 /**
36  * @defgroup DBusServer DBusServer
37  * @ingroup  DBus
38  * @brief Server that listens for new connections.
39  *
40  * A DBusServer represents a server that other applications
41  * can connect to. Each connection from another application
42  * is represented by a #DBusConnection.
43  *
44  * @todo Thread safety hasn't been tested much for #DBusServer
45  * @todo Need notification to apps of disconnection, may matter for some transports
46  */
47
48 /**
49  * @defgroup DBusServerInternals DBusServer implementation details
50  * @ingroup  DBusInternals
51  * @brief Implementation details of DBusServer
52  *
53  * @{
54  */
55
56 /* this is a little fragile since it assumes the address doesn't
57  * already have a guid, but it shouldn't
58  */
59 static char*
60 copy_address_with_guid_appended (const DBusString *address,
61                                  const DBusString *guid_hex)
62 {
63   DBusString with_guid;
64   char *retval;
65   
66   if (!_dbus_string_init (&with_guid))
67     return NULL;
68
69   if (!_dbus_string_copy (address, 0, &with_guid,
70                           _dbus_string_get_length (&with_guid)) ||
71       !_dbus_string_append (&with_guid, ",guid=") ||
72       !_dbus_string_copy (guid_hex, 0,
73                           &with_guid, _dbus_string_get_length (&with_guid)))
74     {
75       _dbus_string_free (&with_guid);
76       return NULL;
77     }
78
79   retval = NULL;
80   _dbus_string_steal_data (&with_guid, &retval);
81
82   _dbus_string_free (&with_guid);
83       
84   return retval; /* may be NULL if steal_data failed */
85 }
86
87 /**
88  * Initializes the members of the DBusServer base class.
89  * Chained up to by subclass constructors.
90  *
91  * @param server the server.
92  * @param vtable the vtable for the subclass.
93  * @param address the server's address
94  * @returns #TRUE on success.
95  */
96 dbus_bool_t
97 _dbus_server_init_base (DBusServer             *server,
98                         const DBusServerVTable *vtable,
99                         const DBusString       *address)
100 {
101   server->vtable = vtable;
102   server->refcount.value = 1;
103
104   server->address = NULL;
105   server->watches = NULL;
106   server->timeouts = NULL;
107   server->published_address = FALSE;
108
109   if (!_dbus_string_init (&server->guid_hex))
110     return FALSE;
111
112   _dbus_generate_uuid (&server->guid);
113
114   if (!_dbus_uuid_encode (&server->guid, &server->guid_hex))
115     goto failed;
116   
117   server->address = copy_address_with_guid_appended (address,
118                                                      &server->guid_hex);
119   if (server->address == NULL)
120     goto failed;
121   
122   _dbus_mutex_new_at_location (&server->mutex);
123   if (server->mutex == NULL)
124     goto failed;
125   
126   server->watches = _dbus_watch_list_new ();
127   if (server->watches == NULL)
128     goto failed;
129
130   server->timeouts = _dbus_timeout_list_new ();
131   if (server->timeouts == NULL)
132     goto failed;
133
134   _dbus_data_slot_list_init (&server->slot_list);
135
136   _dbus_verbose ("Initialized server on address %s\n", server->address);
137   
138   return TRUE;
139
140  failed:
141   _dbus_mutex_free_at_location (&server->mutex);
142   server->mutex = NULL;
143   if (server->watches)
144     {
145       _dbus_watch_list_free (server->watches);
146       server->watches = NULL;
147     }
148   if (server->timeouts)
149     {
150       _dbus_timeout_list_free (server->timeouts);
151       server->timeouts = NULL;
152     }
153   if (server->address)
154     {
155       dbus_free (server->address);
156       server->address = NULL;
157     }
158   _dbus_string_free (&server->guid_hex);
159   
160   return FALSE;
161 }
162
163 /**
164  * Finalizes the members of the DBusServer base class.
165  * Chained up to by subclass finalizers.
166  *
167  * @param server the server.
168  */
169 void
170 _dbus_server_finalize_base (DBusServer *server)
171 {
172   /* We don't have the lock, but nobody should be accessing
173    * concurrently since they don't have a ref
174    */
175 #ifndef DBUS_DISABLE_CHECKS
176   _dbus_assert (!server->have_server_lock);
177 #endif
178   _dbus_assert (server->disconnected);
179   
180   /* calls out to application code... */
181   _dbus_data_slot_list_free (&server->slot_list);
182
183   dbus_server_set_new_connection_function (server, NULL, NULL, NULL);
184
185   _dbus_watch_list_free (server->watches);
186   _dbus_timeout_list_free (server->timeouts);
187
188   _dbus_mutex_free_at_location (&server->mutex);
189   
190   dbus_free (server->address);
191
192   dbus_free_string_array (server->auth_mechanisms);
193
194   _dbus_string_free (&server->guid_hex);
195 }
196
197
198 /** Function to be called in protected_change_watch() with refcount held */
199 typedef dbus_bool_t (* DBusWatchAddFunction)     (DBusWatchList *list,
200                                                   DBusWatch     *watch);
201 /** Function to be called in protected_change_watch() with refcount held */
202 typedef void        (* DBusWatchRemoveFunction)  (DBusWatchList *list,
203                                                   DBusWatch     *watch);
204 /** Function to be called in protected_change_watch() with refcount held */
205 typedef void        (* DBusWatchToggleFunction)  (DBusWatchList *list,
206                                                   DBusWatch     *watch,
207                                                   dbus_bool_t    enabled);
208
209 static dbus_bool_t
210 protected_change_watch (DBusServer             *server,
211                         DBusWatch              *watch,
212                         DBusWatchAddFunction    add_function,
213                         DBusWatchRemoveFunction remove_function,
214                         DBusWatchToggleFunction toggle_function,
215                         dbus_bool_t             enabled)
216 {
217   DBusWatchList *watches;
218   dbus_bool_t retval;
219   
220   HAVE_LOCK_CHECK (server);
221
222   /* This isn't really safe or reasonable; a better pattern is the "do
223    * everything, then drop lock and call out" one; but it has to be
224    * propagated up through all callers
225    */
226   
227   watches = server->watches;
228   if (watches)
229     {
230       server->watches = NULL;
231       _dbus_server_ref_unlocked (server);
232       SERVER_UNLOCK (server);
233
234       if (add_function)
235         retval = (* add_function) (watches, watch);
236       else if (remove_function)
237         {
238           retval = TRUE;
239           (* remove_function) (watches, watch);
240         }
241       else
242         {
243           retval = TRUE;
244           (* toggle_function) (watches, watch, enabled);
245         }
246       
247       SERVER_LOCK (server);
248       server->watches = watches;
249       _dbus_server_unref_unlocked (server);
250
251       return retval;
252     }
253   else
254     return FALSE;
255 }
256
257 /**
258  * Adds a watch for this server, chaining out to application-provided
259  * watch handlers.
260  *
261  * @param server the server.
262  * @param watch the watch to add.
263  */
264 dbus_bool_t
265 _dbus_server_add_watch (DBusServer *server,
266                         DBusWatch  *watch)
267 {
268   HAVE_LOCK_CHECK (server);
269   return protected_change_watch (server, watch,
270                                  _dbus_watch_list_add_watch,
271                                  NULL, NULL, FALSE);
272 }
273
274 /**
275  * Removes a watch previously added with _dbus_server_remove_watch().
276  *
277  * @param server the server.
278  * @param watch the watch to remove.
279  */
280 void
281 _dbus_server_remove_watch  (DBusServer *server,
282                             DBusWatch  *watch)
283 {
284   HAVE_LOCK_CHECK (server);
285   protected_change_watch (server, watch,
286                           NULL,
287                           _dbus_watch_list_remove_watch,
288                           NULL, FALSE);
289 }
290
291 /**
292  * Toggles a watch and notifies app via server's
293  * DBusWatchToggledFunction if available. It's an error to call this
294  * function on a watch that was not previously added.
295  *
296  * @param server the server.
297  * @param watch the watch to toggle.
298  * @param enabled whether to enable or disable
299  */
300 void
301 _dbus_server_toggle_watch (DBusServer  *server,
302                            DBusWatch   *watch,
303                            dbus_bool_t  enabled)
304 {
305   _dbus_assert (watch != NULL);
306
307   HAVE_LOCK_CHECK (server);
308   protected_change_watch (server, watch,
309                           NULL, NULL,
310                           _dbus_watch_list_toggle_watch,
311                           enabled);
312 }
313
314 /** Function to be called in protected_change_timeout() with refcount held */
315 typedef dbus_bool_t (* DBusTimeoutAddFunction)    (DBusTimeoutList *list,
316                                                    DBusTimeout     *timeout);
317 /** Function to be called in protected_change_timeout() with refcount held */
318 typedef void        (* DBusTimeoutRemoveFunction) (DBusTimeoutList *list,
319                                                    DBusTimeout     *timeout);
320 /** Function to be called in protected_change_timeout() with refcount held */
321 typedef void        (* DBusTimeoutToggleFunction) (DBusTimeoutList *list,
322                                                    DBusTimeout     *timeout,
323                                                    dbus_bool_t      enabled);
324
325
326 static dbus_bool_t
327 protected_change_timeout (DBusServer               *server,
328                           DBusTimeout              *timeout,
329                           DBusTimeoutAddFunction    add_function,
330                           DBusTimeoutRemoveFunction remove_function,
331                           DBusTimeoutToggleFunction toggle_function,
332                           dbus_bool_t               enabled)
333 {
334   DBusTimeoutList *timeouts;
335   dbus_bool_t retval;
336   
337   HAVE_LOCK_CHECK (server);
338
339   /* This isn't really safe or reasonable; a better pattern is the "do everything, then
340    * drop lock and call out" one; but it has to be propagated up through all callers
341    */
342   
343   timeouts = server->timeouts;
344   if (timeouts)
345     {
346       server->timeouts = NULL;
347       _dbus_server_ref_unlocked (server);
348       SERVER_UNLOCK (server);
349
350       if (add_function)
351         retval = (* add_function) (timeouts, timeout);
352       else if (remove_function)
353         {
354           retval = TRUE;
355           (* remove_function) (timeouts, timeout);
356         }
357       else
358         {
359           retval = TRUE;
360           (* toggle_function) (timeouts, timeout, enabled);
361         }
362       
363       SERVER_LOCK (server);
364       server->timeouts = timeouts;
365       _dbus_server_unref_unlocked (server);
366
367       return retval;
368     }
369   else
370     return FALSE;
371 }
372
373 /**
374  * Adds a timeout for this server, chaining out to
375  * application-provided timeout handlers. The timeout should be
376  * repeatedly handled with dbus_timeout_handle() at its given interval
377  * until it is removed.
378  *
379  * @param server the server.
380  * @param timeout the timeout to add.
381  */
382 dbus_bool_t
383 _dbus_server_add_timeout (DBusServer  *server,
384                           DBusTimeout *timeout)
385 {
386   return protected_change_timeout (server, timeout,
387                                    _dbus_timeout_list_add_timeout,
388                                    NULL, NULL, FALSE);
389 }
390
391 /**
392  * Removes a timeout previously added with _dbus_server_add_timeout().
393  *
394  * @param server the server.
395  * @param timeout the timeout to remove.
396  */
397 void
398 _dbus_server_remove_timeout (DBusServer  *server,
399                              DBusTimeout *timeout)
400 {
401   protected_change_timeout (server, timeout,
402                             NULL,
403                             _dbus_timeout_list_remove_timeout,
404                             NULL, FALSE);
405 }
406
407 /**
408  * Toggles a timeout and notifies app via server's
409  * DBusTimeoutToggledFunction if available. It's an error to call this
410  * function on a timeout that was not previously added.
411  *
412  * @param server the server.
413  * @param timeout the timeout to toggle.
414  * @param enabled whether to enable or disable
415  */
416 void
417 _dbus_server_toggle_timeout (DBusServer  *server,
418                              DBusTimeout *timeout,
419                              dbus_bool_t  enabled)
420 {
421   protected_change_timeout (server, timeout,
422                             NULL, NULL,
423                             _dbus_timeout_list_toggle_timeout,
424                             enabled);
425 }
426
427
428 /**
429  * Like dbus_server_ref() but does not acquire the lock (must already be held)
430  *
431  * @param server the server.
432  */
433 void
434 _dbus_server_ref_unlocked (DBusServer *server)
435 {
436   _dbus_assert (server != NULL);
437   _dbus_assert (server->refcount.value > 0);
438   
439   HAVE_LOCK_CHECK (server);
440
441 #ifdef DBUS_HAVE_ATOMIC_INT
442   _dbus_atomic_inc (&server->refcount);
443 #else
444   _dbus_assert (server->refcount.value > 0);
445
446   server->refcount.value += 1;
447 #endif
448 }
449
450 /**
451  * Like dbus_server_unref() but does not acquire the lock (must already be held)
452  *
453  * @param server the server.
454  */
455 void
456 _dbus_server_unref_unlocked (DBusServer *server)
457 {
458   dbus_bool_t last_unref;
459
460   /* Keep this in sync with dbus_server_unref */
461   
462   _dbus_assert (server != NULL);
463   _dbus_assert (server->refcount.value > 0);
464
465   HAVE_LOCK_CHECK (server);
466   
467 #ifdef DBUS_HAVE_ATOMIC_INT
468   last_unref = (_dbus_atomic_dec (&server->refcount) == 1);
469 #else
470   _dbus_assert (server->refcount.value > 0);
471
472   server->refcount.value -= 1;
473   last_unref = (server->refcount.value == 0);
474 #endif
475   
476   if (last_unref)
477     {
478       _dbus_assert (server->disconnected);
479       
480       SERVER_UNLOCK (server);
481       
482       _dbus_assert (server->vtable->finalize != NULL);
483       
484       (* server->vtable->finalize) (server);
485     }
486 }
487
488 /** @} */
489
490 /**
491  * @addtogroup DBusServer
492  *
493  * @{
494  */
495
496
497 /**
498  * @typedef DBusServer
499  *
500  * An opaque object representing a server that listens for
501  * connections from other applications. Each time a connection
502  * is made, a new DBusConnection is created and made available
503  * via an application-provided DBusNewConnectionFunction.
504  * The DBusNewConnectionFunction is provided with
505  * dbus_server_set_new_connection_function().
506  * 
507  */
508
509 static const struct {
510   DBusServerListenResult (* func) (DBusAddressEntry *entry,
511                                    DBusServer      **server_p,
512                                    DBusError        *error);
513 } listen_funcs[] = {
514   { _dbus_server_listen_socket }
515   , { _dbus_server_listen_platform_specific }
516 #ifdef DBUS_BUILD_TESTS
517   , { _dbus_server_listen_debug_pipe }
518 #endif
519 };
520
521 /**
522  * Listens for new connections on the given address.  If there are
523  * multiple semicolon-separated address entries in the address, tries
524  * each one and listens on the first one that works.
525  * 
526  * Returns #NULL and sets error if listening fails for any reason.
527  * Otherwise returns a new #DBusServer.
528  * dbus_server_set_new_connection_function(),
529  * dbus_server_set_watch_functions(), and
530  * dbus_server_set_timeout_functions() should be called immediately to
531  * render the server fully functional.
532  *
533  * To free the server, applications must call first
534  * dbus_server_disconnect() and then dbus_server_unref().
535  * 
536  * @param address the address of this server.
537  * @param error location to store reason for failure.
538  * @returns a new #DBusServer, or #NULL on failure.
539  * 
540  */
541 DBusServer*
542 dbus_server_listen (const char     *address,
543                     DBusError      *error)
544 {
545   DBusServer *server;
546   DBusAddressEntry **entries;
547   int len, i;
548   DBusError first_connect_error = DBUS_ERROR_INIT;
549   dbus_bool_t handled_once;
550   
551   _dbus_return_val_if_fail (address != NULL, NULL);
552   _dbus_return_val_if_error_is_set (error, NULL);
553   
554   if (!dbus_parse_address (address, &entries, &len, error))
555     return NULL;
556
557   server = NULL;
558   handled_once = FALSE;
559
560   for (i = 0; i < len; i++)
561     {
562       int j;
563
564       for (j = 0; j < (int) _DBUS_N_ELEMENTS (listen_funcs); ++j)
565         {
566           DBusServerListenResult result;
567           DBusError tmp_error = DBUS_ERROR_INIT;
568
569           result = (* listen_funcs[j].func) (entries[i],
570                                              &server,
571                                              &tmp_error);
572
573           if (result == DBUS_SERVER_LISTEN_OK)
574             {
575               _dbus_assert (server != NULL);
576               _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
577               handled_once = TRUE;
578               goto out;
579             }
580           else if (result == DBUS_SERVER_LISTEN_ADDRESS_ALREADY_USED)
581             {
582               _dbus_assert (server == NULL);
583               dbus_set_error (error,
584                        DBUS_ERROR_ADDRESS_IN_USE,
585                        "Address '%s' already used",
586                        dbus_address_entry_get_method (entries[0]));
587               handled_once = TRUE;
588               goto out;
589             }
590           else if (result == DBUS_SERVER_LISTEN_BAD_ADDRESS)
591             {
592               _dbus_assert (server == NULL);
593               _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
594               dbus_move_error (&tmp_error, error);
595               handled_once = TRUE;
596               goto out;
597             }
598           else if (result == DBUS_SERVER_LISTEN_NOT_HANDLED)
599             {
600               _dbus_assert (server == NULL);
601               _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
602
603               /* keep trying addresses */
604             }
605           else if (result == DBUS_SERVER_LISTEN_DID_NOT_CONNECT)
606             {
607               _dbus_assert (server == NULL);
608               _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
609               if (!dbus_error_is_set (&first_connect_error))
610                 dbus_move_error (&tmp_error, &first_connect_error);
611               else
612                 dbus_error_free (&tmp_error);
613
614               handled_once = TRUE;
615               
616               /* keep trying addresses */
617             }
618         }
619
620       _dbus_assert (server == NULL);
621       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
622     }
623
624  out:
625
626   if (!handled_once)
627     {
628       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
629       if (len > 0)
630         dbus_set_error (error,
631                        DBUS_ERROR_BAD_ADDRESS,
632                        "Unknown address type '%s'",
633                        dbus_address_entry_get_method (entries[0]));
634       else
635         dbus_set_error (error,
636                         DBUS_ERROR_BAD_ADDRESS,
637                         "Empty address '%s'",
638                         address);
639     }
640   
641   dbus_address_entries_free (entries);
642
643   if (server == NULL)
644     {
645       _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error) ||
646                    dbus_error_is_set (error));
647       
648       if (error && dbus_error_is_set (error))
649         {
650           /* already set the error */
651         }
652       else
653         {
654           /* didn't set the error but either error should be
655            * NULL or first_connect_error should be set.
656            */
657           _dbus_assert (error == NULL || dbus_error_is_set (&first_connect_error));
658           dbus_move_error (&first_connect_error, error);
659         }
660
661       _DBUS_ASSERT_ERROR_IS_CLEAR (&first_connect_error); /* be sure we freed it */
662       _DBUS_ASSERT_ERROR_IS_SET (error);
663
664       return NULL;
665     }
666   else
667     {
668       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
669       return server;
670     }
671 }
672
673 /**
674  * Increments the reference count of a DBusServer.
675  *
676  * @param server the server.
677  * @returns the server
678  */
679 DBusServer *
680 dbus_server_ref (DBusServer *server)
681 {
682   _dbus_return_val_if_fail (server != NULL, NULL);
683   _dbus_return_val_if_fail (server->refcount.value > 0, NULL);
684
685 #ifdef DBUS_HAVE_ATOMIC_INT
686   _dbus_atomic_inc (&server->refcount);
687 #else
688   SERVER_LOCK (server);
689   _dbus_assert (server->refcount.value > 0);
690
691   server->refcount.value += 1;
692   SERVER_UNLOCK (server);
693 #endif
694
695   return server;
696 }
697
698 /**
699  * Decrements the reference count of a DBusServer.  Finalizes the
700  * server if the reference count reaches zero.
701  *
702  * The server must be disconnected before the refcount reaches zero.
703  *
704  * @param server the server.
705  */
706 void
707 dbus_server_unref (DBusServer *server)
708 {
709   dbus_bool_t last_unref;
710
711   /* keep this in sync with unref_unlocked */
712   
713   _dbus_return_if_fail (server != NULL);
714   _dbus_return_if_fail (server->refcount.value > 0);
715
716 #ifdef DBUS_HAVE_ATOMIC_INT
717   last_unref = (_dbus_atomic_dec (&server->refcount) == 1);
718 #else
719   SERVER_LOCK (server);
720   
721   _dbus_assert (server->refcount.value > 0);
722
723   server->refcount.value -= 1;
724   last_unref = (server->refcount.value == 0);
725   
726   SERVER_UNLOCK (server);
727 #endif
728   
729   if (last_unref)
730     {
731       /* lock not held! */
732       _dbus_assert (server->disconnected);
733       
734       _dbus_assert (server->vtable->finalize != NULL);
735       
736       (* server->vtable->finalize) (server);
737     }
738 }
739
740 /**
741  * Releases the server's address and stops listening for
742  * new clients. If called more than once, only the first
743  * call has an effect. Does not modify the server's
744  * reference count.
745  * 
746  * @param server the server.
747  */
748 void
749 dbus_server_disconnect (DBusServer *server)
750 {
751   _dbus_return_if_fail (server != NULL);
752   _dbus_return_if_fail (server->refcount.value > 0);
753
754   SERVER_LOCK (server);
755   _dbus_server_ref_unlocked (server);
756   
757   _dbus_assert (server->vtable->disconnect != NULL);
758
759   if (!server->disconnected)
760     {
761       /* this has to be first so recursive calls to disconnect don't happen */
762       server->disconnected = TRUE;
763       
764       (* server->vtable->disconnect) (server);
765     }
766
767   SERVER_UNLOCK (server);
768   dbus_server_unref (server);
769 }
770
771 /**
772  * Returns #TRUE if the server is still listening for new connections.
773  *
774  * @param server the server.
775  */
776 dbus_bool_t
777 dbus_server_get_is_connected (DBusServer *server)
778 {
779   dbus_bool_t retval;
780   
781   _dbus_return_val_if_fail (server != NULL, FALSE);
782
783   SERVER_LOCK (server);
784   retval = !server->disconnected;
785   SERVER_UNLOCK (server);
786
787   return retval;
788 }
789
790 /**
791  * Returns the address of the server, as a newly-allocated
792  * string which must be freed by the caller.
793  *
794  * @param server the server
795  * @returns the address or #NULL if no memory
796  */
797 char*
798 dbus_server_get_address (DBusServer *server)
799 {
800   char *retval;
801   
802   _dbus_return_val_if_fail (server != NULL, NULL);
803
804   SERVER_LOCK (server);
805   retval = _dbus_strdup (server->address);
806   SERVER_UNLOCK (server);
807
808   return retval;
809 }
810
811 /**
812  * Returns the unique ID of the server, as a newly-allocated
813  * string which must be freed by the caller. This ID is
814  * normally used by clients to tell when two #DBusConnection
815  * would be equivalent (because the server address passed
816  * to dbus_connection_open() will have the same guid in the
817  * two cases). dbus_connection_open() can re-use an existing
818  * connection with the same ID instead of opening a new
819  * connection.
820  *
821  * This is an ID unique to each #DBusServer. Remember that
822  * a #DBusServer represents only one mode of connecting,
823  * so e.g. a bus daemon can listen on multiple addresses
824  * which will mean it has multiple #DBusServer each with
825  * their own ID.
826  *
827  * The ID is not a UUID in the sense of RFC4122; the details
828  * are explained in the D-Bus specification.
829  *
830  * @param server the server
831  * @returns the id of the server or #NULL if no memory
832  */
833 char*
834 dbus_server_get_id (DBusServer *server)
835 {
836   char *retval;
837   
838   _dbus_return_val_if_fail (server != NULL, NULL);
839
840   SERVER_LOCK (server);
841   retval = NULL;
842   _dbus_string_copy_data (&server->guid_hex, &retval);
843   SERVER_UNLOCK (server);
844
845   return retval;
846 }
847
848 /**
849  * Sets a function to be used for handling new connections.  The given
850  * function is passed each new connection as the connection is
851  * created. If the new connection function increments the connection's
852  * reference count, the connection will stay alive. Otherwise, the
853  * connection will be unreferenced and closed. The new connection
854  * function may also close the connection itself, which is considered
855  * good form if the connection is not wanted.
856  *
857  * The connection here is private in the sense of
858  * dbus_connection_open_private(), so if the new connection function
859  * keeps a reference it must arrange for the connection to be closed.
860  * i.e. libdbus does not own this connection once the new connection
861  * function takes a reference.
862  *
863  * @param server the server.
864  * @param function a function to handle new connections.
865  * @param data data to pass to the new connection handler.
866  * @param free_data_function function to free the data.
867  */
868 void
869 dbus_server_set_new_connection_function (DBusServer                *server,
870                                          DBusNewConnectionFunction  function,
871                                          void                      *data,
872                                          DBusFreeFunction           free_data_function)
873 {
874   DBusFreeFunction old_free_function;
875   void *old_data;
876   
877   _dbus_return_if_fail (server != NULL);
878
879   SERVER_LOCK (server);
880   old_free_function = server->new_connection_free_data_function;
881   old_data = server->new_connection_data;
882   
883   server->new_connection_function = function;
884   server->new_connection_data = data;
885   server->new_connection_free_data_function = free_data_function;
886   SERVER_UNLOCK (server);
887     
888   if (old_free_function != NULL)
889     (* old_free_function) (old_data);
890 }
891
892 /**
893  * Sets the watch functions for the server. These functions are
894  * responsible for making the application's main loop aware of file
895  * descriptors that need to be monitored for events.
896  *
897  * This function behaves exactly like dbus_connection_set_watch_functions();
898  * see the documentation for that routine.
899  *
900  * @param server the server.
901  * @param add_function function to begin monitoring a new descriptor.
902  * @param remove_function function to stop monitoring a descriptor.
903  * @param toggled_function function to notify when the watch is enabled/disabled
904  * @param data data to pass to add_function and remove_function.
905  * @param free_data_function function to be called to free the data.
906  * @returns #FALSE on failure (no memory)
907  */
908 dbus_bool_t
909 dbus_server_set_watch_functions (DBusServer              *server,
910                                  DBusAddWatchFunction     add_function,
911                                  DBusRemoveWatchFunction  remove_function,
912                                  DBusWatchToggledFunction toggled_function,
913                                  void                    *data,
914                                  DBusFreeFunction         free_data_function)
915 {
916   dbus_bool_t result;
917   DBusWatchList *watches;
918   
919   _dbus_return_val_if_fail (server != NULL, FALSE);
920
921   SERVER_LOCK (server);
922   watches = server->watches;
923   server->watches = NULL;
924   if (watches)
925     {
926       SERVER_UNLOCK (server);
927       result = _dbus_watch_list_set_functions (watches,
928                                                add_function,
929                                                remove_function,
930                                                toggled_function,
931                                                data,
932                                                free_data_function);
933       SERVER_LOCK (server);
934     }
935   else
936     {
937       _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
938       result = FALSE;
939     }
940   server->watches = watches;
941   SERVER_UNLOCK (server);
942   
943   return result;
944 }
945
946 /**
947  * Sets the timeout functions for the server. These functions are
948  * responsible for making the application's main loop aware of timeouts.
949  *
950  * This function behaves exactly like dbus_connection_set_timeout_functions();
951  * see the documentation for that routine.
952  *
953  * @param server the server.
954  * @param add_function function to add a timeout.
955  * @param remove_function function to remove a timeout.
956  * @param toggled_function function to notify when the timeout is enabled/disabled
957  * @param data data to pass to add_function and remove_function.
958  * @param free_data_function function to be called to free the data.
959  * @returns #FALSE on failure (no memory)
960  */
961 dbus_bool_t
962 dbus_server_set_timeout_functions (DBusServer                *server,
963                                    DBusAddTimeoutFunction     add_function,
964                                    DBusRemoveTimeoutFunction  remove_function,
965                                    DBusTimeoutToggledFunction toggled_function,
966                                    void                      *data,
967                                    DBusFreeFunction           free_data_function)
968 {
969   dbus_bool_t result;
970   DBusTimeoutList *timeouts;
971   
972   _dbus_return_val_if_fail (server != NULL, FALSE);
973
974   SERVER_LOCK (server);
975   timeouts = server->timeouts;
976   server->timeouts = NULL;
977   if (timeouts)
978     {
979       SERVER_UNLOCK (server);
980       result = _dbus_timeout_list_set_functions (timeouts,
981                                                  add_function,
982                                                  remove_function,
983                                                  toggled_function,
984                                                  data,
985                                                  free_data_function);
986       SERVER_LOCK (server);
987     }
988   else
989     {
990       _dbus_warn_check_failed ("Re-entrant call to %s\n", _DBUS_FUNCTION_NAME);
991       result = FALSE;
992     }
993   server->timeouts = timeouts;
994   SERVER_UNLOCK (server);
995   
996   return result;
997 }
998
999 /**
1000  * Sets the authentication mechanisms that this server offers to
1001  * clients, as a #NULL-terminated array of mechanism names. This
1002  * function only affects connections created <em>after</em> it is
1003  * called.  Pass #NULL instead of an array to use all available
1004  * mechanisms (this is the default behavior).
1005  *
1006  * The D-Bus specification describes some of the supported mechanisms.
1007  *
1008  * @param server the server
1009  * @param mechanisms #NULL-terminated array of mechanisms
1010  * @returns #FALSE if no memory
1011  */
1012 dbus_bool_t
1013 dbus_server_set_auth_mechanisms (DBusServer  *server,
1014                                  const char **mechanisms)
1015 {
1016   char **copy;
1017
1018   _dbus_return_val_if_fail (server != NULL, FALSE);
1019
1020   SERVER_LOCK (server);
1021   
1022   if (mechanisms != NULL)
1023     {
1024       copy = _dbus_dup_string_array (mechanisms);
1025       if (copy == NULL)
1026         return FALSE;
1027     }
1028   else
1029     copy = NULL;
1030
1031   dbus_free_string_array (server->auth_mechanisms);
1032   server->auth_mechanisms = copy;
1033
1034   SERVER_UNLOCK (server);
1035   
1036   return TRUE;
1037 }
1038
1039
1040 static DBusDataSlotAllocator slot_allocator;
1041 _DBUS_DEFINE_GLOBAL_LOCK (server_slots);
1042
1043 /**
1044  * Allocates an integer ID to be used for storing application-specific
1045  * data on any DBusServer. The allocated ID may then be used
1046  * with dbus_server_set_data() and dbus_server_get_data().
1047  * The slot must be initialized with -1. If a nonnegative
1048  * slot is passed in, the refcount is incremented on that
1049  * slot, rather than creating a new slot.
1050  *  
1051  * The allocated slot is global, i.e. all DBusServer objects will have
1052  * a slot with the given integer ID reserved.
1053  *
1054  * @param slot_p address of global variable storing the slot ID
1055  * @returns #FALSE on no memory
1056  */
1057 dbus_bool_t
1058 dbus_server_allocate_data_slot (dbus_int32_t *slot_p)
1059 {
1060   return _dbus_data_slot_allocator_alloc (&slot_allocator,
1061                                           (DBusMutex **)&_DBUS_LOCK_NAME (server_slots),
1062                                           slot_p);
1063 }
1064
1065 /**
1066  * Deallocates a global ID for server data slots.
1067  * dbus_server_get_data() and dbus_server_set_data()
1068  * may no longer be used with this slot.
1069  * Existing data stored on existing DBusServer objects
1070  * will be freed when the server is finalized,
1071  * but may not be retrieved (and may only be replaced
1072  * if someone else reallocates the slot).
1073  *
1074  * @param slot_p address of the slot to deallocate
1075  */
1076 void
1077 dbus_server_free_data_slot (dbus_int32_t *slot_p)
1078 {
1079   _dbus_return_if_fail (*slot_p >= 0);
1080   
1081   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
1082 }
1083
1084 /**
1085  * Stores a pointer on a DBusServer, along
1086  * with an optional function to be used for freeing
1087  * the data when the data is set again, or when
1088  * the server is finalized. The slot number
1089  * must have been allocated with dbus_server_allocate_data_slot().
1090  *
1091  * @param server the server
1092  * @param slot the slot number
1093  * @param data the data to store
1094  * @param free_data_func finalizer function for the data
1095  * @returns #TRUE if there was enough memory to store the data
1096  */
1097 dbus_bool_t
1098 dbus_server_set_data (DBusServer       *server,
1099                       int               slot,
1100                       void             *data,
1101                       DBusFreeFunction  free_data_func)
1102 {
1103   DBusFreeFunction old_free_func;
1104   void *old_data;
1105   dbus_bool_t retval;
1106
1107   _dbus_return_val_if_fail (server != NULL, FALSE);
1108
1109   SERVER_LOCK (server);
1110   
1111   retval = _dbus_data_slot_list_set (&slot_allocator,
1112                                      &server->slot_list,
1113                                      slot, data, free_data_func,
1114                                      &old_free_func, &old_data);
1115
1116
1117   SERVER_UNLOCK (server);
1118   
1119   if (retval)
1120     {
1121       /* Do the actual free outside the server lock */
1122       if (old_free_func)
1123         (* old_free_func) (old_data);
1124     }
1125
1126   return retval;
1127 }
1128
1129 /**
1130  * Retrieves data previously set with dbus_server_set_data().
1131  * The slot must still be allocated (must not have been freed).
1132  *
1133  * @param server the server
1134  * @param slot the slot to get data from
1135  * @returns the data, or #NULL if not found
1136  */
1137 void*
1138 dbus_server_get_data (DBusServer   *server,
1139                       int           slot)
1140 {
1141   void *res;
1142
1143   _dbus_return_val_if_fail (server != NULL, NULL);
1144   
1145   SERVER_LOCK (server);
1146   
1147   res = _dbus_data_slot_list_get (&slot_allocator,
1148                                   &server->slot_list,
1149                                   slot);
1150
1151   SERVER_UNLOCK (server);
1152   
1153   return res;
1154 }
1155
1156 /** @} */
1157
1158 #ifdef DBUS_BUILD_TESTS
1159 #include "dbus-test.h"
1160 #include <string.h>
1161
1162 dbus_bool_t
1163 _dbus_server_test (void)
1164 {
1165   const char *valid_addresses[] = {
1166     "tcp:port=1234",
1167     "tcp:host=localhost,port=1234",
1168     "tcp:host=localhost,port=1234;tcp:port=5678",
1169 #ifdef DBUS_UNIX
1170     "unix:path=./boogie",
1171     "tcp:port=1234;unix:path=./boogie",
1172 #endif
1173   };
1174
1175   DBusServer *server;
1176   int i;
1177   
1178   for (i = 0; i < _DBUS_N_ELEMENTS (valid_addresses); i++)
1179     {
1180       DBusError error = DBUS_ERROR_INIT;
1181       char *address;
1182       char *id;
1183
1184       server = dbus_server_listen (valid_addresses[i], &error);
1185       if (server == NULL)
1186         {
1187           _dbus_warn ("server listen error: %s: %s\n", error.name, error.message);
1188           dbus_error_free (&error);
1189           _dbus_assert_not_reached ("Failed to listen for valid address.");
1190         }
1191
1192       id = dbus_server_get_id (server);
1193       _dbus_assert (id != NULL);
1194       address = dbus_server_get_address (server);
1195       _dbus_assert (address != NULL);
1196
1197       if (strstr (address, id) == NULL)
1198         {
1199           _dbus_warn ("server id '%s' is not in the server address '%s'\n",
1200                       id, address);
1201           _dbus_assert_not_reached ("bad server id or address");
1202         }
1203
1204       dbus_free (id);
1205       dbus_free (address);
1206       
1207       dbus_server_disconnect (server);
1208       dbus_server_unref (server);
1209     }
1210
1211   return TRUE;
1212 }
1213
1214 #endif /* DBUS_BUILD_TESTS */