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