dbus-server.c revision 7265423411609c14ddb9e6643463b840afcaa09b
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 */ 396void 397dbus_server_set_watch_functions (DBusServer *server, 398 DBusAddWatchFunction add_function, 399 DBusRemoveWatchFunction remove_function, 400 void *data, 401 DBusFreeFunction free_data_function) 402{ 403 _dbus_watch_list_set_functions (server->watches, 404 add_function, 405 remove_function, 406 data, 407 free_data_function); 408} 409 410/** 411 * Sets the timeout functions for the connection. These functions are 412 * responsible for making the application's main loop aware of timeouts. 413 * 414 * This function behaves exactly like dbus_connection_set_timeout_functions(); 415 * see the documentation for that routine. 416 * 417 * @param server the server. 418 * @param add_function function to add a timeout. 419 * @param remove_function function to remove a timeout. 420 * @param data data to pass to add_function and remove_function. 421 * @param free_data_function function to be called to free the data. 422 */ 423void 424dbus_server_set_timeout_functions (DBusServer *server, 425 DBusAddTimeoutFunction add_function, 426 DBusRemoveTimeoutFunction remove_function, 427 void *data, 428 DBusFreeFunction free_data_function) 429{ 430 _dbus_timeout_list_set_functions (server->timeouts, 431 add_function, remove_function, 432 data, free_data_function); 433} 434 435/** 436 * Called to notify the server when a previously-added watch 437 * is ready for reading or writing, or has an exception such 438 * as a hangup. 439 * 440 * @param server the server. 441 * @param watch the watch. 442 * @param condition the current condition of the file descriptors being watched. 443 */ 444void 445dbus_server_handle_watch (DBusServer *server, 446 DBusWatch *watch, 447 unsigned int condition) 448{ 449 _dbus_assert (server->vtable->handle_watch != NULL); 450 451 _dbus_watch_sanitize_condition (watch, &condition); 452 453 (* server->vtable->handle_watch) (server, watch, condition); 454} 455 456/** 457 * Sets the maximum number of connections that can be open at one 458 * time for this server. If the maximum is reached, and another 459 * client tries to connect, then the oldest unauthenticated client 460 * will be dropped. If no unauthenticated client exists, then 461 * the new connection will be refused. 462 * 463 * If the maximum is set to a number lower than the current 464 * number of connections, no current connections are 465 * disconnected. 466 * 467 * @todo honoring max_connections has not been implemented 468 * yet. The only real work involved is keeping a list 469 * of live connections on the DBusServer so the oldest 470 * unauthenticated client can be located when required. 471 * 472 * @todo for a systemwide daemon, we need a max number of connections 473 * per user, since any user can authenticate a bunch of connections 474 * and create a DOS. 475 * 476 * @todo a single process might listen on multiple mechanisms 477 * (multiple DBusServer) and might want the max connections 478 * value to span all those servers. Should consider 479 * changing the API accordingly, though I'm inclined to 480 * punt this to the app that wants to do it instead of 481 * putting it in the library. 482 * 483 * @param server the server 484 * @param max_connections maximum number of connections allowed 485 */ 486void 487dbus_server_set_max_connections (DBusServer *server, 488 int max_connections) 489{ 490 server->max_connections = max_connections; 491} 492 493/** 494 * Gets the maximum number of connections that can be active 495 * at a time for this server. 496 * 497 * @param server the server 498 * @returns maximum number of connections at once 499 */ 500int 501dbus_server_get_max_connections (DBusServer *server) 502{ 503 return server->max_connections; 504} 505 506/** 507 * Gets the number of #DBusConnection to this server that 508 * have not yet been finalized. i.e. all #DBusConnection that 509 * were passed to #DBusNewConnectionFunction and have not yet been 510 * finalized will count in this total. 511 * 512 * @param server the server 513 * @returns the number of connections 514 */ 515int 516dbus_server_get_n_connections (DBusServer *server) 517{ 518 return _dbus_counter_get_value (server->connection_counter); 519} 520 521 522static DBusDataSlotAllocator slot_allocator; 523 524/** 525 * Initialize the mutex used for #DBusConnection data 526 * slot reservations. 527 * 528 * @returns the mutex 529 */ 530DBusMutex * 531_dbus_server_slots_init_lock (void) 532{ 533 if (!_dbus_data_slot_allocator_init (&slot_allocator)) 534 return NULL; 535 else 536 return slot_allocator.lock; 537} 538 539/** 540 * Allocates an integer ID to be used for storing application-specific 541 * data on any DBusServer. The allocated ID may then be used 542 * with dbus_server_set_data() and dbus_server_get_data(). 543 * If allocation fails, -1 is returned. Again, the allocated 544 * slot is global, i.e. all DBusServer objects will 545 * have a slot with the given integer ID reserved. 546 * 547 * @returns -1 on failure, otherwise the data slot ID 548 */ 549int 550dbus_server_allocate_data_slot (void) 551{ 552 return _dbus_data_slot_allocator_alloc (&slot_allocator); 553} 554 555/** 556 * Deallocates a global ID for server data slots. 557 * dbus_server_get_data() and dbus_server_set_data() 558 * may no longer be used with this slot. 559 * Existing data stored on existing DBusServer objects 560 * will be freed when the server is finalized, 561 * but may not be retrieved (and may only be replaced 562 * if someone else reallocates the slot). 563 * 564 * @param slot the slot to deallocate 565 */ 566void 567dbus_server_free_data_slot (int slot) 568{ 569 _dbus_data_slot_allocator_free (&slot_allocator, slot); 570} 571 572/** 573 * Stores a pointer on a DBusServer, along 574 * with an optional function to be used for freeing 575 * the data when the data is set again, or when 576 * the server is finalized. The slot number 577 * must have been allocated with dbus_server_allocate_data_slot(). 578 * 579 * @param server the server 580 * @param slot the slot number 581 * @param data the data to store 582 * @param free_data_func finalizer function for the data 583 * @returns #TRUE if there was enough memory to store the data 584 */ 585dbus_bool_t 586dbus_server_set_data (DBusServer *server, 587 int slot, 588 void *data, 589 DBusFreeFunction free_data_func) 590{ 591 DBusFreeFunction old_free_func; 592 void *old_data; 593 dbus_bool_t retval; 594 595#if 0 596 dbus_mutex_lock (server->mutex); 597#endif 598 599 retval = _dbus_data_slot_list_set (&slot_allocator, 600 &server->slot_list, 601 slot, data, free_data_func, 602 &old_free_func, &old_data); 603 604#if 0 605 dbus_mutex_unlock (server->mutex); 606#endif 607 608 if (retval) 609 { 610 /* Do the actual free outside the server lock */ 611 if (old_free_func) 612 (* old_free_func) (old_data); 613 } 614 615 return retval; 616} 617 618/** 619 * Retrieves data previously set with dbus_server_set_data(). 620 * The slot must still be allocated (must not have been freed). 621 * 622 * @param server the server 623 * @param slot the slot to get data from 624 * @returns the data, or #NULL if not found 625 */ 626void* 627dbus_server_get_data (DBusServer *server, 628 int slot) 629{ 630 void *res; 631 632#if 0 633 dbus_mutex_lock (server->mutex); 634#endif 635 636 res = _dbus_data_slot_list_get (&slot_allocator, 637 &server->slot_list, 638 slot); 639 640#if 0 641 dbus_mutex_unlock (server->mutex); 642#endif 643 644 return res; 645} 646 647/** @} */ 648 649