2003-03-24 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / dbus / dbus-server.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-server.c DBusServer 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-server.h"
25 #include "dbus-server-unix.h"
26 #ifdef DBUS_BUILD_TESTS
27 #include "dbus-server-debug.h"
28 #include "dbus-server-debug-pipe.h"
29 #endif
30 #include "dbus-address.h"
31
32 /**
33  * @defgroup DBusServer DBusServer
34  * @ingroup  DBus
35  * @brief Server that listens for new connections.
36  *
37  * Types and functions related to DBusServer.
38  * A DBusServer represents a server that other applications
39  * can connect to. Each connection from another application
40  * is represented by a DBusConnection.
41  *
42  * @todo Thread safety hasn't been looked at for #DBusServer
43  * @todo Need notification to apps of disconnection, may matter for some transports
44  */
45
46 /**
47  * @defgroup DBusServerInternals DBusServer implementation details
48  * @ingroup  DBusInternals
49  * @brief Implementation details of DBusServer
50  *
51  * @{
52  */
53
54 /**
55  * Initializes the members of the DBusServer base class.
56  * Chained up to by subclass constructors.
57  *
58  * @param server the server.
59  * @param vtable the vtable for the subclass.
60  * @returns #TRUE on success.
61  */
62 dbus_bool_t
63 _dbus_server_init_base (DBusServer             *server,
64                         const DBusServerVTable *vtable)
65 {
66   server->vtable = vtable;
67   server->refcount = 1;
68
69   server->watches = _dbus_watch_list_new ();
70   if (server->watches == NULL)
71     return FALSE;
72
73   server->timeouts = _dbus_timeout_list_new ();
74   if (server->timeouts == NULL)
75     {
76       _dbus_watch_list_free (server->watches);
77       server->watches = NULL;
78       return FALSE;
79     }
80   
81   server->connection_counter = _dbus_counter_new ();
82   if (server->connection_counter == NULL)
83     {
84       _dbus_watch_list_free (server->watches);
85       server->watches = NULL;
86       _dbus_timeout_list_free (server->timeouts);
87       server->timeouts = NULL;
88       
89       return FALSE;
90     }
91
92   server->max_connections = 256; /* same as an X server, seems like a nice default */
93
94   _dbus_data_slot_list_init (&server->slot_list);
95   
96   return TRUE;
97 }
98
99 /**
100  * Finalizes the members of the DBusServer base class.
101  * Chained up to by subclass finalizers.
102  *
103  * @param server the server.
104  */
105 void
106 _dbus_server_finalize_base (DBusServer *server)
107 {
108   /* calls out to application code... */
109   _dbus_data_slot_list_free (&server->slot_list);
110
111   dbus_server_set_new_connection_function (server, NULL, NULL, NULL);
112
113   if (!server->disconnected)
114     dbus_server_disconnect (server);
115
116   _dbus_watch_list_free (server->watches);
117   _dbus_timeout_list_free (server->timeouts);
118   _dbus_counter_unref (server->connection_counter);
119 }
120
121 /**
122  * Adds a watch for this server, chaining out to application-provided
123  * watch handlers.
124  *
125  * @param server the server.
126  * @param watch the watch to add.
127  */
128 dbus_bool_t
129 _dbus_server_add_watch (DBusServer *server,
130                         DBusWatch  *watch)
131 {
132   return _dbus_watch_list_add_watch (server->watches, watch);
133 }
134
135 /**
136  * Removes a watch previously added with _dbus_server_remove_watch().
137  *
138  * @param server the server.
139  * @param watch the watch to remove.
140  */
141 void
142 _dbus_server_remove_watch  (DBusServer *server,
143                             DBusWatch  *watch)
144 {
145   _dbus_watch_list_remove_watch (server->watches, watch);
146 }
147
148 /**
149  * Toggles a watch and notifies app via server's
150  * DBusWatchToggledFunction if available. It's an error to call this
151  * function on a watch that was not previously added.
152  *
153  * @param server the server.
154  * @param watch the watch to toggle.
155  * @param enabled whether to enable or disable
156  */
157 void
158 _dbus_server_toggle_watch (DBusServer  *server,
159                            DBusWatch   *watch,
160                            dbus_bool_t  enabled)
161 {
162   if (server->watches) /* null during finalize */
163     _dbus_watch_list_toggle_watch (server->watches,
164                                    watch, enabled);
165 }
166
167 /**
168  * Adds a timeout for this server, chaining out to
169  * application-provided timeout handlers. The timeout should be
170  * repeatedly handled with dbus_timeout_handle() at its given interval
171  * until it is removed.
172  *
173  * @param server the server.
174  * @param timeout the timeout to add.
175  */
176 dbus_bool_t
177 _dbus_server_add_timeout (DBusServer  *server,
178                           DBusTimeout *timeout)
179 {
180   return _dbus_timeout_list_add_timeout (server->timeouts, timeout);
181 }
182
183 /**
184  * Removes a timeout previously added with _dbus_server_add_timeout().
185  *
186  * @param server the server.
187  * @param timeout the timeout to remove.
188  */
189 void
190 _dbus_server_remove_timeout (DBusServer  *server,
191                              DBusTimeout *timeout)
192 {
193   _dbus_timeout_list_remove_timeout (server->timeouts, timeout);  
194 }
195
196 /**
197  * Toggles a timeout and notifies app via server's
198  * DBusTimeoutToggledFunction if available. It's an error to call this
199  * function on a timeout that was not previously added.
200  *
201  * @param server the server.
202  * @param timeout the timeout to toggle.
203  * @param enabled whether to enable or disable
204  */
205 void
206 _dbus_server_toggle_timeout (DBusServer  *server,
207                              DBusTimeout *timeout,
208                              dbus_bool_t  enabled)
209 {
210   if (server->timeouts) /* null during finalize */
211     _dbus_timeout_list_toggle_timeout (server->timeouts,
212                                        timeout, enabled);
213 }
214
215
216 /** @} */
217
218 /**
219  * @addtogroup DBusServer
220  *
221  * @{
222  */
223
224
225 /**
226  * @typedef DBusServer
227  *
228  * An opaque object representing a server that listens for
229  * connections from other applications. Each time a connection
230  * is made, a new DBusConnection is created and made available
231  * via an application-provided DBusNewConnectionFunction.
232  * The DBusNewConnectionFunction is provided with
233  * dbus_server_set_new_connection_function().
234  * 
235  */
236
237 /**
238  * Listens for new connections on the given address.
239  * Returns #NULL if listening fails for any reason.
240  * Otherwise returns a new #DBusServer.
241  * dbus_server_set_new_connection_function() and
242  * dbus_server_set_watch_functions() should be called
243  * immediately to render the server fully functional.
244  *
245  * @todo error messages on bad address could really be better.
246  * DBusResultCode is a bit limiting here.
247  *
248  * @param address the address of this server.
249  * @param error location to store rationale for failure.
250  * @returns a new DBusServer, or #NULL on failure.
251  * 
252  */
253 DBusServer*
254 dbus_server_listen (const char     *address,
255                     DBusError      *error)
256 {
257   DBusServer *server;
258   DBusAddressEntry **entries;
259   int len, i;
260   const char *address_problem_type;
261   const char *address_problem_field;
262   const char *address_problem_other;
263
264   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
265   
266   if (!dbus_parse_address (address, &entries, &len, error))
267     return NULL;
268
269   server = NULL;
270   address_problem_type = NULL;
271   address_problem_field = NULL;
272   address_problem_other = NULL;
273   
274   for (i = 0; i < len; i++)
275     {
276       const char *method = dbus_address_entry_get_method (entries[i]);
277
278       if (strcmp (method, "unix") == 0)
279         {
280           const char *path = dbus_address_entry_get_value (entries[i], "path");
281
282           if (path == NULL)
283             {
284               address_problem_type = "unix";
285               address_problem_field = "path";
286               goto bad_address;
287             }
288
289           server = _dbus_server_new_for_domain_socket (path, error);
290
291           if (server)
292             break;
293         }
294       else if (strcmp (method, "tcp") == 0)
295         {
296           const char *host = dbus_address_entry_get_value (entries[i], "host");
297           const char *port = dbus_address_entry_get_value (entries[i], "port");
298           DBusString  str;
299           long lport;
300           dbus_bool_t sresult;
301           
302           if (port == NULL)
303             {
304               address_problem_type = "tcp";
305               address_problem_field = "port";
306               goto bad_address;
307             }
308
309           _dbus_string_init_const (&str, port);
310           sresult = _dbus_string_parse_int (&str, 0, &lport, NULL);
311           _dbus_string_free (&str);
312           
313           if (sresult == FALSE || lport <= 0 || lport > 65535)
314             {
315               address_problem_other = "Port is not an integer between 0 and 65535";
316               goto bad_address;
317             }
318           
319           server = _dbus_server_new_for_tcp_socket (host, lport, error);
320
321           if (server)
322             break;
323         }
324 #ifdef DBUS_BUILD_TESTS
325       else if (strcmp (method, "debug") == 0)
326         {
327           const char *name = dbus_address_entry_get_value (entries[i], "name");
328
329           if (name == NULL)
330             {
331               address_problem_type = "debug";
332               address_problem_field = "name";
333               goto bad_address;
334             }
335
336           server = _dbus_server_debug_new (name, error);
337
338           if (server)
339             break;
340         }
341       else if (strcmp (method, "debug-pipe") == 0)
342         {
343           const char *name = dbus_address_entry_get_value (entries[i], "name");
344
345           if (name == NULL)
346             {
347               address_problem_type = "debug-pipe";
348               address_problem_field = "name";
349               goto bad_address;
350             }
351
352           server = _dbus_server_debug_pipe_new (name, error);
353
354           if (server)
355             break;
356         }
357 #endif
358       else
359         {
360           address_problem_other = "Unknown address type (examples of valid types are \"unix\" and \"tcp\")";
361           goto bad_address;
362         }
363     }
364   
365   dbus_address_entries_free (entries);
366   return server;
367
368  bad_address:
369   dbus_address_entries_free (entries);
370   if (address_problem_type != NULL)
371     dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
372                     "Server address of type %s was missing argument %s",
373                     address_problem_type, address_problem_field);
374   else
375     dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
376                     "Could not parse server address: %s",
377                     address_problem_other);
378
379   return NULL;
380 }
381
382 /**
383  * Increments the reference count of a DBusServer.
384  *
385  * @param server the server.
386  */
387 void
388 dbus_server_ref (DBusServer *server)
389 {
390   server->refcount += 1;
391 }
392
393 /**
394  * Decrements the reference count of a DBusServer.  Finalizes the
395  * server if the reference count reaches zero. The server connection
396  * will be closed as with dbus_server_disconnect() when the server is
397  * finalized.
398  *
399  * @param server the server.
400  */
401 void
402 dbus_server_unref (DBusServer *server)
403 {
404   _dbus_assert (server != NULL);
405   _dbus_assert (server->refcount > 0);
406
407   server->refcount -= 1;
408   if (server->refcount == 0)
409     {
410       _dbus_assert (server->vtable->finalize != NULL);
411       
412       (* server->vtable->finalize) (server);
413     }
414 }
415
416 /**
417  * Releases the server's address and stops listening for
418  * new clients. If called more than once, only the first
419  * call has an effect. Does not modify the server's
420  * reference count.
421  * 
422  * @param server the server.
423  */
424 void
425 dbus_server_disconnect (DBusServer *server)
426 {
427   _dbus_assert (server->vtable->disconnect != NULL);
428
429   if (server->disconnected)
430     return;
431   
432   (* server->vtable->disconnect) (server);
433   server->disconnected = TRUE;
434 }
435
436 /**
437  * Returns #TRUE if the server is still listening for new connections.
438  *
439  * @param server the server.
440  */
441 dbus_bool_t
442 dbus_server_get_is_connected (DBusServer *server)
443 {
444   return !server->disconnected;
445 }
446
447 /**
448  * Sets a function to be used for handling new connections.  The given
449  * function is passed each new connection as the connection is
450  * created. If the new connection function increments the connection's
451  * reference count, the connection will stay alive. Otherwise, the
452  * connection will be unreferenced and closed.
453  *
454  * @param server the server.
455  * @param function a function to handle new connections.
456  * @param data data to pass to the new connection handler.
457  * @param free_data_function function to free the data.
458  */
459 void
460 dbus_server_set_new_connection_function (DBusServer                *server,
461                                          DBusNewConnectionFunction  function,
462                                          void                      *data,
463                                          DBusFreeFunction           free_data_function)
464 {
465   if (server->new_connection_free_data_function != NULL)
466     (* server->new_connection_free_data_function) (server->new_connection_data);
467   
468   server->new_connection_function = function;
469   server->new_connection_data = data;
470   server->new_connection_free_data_function = free_data_function;
471 }
472
473 /**
474  * Sets the watch functions for the connection. These functions are
475  * responsible for making the application's main loop aware of file
476  * descriptors that need to be monitored for events.
477  *
478  * This function behaves exactly like dbus_connection_set_watch_functions();
479  * see the documentation for that routine.
480  *
481  * @param server the server.
482  * @param add_function function to begin monitoring a new descriptor.
483  * @param remove_function function to stop monitoring a descriptor.
484  * @param toggled_function function to notify when the watch is enabled/disabled
485  * @param data data to pass to add_function and remove_function.
486  * @param free_data_function function to be called to free the data.
487  * @returns #FALSE on failure (no memory)
488  */
489 dbus_bool_t
490 dbus_server_set_watch_functions (DBusServer              *server,
491                                  DBusAddWatchFunction     add_function,
492                                  DBusRemoveWatchFunction  remove_function,
493                                  DBusWatchToggledFunction toggled_function,
494                                  void                    *data,
495                                  DBusFreeFunction         free_data_function)
496 {
497   return _dbus_watch_list_set_functions (server->watches,
498                                          add_function,
499                                          remove_function,
500                                          toggled_function,
501                                          data,
502                                          free_data_function);
503 }
504
505 /**
506  * Sets the timeout functions for the connection. These functions are
507  * responsible for making the application's main loop aware of timeouts.
508  *
509  * This function behaves exactly like dbus_connection_set_timeout_functions();
510  * see the documentation for that routine.
511  *
512  * @param server the server.
513  * @param add_function function to add a timeout.
514  * @param remove_function function to remove a timeout.
515  * @param toggled_function function to notify when the timeout is enabled/disabled
516  * @param data data to pass to add_function and remove_function.
517  * @param free_data_function function to be called to free the data.
518  * @returns #FALSE on failure (no memory)
519  */
520 dbus_bool_t
521 dbus_server_set_timeout_functions (DBusServer                *server,
522                                    DBusAddTimeoutFunction     add_function,
523                                    DBusRemoveTimeoutFunction  remove_function,
524                                    DBusTimeoutToggledFunction toggled_function,
525                                    void                      *data,
526                                    DBusFreeFunction           free_data_function)
527 {
528   return _dbus_timeout_list_set_functions (server->timeouts,
529                                            add_function, remove_function,
530                                            toggled_function,
531                                            data, free_data_function); 
532 }
533
534 /**
535  * Called to notify the server when a previously-added watch
536  * is ready for reading or writing, or has an exception such
537  * as a hangup.
538  * 
539  * If this function returns #FALSE, then the file descriptor may still
540  * be ready for reading or writing, but more memory is needed in order
541  * to do the reading or writing. If you ignore the #FALSE return, your
542  * application may spin in a busy loop on the file descriptor until
543  * memory becomes available, but nothing more catastrophic should
544  * happen.
545  *
546  * @param server the server.
547  * @param watch the watch.
548  * @param condition the current condition of the file descriptors being watched.
549  */
550 dbus_bool_t
551 dbus_server_handle_watch (DBusServer              *server,
552                           DBusWatch               *watch,
553                           unsigned int             condition)
554 {
555   _dbus_assert (server->vtable->handle_watch != NULL);
556
557   _dbus_watch_sanitize_condition (watch, &condition);
558   
559   return (* server->vtable->handle_watch) (server, watch, condition);
560 }
561
562 /**
563  * Sets the maximum number of connections that can be open at one
564  * time for this server. If the maximum is reached, and another
565  * client tries to connect, then the oldest unauthenticated client
566  * will be dropped. If no unauthenticated client exists, then
567  * the new connection will be refused.
568  *
569  * If the maximum is set to a number lower than the current
570  * number of connections, no current connections are
571  * disconnected.
572  *
573  * @todo honoring max_connections has not been implemented
574  * yet. The only real work involved is keeping a list
575  * of live connections on the DBusServer so the oldest
576  * unauthenticated client can be located when required.
577  * 
578  * @todo for a systemwide daemon, we need a max number of connections
579  * per user, since any user can authenticate a bunch of connections
580  * and create a DOS.
581  *
582  * @todo a single process might listen on multiple mechanisms
583  * (multiple DBusServer) and might want the max connections
584  * value to span all those servers. Should consider
585  * changing the API accordingly, though I'm inclined to
586  * punt this to the app that wants to do it instead of
587  * putting it in the library.
588  * 
589  * @param server the server
590  * @param max_connections maximum number of connections allowed
591  */
592 void
593 dbus_server_set_max_connections (DBusServer *server,
594                                  int         max_connections)
595 {
596   server->max_connections = max_connections;
597 }
598
599 /**
600  * Gets the maximum number of connections that can be active
601  * at a time for this server.
602  *
603  * @param server the server
604  * @returns maximum number of connections at once
605  */
606 int
607 dbus_server_get_max_connections (DBusServer *server)
608 {
609   return server->max_connections;
610 }
611
612 /**
613  * Gets the number of #DBusConnection to this server that
614  * have not yet been finalized. i.e. all #DBusConnection that
615  * were passed to #DBusNewConnectionFunction and have not yet been
616  * finalized will count in this total.
617  *
618  * @param server the server
619  * @returns the number of connections
620  */
621 int
622 dbus_server_get_n_connections (DBusServer *server)
623 {
624   return _dbus_counter_get_value (server->connection_counter);
625 }
626
627
628 static DBusDataSlotAllocator slot_allocator;
629 _DBUS_DEFINE_GLOBAL_LOCK (server_slots);
630
631 /**
632  * Allocates an integer ID to be used for storing application-specific
633  * data on any DBusServer. The allocated ID may then be used
634  * with dbus_server_set_data() and dbus_server_get_data().
635  * If allocation fails, -1 is returned. Again, the allocated
636  * slot is global, i.e. all DBusServer objects will
637  * have a slot with the given integer ID reserved.
638  *
639  * @returns -1 on failure, otherwise the data slot ID
640  */
641 int
642 dbus_server_allocate_data_slot (void)
643 {
644   return _dbus_data_slot_allocator_alloc (&slot_allocator,
645                                           _DBUS_LOCK_NAME (server_slots));
646 }
647
648 /**
649  * Deallocates a global ID for server data slots.
650  * dbus_server_get_data() and dbus_server_set_data()
651  * may no longer be used with this slot.
652  * Existing data stored on existing DBusServer objects
653  * will be freed when the server is finalized,
654  * but may not be retrieved (and may only be replaced
655  * if someone else reallocates the slot).
656  *
657  * @param slot the slot to deallocate
658  */
659 void
660 dbus_server_free_data_slot (int slot)
661 {
662   _dbus_data_slot_allocator_free (&slot_allocator, slot);
663 }
664
665 /**
666  * Stores a pointer on a DBusServer, along
667  * with an optional function to be used for freeing
668  * the data when the data is set again, or when
669  * the server is finalized. The slot number
670  * must have been allocated with dbus_server_allocate_data_slot().
671  *
672  * @param server the server
673  * @param slot the slot number
674  * @param data the data to store
675  * @param free_data_func finalizer function for the data
676  * @returns #TRUE if there was enough memory to store the data
677  */
678 dbus_bool_t
679 dbus_server_set_data (DBusServer   *server,
680                       int               slot,
681                       void             *data,
682                       DBusFreeFunction  free_data_func)
683 {
684   DBusFreeFunction old_free_func;
685   void *old_data;
686   dbus_bool_t retval;
687
688 #if 0
689   dbus_mutex_lock (server->mutex);
690 #endif
691   
692   retval = _dbus_data_slot_list_set (&slot_allocator,
693                                      &server->slot_list,
694                                      slot, data, free_data_func,
695                                      &old_free_func, &old_data);
696
697 #if 0
698   dbus_mutex_unlock (server->mutex);
699 #endif
700   
701   if (retval)
702     {
703       /* Do the actual free outside the server lock */
704       if (old_free_func)
705         (* old_free_func) (old_data);
706     }
707
708   return retval;
709 }
710
711 /**
712  * Retrieves data previously set with dbus_server_set_data().
713  * The slot must still be allocated (must not have been freed).
714  *
715  * @param server the server
716  * @param slot the slot to get data from
717  * @returns the data, or #NULL if not found
718  */
719 void*
720 dbus_server_get_data (DBusServer   *server,
721                       int               slot)
722 {
723   void *res;
724   
725 #if 0
726   dbus_mutex_lock (server->mutex);
727 #endif
728   
729   res = _dbus_data_slot_list_get (&slot_allocator,
730                                   &server->slot_list,
731                                   slot);
732
733 #if 0
734   dbus_mutex_unlock (server->mutex);
735 #endif
736   
737   return res;
738 }
739
740 /** @} */
741