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