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