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