1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 2 /* dispatch.c Message dispatcher 3 * 4 * Copyright (C) 2003 CodeFactory AB 5 * Copyright (C) 2003, 2004, 2005 Red Hat, Inc. 6 * Copyright (C) 2004 Imendio HB 7 * 8 * Licensed under the Academic Free License version 2.1 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 23 * 24 */ 25 26 #include <config.h> 27 #include "dispatch.h" 28 #include "connection.h" 29 #include "driver.h" 30 #include "services.h" 31 #include "activation.h" 32 #include "utils.h" 33 #include "bus.h" 34 #include "signals.h" 35 #include "test.h" 36 #include <dbus/dbus-internals.h> 37 #include <string.h> 38 39 #ifdef HAVE_UNIX_FD_PASSING 40 #include <dbus/dbus-sysdeps-unix.h> 41 #include <unistd.h> 42 #endif 43 44 /* This is hard-coded in the files in valid-config-files-*. We have to use 45 * the debug-pipe transport because the tests in this file require that 46 * dbus_connection_open_private() does not block. */ 47 #define TEST_DEBUG_PIPE "debug-pipe:name=test-server" 48 49 static dbus_bool_t 50 send_one_message (DBusConnection *connection, 51 BusContext *context, 52 DBusConnection *sender, 53 DBusConnection *addressed_recipient, 54 DBusMessage *message, 55 BusTransaction *transaction, 56 DBusError *error) 57 { 58 if (!bus_context_check_security_policy (context, transaction, 59 sender, 60 addressed_recipient, 61 connection, 62 message, 63 NULL)) 64 return TRUE; /* silently don't send it */ 65 66 if (dbus_message_contains_unix_fds(message) && 67 !dbus_connection_can_send_type(connection, DBUS_TYPE_UNIX_FD)) 68 return TRUE; /* silently don't send it */ 69 70 if (!bus_transaction_send (transaction, 71 connection, 72 message)) 73 { 74 BUS_SET_OOM (error); 75 return FALSE; 76 } 77 78 return TRUE; 79 } 80 81 dbus_bool_t 82 bus_dispatch_matches (BusTransaction *transaction, 83 DBusConnection *sender, 84 DBusConnection *addressed_recipient, 85 DBusMessage *message, 86 DBusError *error) 87 { 88 DBusError tmp_error; 89 BusConnections *connections; 90 DBusList *recipients; 91 BusMatchmaker *matchmaker; 92 DBusList *link; 93 BusContext *context; 94 95 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 96 97 /* sender and recipient can both be NULL for the bus driver, 98 * or for signals with no particular recipient 99 */ 100 101 _dbus_assert (sender == NULL || bus_connection_is_active (sender)); 102 _dbus_assert (dbus_message_get_sender (message) != NULL); 103 104 context = bus_transaction_get_context (transaction); 105 106 /* First, send the message to the addressed_recipient, if there is one. */ 107 if (addressed_recipient != NULL) 108 { 109 if (!bus_context_check_security_policy (context, transaction, 110 sender, addressed_recipient, 111 addressed_recipient, 112 message, error)) 113 return FALSE; 114 115 if (dbus_message_contains_unix_fds (message) && 116 !dbus_connection_can_send_type (addressed_recipient, 117 DBUS_TYPE_UNIX_FD)) 118 { 119 dbus_set_error (error, 120 DBUS_ERROR_NOT_SUPPORTED, 121 "Tried to send message with Unix file descriptors" 122 "to a client that doesn't support that."); 123 return FALSE; 124 } 125 126 /* Dispatch the message */ 127 if (!bus_transaction_send (transaction, addressed_recipient, message)) 128 { 129 BUS_SET_OOM (error); 130 return FALSE; 131 } 132 } 133 134 /* Now dispatch to others who look interested in this message */ 135 connections = bus_transaction_get_connections (transaction); 136 dbus_error_init (&tmp_error); 137 matchmaker = bus_context_get_matchmaker (context); 138 139 recipients = NULL; 140 if (!bus_matchmaker_get_recipients (matchmaker, connections, 141 sender, addressed_recipient, message, 142 &recipients)) 143 { 144 BUS_SET_OOM (error); 145 return FALSE; 146 } 147 148 link = _dbus_list_get_first_link (&recipients); 149 while (link != NULL) 150 { 151 DBusConnection *dest; 152 153 dest = link->data; 154 155 if (!send_one_message (dest, context, sender, addressed_recipient, 156 message, transaction, &tmp_error)) 157 break; 158 159 link = _dbus_list_get_next_link (&recipients, link); 160 } 161 162 _dbus_list_clear (&recipients); 163 164 if (dbus_error_is_set (&tmp_error)) 165 { 166 dbus_move_error (&tmp_error, error); 167 return FALSE; 168 } 169 else 170 return TRUE; 171 } 172 173 static DBusHandlerResult 174 bus_dispatch (DBusConnection *connection, 175 DBusMessage *message) 176 { 177 const char *sender, *service_name; 178 DBusError error; 179 BusTransaction *transaction; 180 BusContext *context; 181 DBusHandlerResult result; 182 DBusConnection *addressed_recipient; 183 184 result = DBUS_HANDLER_RESULT_HANDLED; 185 186 transaction = NULL; 187 addressed_recipient = NULL; 188 dbus_error_init (&error); 189 190 context = bus_connection_get_context (connection); 191 _dbus_assert (context != NULL); 192 193 /* If we can't even allocate an OOM error, we just go to sleep 194 * until we can. 195 */ 196 while (!bus_connection_preallocate_oom_error (connection)) 197 _dbus_wait_for_memory (); 198 199 /* Ref connection in case we disconnect it at some point in here */ 200 dbus_connection_ref (connection); 201 202 service_name = dbus_message_get_destination (message); 203 204 #ifdef DBUS_ENABLE_VERBOSE_MODE 205 { 206 const char *interface_name, *member_name, *error_name; 207 208 interface_name = dbus_message_get_interface (message); 209 member_name = dbus_message_get_member (message); 210 error_name = dbus_message_get_error_name (message); 211 212 _dbus_verbose ("DISPATCH: %s %s %s to %s\n", 213 interface_name ? interface_name : "(no interface)", 214 member_name ? member_name : "(no member)", 215 error_name ? error_name : "(no error name)", 216 service_name ? service_name : "peer"); 217 } 218 #endif /* DBUS_ENABLE_VERBOSE_MODE */ 219 220 /* If service_name is NULL, if it's a signal we send it to all 221 * connections with a match rule. If it's not a signal, there 222 * are some special cases here but mostly we just bail out. 223 */ 224 if (service_name == NULL) 225 { 226 if (dbus_message_is_signal (message, 227 DBUS_INTERFACE_LOCAL, 228 "Disconnected")) 229 { 230 bus_connection_disconnected (connection); 231 goto out; 232 } 233 234 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL) 235 { 236 /* DBusConnection also handles some of these automatically, we leave 237 * it to do so. 238 */ 239 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 240 goto out; 241 } 242 } 243 244 /* Create our transaction */ 245 transaction = bus_transaction_new (context); 246 if (transaction == NULL) 247 { 248 BUS_SET_OOM (&error); 249 goto out; 250 } 251 252 /* Assign a sender to the message */ 253 if (bus_connection_is_active (connection)) 254 { 255 sender = bus_connection_get_name (connection); 256 _dbus_assert (sender != NULL); 257 258 if (!dbus_message_set_sender (message, sender)) 259 { 260 BUS_SET_OOM (&error); 261 goto out; 262 } 263 264 /* We need to refetch the service name here, because 265 * dbus_message_set_sender can cause the header to be 266 * reallocated, and thus the service_name pointer will become 267 * invalid. 268 */ 269 service_name = dbus_message_get_destination (message); 270 } 271 272 if (service_name && 273 strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */ 274 { 275 if (!bus_context_check_security_policy (context, transaction, 276 connection, NULL, NULL, message, &error)) 277 { 278 _dbus_verbose ("Security policy rejected message\n"); 279 goto out; 280 } 281 282 _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_DBUS); 283 if (!bus_driver_handle_message (connection, transaction, message, &error)) 284 goto out; 285 } 286 else if (!bus_connection_is_active (connection)) /* clients must talk to bus driver first */ 287 { 288 _dbus_verbose ("Received message from non-registered client. Disconnecting.\n"); 289 dbus_connection_close (connection); 290 goto out; 291 } 292 else if (service_name != NULL) /* route to named service */ 293 { 294 DBusString service_string; 295 BusService *service; 296 BusRegistry *registry; 297 298 _dbus_assert (service_name != NULL); 299 300 registry = bus_connection_get_registry (connection); 301 302 _dbus_string_init_const (&service_string, service_name); 303 service = bus_registry_lookup (registry, &service_string); 304 305 if (service == NULL && dbus_message_get_auto_start (message)) 306 { 307 BusActivation *activation; 308 /* We can't do the security policy check here, since the addressed 309 * recipient service doesn't exist yet. We do it before sending the 310 * message after the service has been created. 311 */ 312 activation = bus_connection_get_activation (connection); 313 314 if (!bus_activation_activate_service (activation, connection, transaction, TRUE, 315 message, service_name, &error)) 316 { 317 _DBUS_ASSERT_ERROR_IS_SET (&error); 318 _dbus_verbose ("bus_activation_activate_service() failed: %s\n", error.name); 319 goto out; 320 } 321 322 goto out; 323 } 324 else if (service == NULL) 325 { 326 dbus_set_error (&error, 327 DBUS_ERROR_NAME_HAS_NO_OWNER, 328 "Name \"%s\" does not exist", 329 service_name); 330 goto out; 331 } 332 else 333 { 334 addressed_recipient = bus_service_get_primary_owners_connection (service); 335 _dbus_assert (addressed_recipient != NULL); 336 } 337 } 338 339 /* Now send the message to its destination (or not, if 340 * addressed_recipient == NULL), and match it against other connections' 341 * match rules. 342 */ 343 if (!bus_dispatch_matches (transaction, connection, addressed_recipient, message, &error)) 344 goto out; 345 346 out: 347 if (dbus_error_is_set (&error)) 348 { 349 if (!dbus_connection_get_is_connected (connection)) 350 { 351 /* If we disconnected it, we won't bother to send it any error 352 * messages. 353 */ 354 _dbus_verbose ("Not sending error to connection we disconnected\n"); 355 } 356 else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) 357 { 358 bus_connection_send_oom_error (connection, message); 359 360 /* cancel transaction due to OOM */ 361 if (transaction != NULL) 362 { 363 bus_transaction_cancel_and_free (transaction); 364 transaction = NULL; 365 } 366 } 367 else 368 { 369 /* Try to send the real error, if no mem to do that, send 370 * the OOM error 371 */ 372 _dbus_assert (transaction != NULL); 373 if (!bus_transaction_send_error_reply (transaction, connection, 374 &error, message)) 375 { 376 bus_connection_send_oom_error (connection, message); 377 378 /* cancel transaction due to OOM */ 379 if (transaction != NULL) 380 { 381 bus_transaction_cancel_and_free (transaction); 382 transaction = NULL; 383 } 384 } 385 } 386 387 388 dbus_error_free (&error); 389 } 390 391 if (transaction != NULL) 392 { 393 bus_transaction_execute_and_free (transaction); 394 } 395 396 dbus_connection_unref (connection); 397 398 return result; 399 } 400 401 static DBusHandlerResult 402 bus_dispatch_message_filter (DBusConnection *connection, 403 DBusMessage *message, 404 void *user_data) 405 { 406 return bus_dispatch (connection, message); 407 } 408 409 dbus_bool_t 410 bus_dispatch_add_connection (DBusConnection *connection) 411 { 412 if (!dbus_connection_add_filter (connection, 413 bus_dispatch_message_filter, 414 NULL, NULL)) 415 return FALSE; 416 417 return TRUE; 418 } 419 420 void 421 bus_dispatch_remove_connection (DBusConnection *connection) 422 { 423 /* Here we tell the bus driver that we want to get off. */ 424 bus_driver_remove_connection (connection); 425 426 dbus_connection_remove_filter (connection, 427 bus_dispatch_message_filter, 428 NULL); 429 } 430 431 #ifdef DBUS_BUILD_TESTS 432 433 #include <stdio.h> 434 435 /* This is used to know whether we need to block in order to finish 436 * sending a message, or whether the initial dbus_connection_send() 437 * already flushed the queue. 438 */ 439 #define SEND_PENDING(connection) (dbus_connection_has_messages_to_send (connection)) 440 441 typedef dbus_bool_t (* Check1Func) (BusContext *context); 442 typedef dbus_bool_t (* Check2Func) (BusContext *context, 443 DBusConnection *connection); 444 445 static dbus_bool_t check_no_leftovers (BusContext *context); 446 447 static void 448 block_connection_until_message_from_bus (BusContext *context, 449 DBusConnection *connection, 450 const char *what_is_expected) 451 { 452 _dbus_verbose ("expecting: %s\n", what_is_expected); 453 454 while (dbus_connection_get_dispatch_status (connection) == 455 DBUS_DISPATCH_COMPLETE && 456 dbus_connection_get_is_connected (connection)) 457 { 458 bus_test_run_bus_loop (context, TRUE); 459 bus_test_run_clients_loop (FALSE); 460 } 461 } 462 463 static void 464 spin_connection_until_authenticated (BusContext *context, 465 DBusConnection *connection) 466 { 467 _dbus_verbose ("Spinning to auth connection %p\n", connection); 468 while (!dbus_connection_get_is_authenticated (connection) && 469 dbus_connection_get_is_connected (connection)) 470 { 471 bus_test_run_bus_loop (context, FALSE); 472 bus_test_run_clients_loop (FALSE); 473 } 474 _dbus_verbose (" ... done spinning to auth connection %p\n", connection); 475 } 476 477 /* compensate for fact that pop_message() can return #NULL due to OOM */ 478 static DBusMessage* 479 pop_message_waiting_for_memory (DBusConnection *connection) 480 { 481 while (dbus_connection_get_dispatch_status (connection) == 482 DBUS_DISPATCH_NEED_MEMORY) 483 _dbus_wait_for_memory (); 484 485 return dbus_connection_pop_message (connection); 486 } 487 488 static DBusMessage* 489 borrow_message_waiting_for_memory (DBusConnection *connection) 490 { 491 while (dbus_connection_get_dispatch_status (connection) == 492 DBUS_DISPATCH_NEED_MEMORY) 493 _dbus_wait_for_memory (); 494 495 return dbus_connection_borrow_message (connection); 496 } 497 498 static void 499 warn_unexpected_real (DBusConnection *connection, 500 DBusMessage *message, 501 const char *expected, 502 const char *function, 503 int line) 504 { 505 if (message) 506 _dbus_warn ("%s:%d received message interface \"%s\" member \"%s\" error name \"%s\" on %p, expecting %s\n", 507 function, line, 508 dbus_message_get_interface (message) ? 509 dbus_message_get_interface (message) : "(unset)", 510 dbus_message_get_member (message) ? 511 dbus_message_get_member (message) : "(unset)", 512 dbus_message_get_error_name (message) ? 513 dbus_message_get_error_name (message) : "(unset)", 514 connection, 515 expected); 516 else 517 _dbus_warn ("%s:%d received no message on %p, expecting %s\n", 518 function, line, connection, expected); 519 } 520 521 #define warn_unexpected(connection, message, expected) \ 522 warn_unexpected_real (connection, message, expected, _DBUS_FUNCTION_NAME, __LINE__) 523 524 static void 525 verbose_message_received (DBusConnection *connection, 526 DBusMessage *message) 527 { 528 _dbus_verbose ("Received message interface \"%s\" member \"%s\" error name \"%s\" on %p\n", 529 dbus_message_get_interface (message) ? 530 dbus_message_get_interface (message) : "(unset)", 531 dbus_message_get_member (message) ? 532 dbus_message_get_member (message) : "(unset)", 533 dbus_message_get_error_name (message) ? 534 dbus_message_get_error_name (message) : "(unset)", 535 connection); 536 } 537 538 typedef enum 539 { 540 SERVICE_CREATED, 541 OWNER_CHANGED, 542 SERVICE_DELETED 543 } ServiceInfoKind; 544 545 typedef struct 546 { 547 ServiceInfoKind expected_kind; 548 const char *expected_service_name; 549 dbus_bool_t failed; 550 DBusConnection *skip_connection; 551 } CheckServiceOwnerChangedData; 552 553 static dbus_bool_t 554 check_service_owner_changed_foreach (DBusConnection *connection, 555 void *data) 556 { 557 CheckServiceOwnerChangedData *d = data; 558 DBusMessage *message; 559 DBusError error; 560 const char *service_name, *old_owner, *new_owner; 561 562 if (d->expected_kind == SERVICE_CREATED 563 && connection == d->skip_connection) 564 return TRUE; 565 566 dbus_error_init (&error); 567 d->failed = TRUE; 568 569 message = pop_message_waiting_for_memory (connection); 570 if (message == NULL) 571 { 572 _dbus_warn ("Did not receive a message on %p, expecting %s\n", 573 connection, "NameOwnerChanged"); 574 goto out; 575 } 576 else if (!dbus_message_is_signal (message, 577 DBUS_INTERFACE_DBUS, 578 "NameOwnerChanged")) 579 { 580 warn_unexpected (connection, message, "NameOwnerChanged"); 581 582 goto out; 583 } 584 else 585 { 586 reget_service_info_data: 587 service_name = NULL; 588 old_owner = NULL; 589 new_owner = NULL; 590 591 dbus_message_get_args (message, &error, 592 DBUS_TYPE_STRING, &service_name, 593 DBUS_TYPE_STRING, &old_owner, 594 DBUS_TYPE_STRING, &new_owner, 595 DBUS_TYPE_INVALID); 596 597 if (dbus_error_is_set (&error)) 598 { 599 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) 600 { 601 dbus_error_free (&error); 602 _dbus_wait_for_memory (); 603 goto reget_service_info_data; 604 } 605 else 606 { 607 _dbus_warn ("Did not get the expected arguments\n"); 608 goto out; 609 } 610 } 611 612 if ((d->expected_kind == SERVICE_CREATED && ( old_owner[0] || !new_owner[0])) 613 || (d->expected_kind == OWNER_CHANGED && (!old_owner[0] || !new_owner[0])) 614 || (d->expected_kind == SERVICE_DELETED && (!old_owner[0] || new_owner[0]))) 615 { 616 _dbus_warn ("inconsistent NameOwnerChanged arguments\n"); 617 goto out; 618 } 619 620 if (strcmp (service_name, d->expected_service_name) != 0) 621 { 622 _dbus_warn ("expected info on service %s, got info on %s\n", 623 d->expected_service_name, 624 service_name); 625 goto out; 626 } 627 628 if (*service_name == ':' && new_owner[0] 629 && strcmp (service_name, new_owner) != 0) 630 { 631 _dbus_warn ("inconsistent ServiceOwnedChanged message (\"%s\" [ %s -> %s ])\n", 632 service_name, old_owner, new_owner); 633 goto out; 634 } 635 } 636 637 d->failed = FALSE; 638 639 out: 640 dbus_error_free (&error); 641 642 if (message) 643 dbus_message_unref (message); 644 645 return !d->failed; 646 } 647 648 649 static void 650 kill_client_connection (BusContext *context, 651 DBusConnection *connection) 652 { 653 char *base_service; 654 const char *s; 655 CheckServiceOwnerChangedData socd; 656 657 _dbus_verbose ("killing connection %p\n", connection); 658 659 s = dbus_bus_get_unique_name (connection); 660 _dbus_assert (s != NULL); 661 662 while ((base_service = _dbus_strdup (s)) == NULL) 663 _dbus_wait_for_memory (); 664 665 dbus_connection_ref (connection); 666 667 /* kick in the disconnect handler that unrefs the connection */ 668 dbus_connection_close (connection); 669 670 bus_test_run_everything (context); 671 672 _dbus_assert (bus_test_client_listed (connection)); 673 674 /* Run disconnect handler in test.c */ 675 if (bus_connection_dispatch_one_message (connection)) 676 _dbus_assert_not_reached ("something received on connection being killed other than the disconnect"); 677 678 _dbus_assert (!dbus_connection_get_is_connected (connection)); 679 dbus_connection_unref (connection); 680 connection = NULL; 681 _dbus_assert (!bus_test_client_listed (connection)); 682 683 socd.expected_kind = SERVICE_DELETED; 684 socd.expected_service_name = base_service; 685 socd.failed = FALSE; 686 socd.skip_connection = NULL; 687 688 bus_test_clients_foreach (check_service_owner_changed_foreach, 689 &socd); 690 691 dbus_free (base_service); 692 693 if (socd.failed) 694 _dbus_assert_not_reached ("didn't get the expected NameOwnerChanged (deletion) messages"); 695 696 if (!check_no_leftovers (context)) 697 _dbus_assert_not_reached ("stuff left in message queues after disconnecting a client"); 698 } 699 700 static void 701 kill_client_connection_unchecked (DBusConnection *connection) 702 { 703 /* This kills the connection without expecting it to affect 704 * the rest of the bus. 705 */ 706 _dbus_verbose ("Unchecked kill of connection %p\n", connection); 707 708 dbus_connection_ref (connection); 709 dbus_connection_close (connection); 710 /* dispatching disconnect handler will unref once */ 711 if (bus_connection_dispatch_one_message (connection)) 712 _dbus_assert_not_reached ("message other than disconnect dispatched after failure to register"); 713 714 _dbus_assert (!bus_test_client_listed (connection)); 715 dbus_connection_unref (connection); 716 } 717 718 typedef struct 719 { 720 dbus_bool_t failed; 721 } CheckNoMessagesData; 722 723 static dbus_bool_t 724 check_no_messages_foreach (DBusConnection *connection, 725 void *data) 726 { 727 CheckNoMessagesData *d = data; 728 DBusMessage *message; 729 730 message = pop_message_waiting_for_memory (connection); 731 if (message != NULL) 732 { 733 warn_unexpected (connection, message, "no messages"); 734 735 d->failed = TRUE; 736 } 737 738 if (message) 739 dbus_message_unref (message); 740 return !d->failed; 741 } 742 743 static dbus_bool_t 744 check_no_leftovers (BusContext *context) 745 { 746 CheckNoMessagesData nmd; 747 748 nmd.failed = FALSE; 749 bus_test_clients_foreach (check_no_messages_foreach, 750 &nmd); 751 752 if (nmd.failed) 753 { 754 _dbus_verbose ("leftover message found\n"); 755 return FALSE; 756 } 757 else 758 return TRUE; 759 } 760 761 /* returns TRUE if the correct thing happens, 762 * but the correct thing may include OOM errors. 763 */ 764 static dbus_bool_t 765 check_hello_message (BusContext *context, 766 DBusConnection *connection) 767 { 768 DBusMessage *message; 769 DBusMessage *name_message; 770 dbus_uint32_t serial; 771 dbus_bool_t retval; 772 DBusError error; 773 const char *name; 774 const char *acquired; 775 776 retval = FALSE; 777 dbus_error_init (&error); 778 name = NULL; 779 acquired = NULL; 780 message = NULL; 781 name_message = NULL; 782 783 _dbus_verbose ("check_hello_message for %p\n", connection); 784 785 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS, 786 DBUS_PATH_DBUS, 787 DBUS_INTERFACE_DBUS, 788 "Hello"); 789 790 if (message == NULL) 791 return TRUE; 792 793 dbus_connection_ref (connection); /* because we may get disconnected */ 794 795 if (!dbus_connection_send (connection, message, &serial)) 796 { 797 dbus_message_unref (message); 798 dbus_connection_unref (connection); 799 return TRUE; 800 } 801 802 _dbus_assert (dbus_message_has_signature (message, "")); 803 804 dbus_message_unref (message); 805 message = NULL; 806 807 if (!dbus_connection_get_is_connected (connection)) 808 { 809 _dbus_verbose ("connection was disconnected (presumably auth failed)\n"); 810 811 dbus_connection_unref (connection); 812 813 return TRUE; 814 } 815 816 /* send our message */ 817 bus_test_run_clients_loop (SEND_PENDING (connection)); 818 819 if (!dbus_connection_get_is_connected (connection)) 820 { 821 _dbus_verbose ("connection was disconnected (presumably auth failed)\n"); 822 823 dbus_connection_unref (connection); 824 825 return TRUE; 826 } 827 828 block_connection_until_message_from_bus (context, connection, "reply to Hello"); 829 830 if (!dbus_connection_get_is_connected (connection)) 831 { 832 _dbus_verbose ("connection was disconnected (presumably auth failed)\n"); 833 834 dbus_connection_unref (connection); 835 836 return TRUE; 837 } 838 839 dbus_connection_unref (connection); 840 841 message = pop_message_waiting_for_memory (connection); 842 if (message == NULL) 843 { 844 _dbus_warn ("Did not receive a reply to %s %d on %p\n", 845 "Hello", serial, connection); 846 goto out; 847 } 848 849 verbose_message_received (connection, message); 850 851 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS)) 852 { 853 _dbus_warn ("Message has wrong sender %s\n", 854 dbus_message_get_sender (message) ? 855 dbus_message_get_sender (message) : "(none)"); 856 goto out; 857 } 858 859 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR) 860 { 861 if (dbus_message_is_error (message, 862 DBUS_ERROR_NO_MEMORY)) 863 { 864 ; /* good, this is a valid response */ 865 } 866 else 867 { 868 warn_unexpected (connection, message, "not this error"); 869 870 goto out; 871 } 872 } 873 else 874 { 875 CheckServiceOwnerChangedData socd; 876 877 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN) 878 { 879 ; /* good, expected */ 880 } 881 else 882 { 883 warn_unexpected (connection, message, "method return for Hello"); 884 885 goto out; 886 } 887 888 retry_get_hello_name: 889 if (!dbus_message_get_args (message, &error, 890 DBUS_TYPE_STRING, &name, 891 DBUS_TYPE_INVALID)) 892 { 893 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) 894 { 895 _dbus_verbose ("no memory to get service name arg from hello\n"); 896 dbus_error_free (&error); 897 _dbus_wait_for_memory (); 898 goto retry_get_hello_name; 899 } 900 else 901 { 902 _dbus_assert (dbus_error_is_set (&error)); 903 _dbus_warn ("Did not get the expected single string argument to hello\n"); 904 goto out; 905 } 906 } 907 908 _dbus_verbose ("Got hello name: %s\n", name); 909 910 while (!dbus_bus_set_unique_name (connection, name)) 911 _dbus_wait_for_memory (); 912 913 socd.expected_kind = SERVICE_CREATED; 914 socd.expected_service_name = name; 915 socd.failed = FALSE; 916 socd.skip_connection = connection; /* we haven't done AddMatch so won't get it ourselves */ 917 bus_test_clients_foreach (check_service_owner_changed_foreach, 918 &socd); 919 920 if (socd.failed) 921 goto out; 922 923 name_message = message; 924 /* Client should also have gotten ServiceAcquired */ 925 926 message = pop_message_waiting_for_memory (connection); 927 if (message == NULL) 928 { 929 _dbus_warn ("Expecting %s, got nothing\n", 930 "NameAcquired"); 931 goto out; 932 } 933 if (! dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, 934 "NameAcquired")) 935 { 936 _dbus_warn ("Expecting %s, got smthg else\n", 937 "NameAcquired"); 938 goto out; 939 } 940 941 retry_get_acquired_name: 942 if (!dbus_message_get_args (message, &error, 943 DBUS_TYPE_STRING, &acquired, 944 DBUS_TYPE_INVALID)) 945 { 946 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) 947 { 948 _dbus_verbose ("no memory to get service name arg from acquired\n"); 949 dbus_error_free (&error); 950 _dbus_wait_for_memory (); 951 goto retry_get_acquired_name; 952 } 953 else 954 { 955 _dbus_assert (dbus_error_is_set (&error)); 956 _dbus_warn ("Did not get the expected single string argument to ServiceAcquired\n"); 957 goto out; 958 } 959 } 960 961 _dbus_verbose ("Got acquired name: %s\n", acquired); 962 963 if (strcmp (acquired, name) != 0) 964 { 965 _dbus_warn ("Acquired name is %s but expected %s\n", 966 acquired, name); 967 goto out; 968 } 969 acquired = NULL; 970 } 971 972 if (!check_no_leftovers (context)) 973 goto out; 974 975 retval = TRUE; 976 977 out: 978 _dbus_verbose ("ending - retval = %d\n", retval); 979 980 dbus_error_free (&error); 981 982 if (message) 983 dbus_message_unref (message); 984 985 if (name_message) 986 dbus_message_unref (name_message); 987 988 return retval; 989 } 990 991 /* returns TRUE if the correct thing happens, 992 * but the correct thing may include OOM errors. 993 */ 994 static dbus_bool_t 995 check_double_hello_message (BusContext *context, 996 DBusConnection *connection) 997 { 998 DBusMessage *message; 999 dbus_uint32_t serial; 1000 dbus_bool_t retval; 1001 DBusError error; 1002 1003 retval = FALSE; 1004 dbus_error_init (&error); 1005 message = NULL; 1006 1007 _dbus_verbose ("check_double_hello_message for %p\n", connection); 1008 1009 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS, 1010 DBUS_PATH_DBUS, 1011 DBUS_INTERFACE_DBUS, 1012 "Hello"); 1013 1014 if (message == NULL) 1015 return TRUE; 1016 1017 if (!dbus_connection_send (connection, message, &serial)) 1018 { 1019 dbus_message_unref (message); 1020 return TRUE; 1021 } 1022 1023 dbus_message_unref (message); 1024 message = NULL; 1025 1026 /* send our message */ 1027 bus_test_run_clients_loop (SEND_PENDING (connection)); 1028 1029 dbus_connection_ref (connection); /* because we may get disconnected */ 1030 block_connection_until_message_from_bus (context, connection, "reply to Hello"); 1031 1032 if (!dbus_connection_get_is_connected (connection)) 1033 { 1034 _dbus_verbose ("connection was disconnected\n"); 1035 1036 dbus_connection_unref (connection); 1037 1038 return TRUE; 1039 } 1040 1041 dbus_connection_unref (connection); 1042 1043 message = pop_message_waiting_for_memory (connection); 1044 if (message == NULL) 1045 { 1046 _dbus_warn ("Did not receive a reply to %s %d on %p\n", 1047 "Hello", serial, connection); 1048 goto out; 1049 } 1050 1051 verbose_message_received (connection, message); 1052 1053 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS)) 1054 { 1055 _dbus_warn ("Message has wrong sender %s\n", 1056 dbus_message_get_sender (message) ? 1057 dbus_message_get_sender (message) : "(none)"); 1058 goto out; 1059 } 1060 1061 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) 1062 { 1063 warn_unexpected (connection, message, "method return for Hello"); 1064 goto out; 1065 } 1066 1067 if (!check_no_leftovers (context)) 1068 goto out; 1069 1070 retval = TRUE; 1071 1072 out: 1073 dbus_error_free (&error); 1074 1075 if (message) 1076 dbus_message_unref (message); 1077 1078 return retval; 1079 } 1080 1081 /* returns TRUE if the correct thing happens, 1082 * but the correct thing may include OOM errors. 1083 */ 1084 static dbus_bool_t 1085 check_get_connection_unix_user (BusContext *context, 1086 DBusConnection *connection) 1087 { 1088 DBusMessage *message; 1089 dbus_uint32_t serial; 1090 dbus_bool_t retval; 1091 DBusError error; 1092 const char *base_service_name; 1093 dbus_uint32_t uid; 1094 1095 retval = FALSE; 1096 dbus_error_init (&error); 1097 message = NULL; 1098 1099 _dbus_verbose ("check_get_connection_unix_user for %p\n", connection); 1100 1101 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS, 1102 DBUS_PATH_DBUS, 1103 DBUS_INTERFACE_DBUS, 1104 "GetConnectionUnixUser"); 1105 1106 if (message == NULL) 1107 return TRUE; 1108 1109 base_service_name = dbus_bus_get_unique_name (connection); 1110 1111 if (!dbus_message_append_args (message, 1112 DBUS_TYPE_STRING, &base_service_name, 1113 DBUS_TYPE_INVALID)) 1114 { 1115 dbus_message_unref (message); 1116 return TRUE; 1117 } 1118 1119 if (!dbus_connection_send (connection, message, &serial)) 1120 { 1121 dbus_message_unref (message); 1122 return TRUE; 1123 } 1124 1125 /* send our message */ 1126 bus_test_run_clients_loop (SEND_PENDING (connection)); 1127 1128 dbus_message_unref (message); 1129 message = NULL; 1130 1131 dbus_connection_ref (connection); /* because we may get disconnected */ 1132 block_connection_until_message_from_bus (context, connection, "reply to GetConnectionUnixUser"); 1133 1134 if (!dbus_connection_get_is_connected (connection)) 1135 { 1136 _dbus_verbose ("connection was disconnected\n"); 1137 1138 dbus_connection_unref (connection); 1139 1140 return TRUE; 1141 } 1142 1143 dbus_connection_unref (connection); 1144 1145 message = pop_message_waiting_for_memory (connection); 1146 if (message == NULL) 1147 { 1148 _dbus_warn ("Did not receive a reply to %s %d on %p\n", 1149 "GetConnectionUnixUser", serial, connection); 1150 goto out; 1151 } 1152 1153 verbose_message_received (connection, message); 1154 1155 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR) 1156 { 1157 if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY)) 1158 { 1159 ; /* good, this is a valid response */ 1160 } 1161 else 1162 { 1163 warn_unexpected (connection, message, "not this error"); 1164 1165 goto out; 1166 } 1167 } 1168 else 1169 { 1170 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN) 1171 { 1172 ; /* good, expected */ 1173 } 1174 else 1175 { 1176 warn_unexpected (connection, message, 1177 "method_return for GetConnectionUnixUser"); 1178 1179 goto out; 1180 } 1181 1182 retry_get_property: 1183 1184 if (!dbus_message_get_args (message, &error, 1185 DBUS_TYPE_UINT32, &uid, 1186 DBUS_TYPE_INVALID)) 1187 { 1188 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) 1189 { 1190 _dbus_verbose ("no memory to get uid by GetConnectionUnixUser\n"); 1191 dbus_error_free (&error); 1192 _dbus_wait_for_memory (); 1193 goto retry_get_property; 1194 } 1195 else 1196 { 1197 _dbus_assert (dbus_error_is_set (&error)); 1198 _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixUser\n"); 1199 goto out; 1200 } 1201 } 1202 } 1203 1204 if (!check_no_leftovers (context)) 1205 goto out; 1206 1207 retval = TRUE; 1208 1209 out: 1210 dbus_error_free (&error); 1211 1212 if (message) 1213 dbus_message_unref (message); 1214 1215 return retval; 1216 } 1217 1218 /* returns TRUE if the correct thing happens, 1219 * but the correct thing may include OOM errors. 1220 */ 1221 static dbus_bool_t 1222 check_get_connection_unix_process_id (BusContext *context, 1223 DBusConnection *connection) 1224 { 1225 DBusMessage *message; 1226 dbus_uint32_t serial; 1227 dbus_bool_t retval; 1228 DBusError error; 1229 const char *base_service_name; 1230 dbus_uint32_t pid; 1231 1232 retval = FALSE; 1233 dbus_error_init (&error); 1234 message = NULL; 1235 1236 _dbus_verbose ("check_get_connection_unix_process_id for %p\n", connection); 1237 1238 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS, 1239 DBUS_PATH_DBUS, 1240 DBUS_INTERFACE_DBUS, 1241 "GetConnectionUnixProcessID"); 1242 1243 if (message == NULL) 1244 return TRUE; 1245 1246 base_service_name = dbus_bus_get_unique_name (connection); 1247 1248 if (!dbus_message_append_args (message, 1249 DBUS_TYPE_STRING, &base_service_name, 1250 DBUS_TYPE_INVALID)) 1251 { 1252 dbus_message_unref (message); 1253 return TRUE; 1254 } 1255 1256 if (!dbus_connection_send (connection, message, &serial)) 1257 { 1258 dbus_message_unref (message); 1259 return TRUE; 1260 } 1261 1262 /* send our message */ 1263 bus_test_run_clients_loop (SEND_PENDING (connection)); 1264 1265 dbus_message_unref (message); 1266 message = NULL; 1267 1268 dbus_connection_ref (connection); /* because we may get disconnected */ 1269 block_connection_until_message_from_bus (context, connection, "reply to GetConnectionUnixProcessID"); 1270 1271 if (!dbus_connection_get_is_connected (connection)) 1272 { 1273 _dbus_verbose ("connection was disconnected\n"); 1274 1275 dbus_connection_unref (connection); 1276 1277 return TRUE; 1278 } 1279 1280 dbus_connection_unref (connection); 1281 1282 message = pop_message_waiting_for_memory (connection); 1283 if (message == NULL) 1284 { 1285 _dbus_warn ("Did not receive a reply to %s %d on %p\n", 1286 "GetConnectionUnixProcessID", serial, connection); 1287 goto out; 1288 } 1289 1290 verbose_message_received (connection, message); 1291 1292 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR) 1293 { 1294 if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY)) 1295 { 1296 ; /* good, this is a valid response */ 1297 } 1298 #ifdef DBUS_WIN 1299 else if (dbus_message_is_error (message, DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN)) 1300 { 1301 /* We are expecting this error, since we know in the test suite we aren't 1302 * talking to a client running on UNIX 1303 */ 1304 _dbus_verbose ("Windows correctly does not support GetConnectionUnixProcessID\n"); 1305 } 1306 #endif 1307 else 1308 { 1309 warn_unexpected (connection, message, "not this error"); 1310 1311 goto out; 1312 } 1313 } 1314 else 1315 { 1316 #ifdef DBUS_WIN 1317 warn_unexpected (connection, message, "GetConnectionUnixProcessID to fail on Windows"); 1318 goto out; 1319 #else 1320 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN) 1321 { 1322 ; /* good, expected */ 1323 } 1324 else 1325 { 1326 warn_unexpected (connection, message, 1327 "method_return for GetConnectionUnixProcessID"); 1328 1329 goto out; 1330 } 1331 1332 retry_get_property: 1333 1334 if (!dbus_message_get_args (message, &error, 1335 DBUS_TYPE_UINT32, &pid, 1336 DBUS_TYPE_INVALID)) 1337 { 1338 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) 1339 { 1340 _dbus_verbose ("no memory to get pid by GetConnectionUnixProcessID\n"); 1341 dbus_error_free (&error); 1342 _dbus_wait_for_memory (); 1343 goto retry_get_property; 1344 } 1345 else 1346 { 1347 _dbus_assert (dbus_error_is_set (&error)); 1348 _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixProcessID\n"); 1349 goto out; 1350 } 1351 } 1352 else 1353 { 1354 /* test if returned pid is the same as our own pid 1355 * 1356 * @todo It would probably be good to restructure the tests 1357 * in a way so our parent is the bus that we're testing 1358 * cause then we can test that the pid returned matches 1359 * getppid() 1360 */ 1361 if (pid != (dbus_uint32_t) _dbus_getpid ()) 1362 { 1363 _dbus_assert (dbus_error_is_set (&error)); 1364 _dbus_warn ("Result from GetConnectionUnixProcessID is not our own pid\n"); 1365 goto out; 1366 } 1367 } 1368 #endif /* !DBUS_WIN */ 1369 } 1370 1371 if (!check_no_leftovers (context)) 1372 goto out; 1373 1374 retval = TRUE; 1375 1376 out: 1377 dbus_error_free (&error); 1378 1379 if (message) 1380 dbus_message_unref (message); 1381 1382 return retval; 1383 } 1384 1385 /* returns TRUE if the correct thing happens, 1386 * but the correct thing may include OOM errors. 1387 */ 1388 static dbus_bool_t 1389 check_add_match_all (BusContext *context, 1390 DBusConnection *connection) 1391 { 1392 DBusMessage *message; 1393 dbus_bool_t retval; 1394 dbus_uint32_t serial; 1395 DBusError error; 1396 const char *empty = ""; 1397 1398 retval = FALSE; 1399 dbus_error_init (&error); 1400 message = NULL; 1401 1402 _dbus_verbose ("check_add_match_all for %p\n", connection); 1403 1404 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS, 1405 DBUS_PATH_DBUS, 1406 DBUS_INTERFACE_DBUS, 1407 "AddMatch"); 1408 1409 if (message == NULL) 1410 return TRUE; 1411 1412 /* empty string match rule matches everything */ 1413 if (!dbus_message_append_args (message, DBUS_TYPE_STRING, &empty, 1414 DBUS_TYPE_INVALID)) 1415 { 1416 dbus_message_unref (message); 1417 return TRUE; 1418 } 1419 1420 if (!dbus_connection_send (connection, message, &serial)) 1421 { 1422 dbus_message_unref (message); 1423 return TRUE; 1424 } 1425 1426 dbus_message_unref (message); 1427 message = NULL; 1428 1429 dbus_connection_ref (connection); /* because we may get disconnected */ 1430 1431 /* send our message */ 1432 bus_test_run_clients_loop (SEND_PENDING (connection)); 1433 1434 if (!dbus_connection_get_is_connected (connection)) 1435 { 1436 _dbus_verbose ("connection was disconnected\n"); 1437 1438 dbus_connection_unref (connection); 1439 1440 return TRUE; 1441 } 1442 1443 block_connection_until_message_from_bus (context, connection, "reply to AddMatch"); 1444 1445 if (!dbus_connection_get_is_connected (connection)) 1446 { 1447 _dbus_verbose ("connection was disconnected\n"); 1448 1449 dbus_connection_unref (connection); 1450 1451 return TRUE; 1452 } 1453 1454 dbus_connection_unref (connection); 1455 1456 message = pop_message_waiting_for_memory (connection); 1457 if (message == NULL) 1458 { 1459 _dbus_warn ("Did not receive a reply to %s %d on %p\n", 1460 "AddMatch", serial, connection); 1461 goto out; 1462 } 1463 1464 verbose_message_received (connection, message); 1465 1466 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS)) 1467 { 1468 _dbus_warn ("Message has wrong sender %s\n", 1469 dbus_message_get_sender (message) ? 1470 dbus_message_get_sender (message) : "(none)"); 1471 goto out; 1472 } 1473 1474 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR) 1475 { 1476 if (dbus_message_is_error (message, 1477 DBUS_ERROR_NO_MEMORY)) 1478 { 1479 ; /* good, this is a valid response */ 1480 } 1481 else 1482 { 1483 warn_unexpected (connection, message, "not this error"); 1484 1485 goto out; 1486 } 1487 } 1488 else 1489 { 1490 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN) 1491 { 1492 ; /* good, expected */ 1493 _dbus_assert (dbus_message_get_reply_serial (message) == serial); 1494 } 1495 else 1496 { 1497 warn_unexpected (connection, message, "method return for AddMatch"); 1498 1499 goto out; 1500 } 1501 } 1502 1503 if (!check_no_leftovers (context)) 1504 goto out; 1505 1506 retval = TRUE; 1507 1508 out: 1509 dbus_error_free (&error); 1510 1511 if (message) 1512 dbus_message_unref (message); 1513 1514 return retval; 1515 } 1516 1517 /* returns TRUE if the correct thing happens, 1518 * but the correct thing may include OOM errors. 1519 */ 1520 static dbus_bool_t 1521 check_hello_connection (BusContext *context) 1522 { 1523 DBusConnection *connection; 1524 DBusError error; 1525 1526 dbus_error_init (&error); 1527 1528 connection = dbus_connection_open_private (TEST_DEBUG_PIPE, &error); 1529 if (connection == NULL) 1530 { 1531 _DBUS_ASSERT_ERROR_IS_SET (&error); 1532 dbus_error_free (&error); 1533 return TRUE; 1534 } 1535 1536 if (!bus_setup_debug_client (connection)) 1537 { 1538 dbus_connection_close (connection); 1539 dbus_connection_unref (connection); 1540 return TRUE; 1541 } 1542 1543 spin_connection_until_authenticated (context, connection); 1544 1545 if (!check_hello_message (context, connection)) 1546 return FALSE; 1547 1548 if (dbus_bus_get_unique_name (connection) == NULL) 1549 { 1550 /* We didn't successfully register, so we can't 1551 * do the usual kill_client_connection() checks 1552 */ 1553 kill_client_connection_unchecked (connection); 1554 } 1555 else 1556 { 1557 if (!check_add_match_all (context, connection)) 1558 return FALSE; 1559 1560 kill_client_connection (context, connection); 1561 } 1562 1563 return TRUE; 1564 } 1565 1566 #define NONEXISTENT_SERVICE_NAME "test.this.service.does.not.exist.ewuoiurjdfxcvn" 1567 1568 /* returns TRUE if the correct thing happens, 1569 * but the correct thing may include OOM errors. 1570 */ 1571 static dbus_bool_t 1572 check_nonexistent_service_no_auto_start (BusContext *context, 1573 DBusConnection *connection) 1574 { 1575 DBusMessage *message; 1576 dbus_uint32_t serial; 1577 dbus_bool_t retval; 1578 const char *nonexistent = NONEXISTENT_SERVICE_NAME; 1579 dbus_uint32_t flags; 1580 1581 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS, 1582 DBUS_PATH_DBUS, 1583 DBUS_INTERFACE_DBUS, 1584 "StartServiceByName"); 1585 1586 if (message == NULL) 1587 return TRUE; 1588 1589 dbus_message_set_auto_start (message, FALSE); 1590 1591 flags = 0; 1592 if (!dbus_message_append_args (message, 1593 DBUS_TYPE_STRING, &nonexistent, 1594 DBUS_TYPE_UINT32, &flags, 1595 DBUS_TYPE_INVALID)) 1596 { 1597 dbus_message_unref (message); 1598 return TRUE; 1599 } 1600 1601 if (!dbus_connection_send (connection, message, &serial)) 1602 { 1603 dbus_message_unref (message); 1604 return TRUE; 1605 } 1606 1607 dbus_message_unref (message); 1608 message = NULL; 1609 1610 bus_test_run_everything (context); 1611 block_connection_until_message_from_bus (context, connection, "reply to ActivateService on nonexistent"); 1612 bus_test_run_everything (context); 1613 1614 if (!dbus_connection_get_is_connected (connection)) 1615 { 1616 _dbus_verbose ("connection was disconnected\n"); 1617 return TRUE; 1618 } 1619 1620 retval = FALSE; 1621 1622 message = pop_message_waiting_for_memory (connection); 1623 if (message == NULL) 1624 { 1625 _dbus_warn ("Did not receive a reply to %s %d on %p\n", 1626 "StartServiceByName", serial, connection); 1627 goto out; 1628 } 1629 1630 verbose_message_received (connection, message); 1631 1632 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR) 1633 { 1634 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS)) 1635 { 1636 _dbus_warn ("Message has wrong sender %s\n", 1637 dbus_message_get_sender (message) ? 1638 dbus_message_get_sender (message) : "(none)"); 1639 goto out; 1640 } 1641 1642 if (dbus_message_is_error (message, 1643 DBUS_ERROR_NO_MEMORY)) 1644 { 1645 ; /* good, this is a valid response */ 1646 } 1647 else if (dbus_message_is_error (message, 1648 DBUS_ERROR_SERVICE_UNKNOWN)) 1649 { 1650 ; /* good, this is expected also */ 1651 } 1652 else 1653 { 1654 warn_unexpected (connection, message, "not this error"); 1655 goto out; 1656 } 1657 } 1658 else 1659 { 1660 _dbus_warn ("Did not expect to successfully activate %s\n", 1661 NONEXISTENT_SERVICE_NAME); 1662 goto out; 1663 } 1664 1665 retval = TRUE; 1666 1667 out: 1668 if (message) 1669 dbus_message_unref (message); 1670 1671 return retval; 1672 } 1673 1674 /* returns TRUE if the correct thing happens, 1675 * but the correct thing may include OOM errors. 1676 */ 1677 static dbus_bool_t 1678 check_nonexistent_service_auto_start (BusContext *context, 1679 DBusConnection *connection) 1680 { 1681 DBusMessage *message; 1682 dbus_uint32_t serial; 1683 dbus_bool_t retval; 1684 1685 message = dbus_message_new_method_call (NONEXISTENT_SERVICE_NAME, 1686 "/org/freedesktop/TestSuite", 1687 "org.freedesktop.TestSuite", 1688 "Echo"); 1689 1690 if (message == NULL) 1691 return TRUE; 1692 1693 if (!dbus_connection_send (connection, message, &serial)) 1694 { 1695 dbus_message_unref (message); 1696 return TRUE; 1697 } 1698 1699 dbus_message_unref (message); 1700 message = NULL; 1701 1702 bus_test_run_everything (context); 1703 block_connection_until_message_from_bus (context, connection, "reply to Echo"); 1704 bus_test_run_everything (context); 1705 1706 if (!dbus_connection_get_is_connected (connection)) 1707 { 1708 _dbus_verbose ("connection was disconnected\n"); 1709 return TRUE; 1710 } 1711 1712 retval = FALSE; 1713 1714 message = pop_message_waiting_for_memory (connection); 1715 1716 if (message == NULL) 1717 { 1718 _dbus_warn ("Did not receive a reply to %s %d on %p\n", 1719 "Echo message (auto activation)", serial, connection); 1720 goto out; 1721 } 1722 1723 verbose_message_received (connection, message); 1724 1725 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR) 1726 { 1727 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS)) 1728 { 1729 _dbus_warn ("Message has wrong sender %s\n", 1730 dbus_message_get_sender (message) ? 1731 dbus_message_get_sender (message) : "(none)"); 1732 goto out; 1733 } 1734 1735 if (dbus_message_is_error (message, 1736 DBUS_ERROR_NO_MEMORY)) 1737 { 1738 ; /* good, this is a valid response */ 1739 } 1740 else if (dbus_message_is_error (message, 1741 DBUS_ERROR_SERVICE_UNKNOWN)) 1742 { 1743 ; /* good, this is expected also */ 1744 } 1745 else 1746 { 1747 warn_unexpected (connection, message, "not this error"); 1748 goto out; 1749 } 1750 } 1751 else 1752 { 1753 _dbus_warn ("Did not expect to successfully activate %s\n", 1754 NONEXISTENT_SERVICE_NAME); 1755 goto out; 1756 } 1757 1758 retval = TRUE; 1759 1760 out: 1761 if (message) 1762 dbus_message_unref (message); 1763 1764 return retval; 1765 } 1766 1767 static dbus_bool_t 1768 check_base_service_activated (BusContext *context, 1769 DBusConnection *connection, 1770 DBusMessage *initial_message, 1771 const char **base_service_p) 1772 { 1773 DBusMessage *message; 1774 dbus_bool_t retval; 1775 DBusError error; 1776 const char *base_service, *base_service_from_bus, *old_owner; 1777 1778 retval = FALSE; 1779 1780 dbus_error_init (&error); 1781 base_service = NULL; 1782 old_owner = NULL; 1783 base_service_from_bus = NULL; 1784 1785 message = initial_message; 1786 dbus_message_ref (message); 1787 1788 if (dbus_message_is_signal (message, 1789 DBUS_INTERFACE_DBUS, 1790 "NameOwnerChanged")) 1791 { 1792 CheckServiceOwnerChangedData socd; 1793 1794 reget_service_name_arg: 1795 base_service = NULL; 1796 old_owner = NULL; 1797 base_service_from_bus = NULL; 1798 1799 if (!dbus_message_get_args (message, &error, 1800 DBUS_TYPE_STRING, &base_service, 1801 DBUS_TYPE_STRING, &old_owner, 1802 DBUS_TYPE_STRING, &base_service_from_bus, 1803 DBUS_TYPE_INVALID)) 1804 { 1805 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) 1806 { 1807 dbus_error_free (&error); 1808 _dbus_wait_for_memory (); 1809 goto reget_service_name_arg; 1810 } 1811 else 1812 { 1813 _dbus_warn ("Message %s doesn't have a service name: %s\n", 1814 "NameOwnerChanged (creation)", 1815 error.message); 1816 goto out; 1817 } 1818 } 1819 1820 if (*base_service != ':') 1821 { 1822 _dbus_warn ("Expected base service activation, got \"%s\" instead\n", 1823 base_service); 1824 goto out; 1825 } 1826 1827 if (strcmp (base_service, base_service_from_bus) != 0) 1828 { 1829 _dbus_warn ("Expected base service activation, got \"%s\" instead with owner \"%s\"\n", 1830 base_service, base_service_from_bus); 1831 goto out; 1832 } 1833 1834 if (old_owner[0]) 1835 { 1836 _dbus_warn ("Received an old_owner argument during base service activation, \"%s\"\n", 1837 old_owner); 1838 goto out; 1839 } 1840 1841 socd.expected_kind = SERVICE_CREATED; 1842 socd.expected_service_name = base_service; 1843 socd.failed = FALSE; 1844 socd.skip_connection = connection; 1845 bus_test_clients_foreach (check_service_owner_changed_foreach, 1846 &socd); 1847 1848 if (socd.failed) 1849 goto out; 1850 } 1851 else 1852 { 1853 warn_unexpected (connection, message, "NameOwnerChanged (creation) for base service"); 1854 1855 goto out; 1856 } 1857 1858 if (base_service_p) 1859 *base_service_p = base_service; 1860 1861 retval = TRUE; 1862 1863 out: 1864 if (message) 1865 dbus_message_unref (message); 1866 dbus_error_free (&error); 1867 1868 return retval; 1869 } 1870 1871 static dbus_bool_t 1872 check_service_activated (BusContext *context, 1873 DBusConnection *connection, 1874 const char *activated_name, 1875 const char *base_service_name, 1876 DBusMessage *initial_message) 1877 { 1878 DBusMessage *message; 1879 dbus_bool_t retval; 1880 DBusError error; 1881 dbus_uint32_t activation_result; 1882 1883 retval = FALSE; 1884 1885 dbus_error_init (&error); 1886 1887 message = initial_message; 1888 dbus_message_ref (message); 1889 1890 if (dbus_message_is_signal (message, 1891 DBUS_INTERFACE_DBUS, 1892 "NameOwnerChanged")) 1893 { 1894 CheckServiceOwnerChangedData socd; 1895 const char *service_name, *base_service_from_bus, *old_owner; 1896 1897 reget_service_name_arg: 1898 service_name = NULL; 1899 old_owner = NULL; 1900 base_service_from_bus = NULL; 1901 1902 if (!dbus_message_get_args (message, &error, 1903 DBUS_TYPE_STRING, &service_name, 1904 DBUS_TYPE_STRING, &old_owner, 1905 DBUS_TYPE_STRING, &base_service_from_bus, 1906 DBUS_TYPE_INVALID)) 1907 { 1908 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) 1909 { 1910 dbus_error_free (&error); 1911 _dbus_wait_for_memory (); 1912 goto reget_service_name_arg; 1913 } 1914 else 1915 { 1916 _dbus_warn ("Message %s doesn't have a service name: %s\n", 1917 "NameOwnerChanged (creation)", 1918 error.message); 1919 goto out; 1920 } 1921 } 1922 1923 if (strcmp (service_name, activated_name) != 0) 1924 { 1925 _dbus_warn ("Expected to see service %s created, saw %s instead\n", 1926 activated_name, service_name); 1927 goto out; 1928 } 1929 1930 if (strcmp (base_service_name, base_service_from_bus) != 0) 1931 { 1932 _dbus_warn ("NameOwnerChanged reports wrong base service: %s owner, expected %s instead\n", 1933 base_service_from_bus, base_service_name); 1934 goto out; 1935 } 1936 1937 if (old_owner[0]) 1938 { 1939 _dbus_warn ("expected a %s, got a %s\n", 1940 "NameOwnerChanged (creation)", 1941 "NameOwnerChanged (change)"); 1942 goto out; 1943 } 1944 1945 socd.expected_kind = SERVICE_CREATED; 1946 socd.skip_connection = connection; 1947 socd.failed = FALSE; 1948 socd.expected_service_name = service_name; 1949 bus_test_clients_foreach (check_service_owner_changed_foreach, 1950 &socd); 1951 1952 if (socd.failed) 1953 goto out; 1954 1955 dbus_message_unref (message); 1956 service_name = NULL; 1957 old_owner = NULL; 1958 base_service_from_bus = NULL; 1959 1960 message = pop_message_waiting_for_memory (connection); 1961 if (message == NULL) 1962 { 1963 _dbus_warn ("Expected a reply to %s, got nothing\n", 1964 "StartServiceByName"); 1965 goto out; 1966 } 1967 } 1968 else 1969 { 1970 warn_unexpected (connection, message, "NameOwnerChanged for the activated name"); 1971 1972 goto out; 1973 } 1974 1975 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN) 1976 { 1977 warn_unexpected (connection, message, "reply to StartServiceByName"); 1978 1979 goto out; 1980 } 1981 1982 activation_result = 0; 1983 if (!dbus_message_get_args (message, &error, 1984 DBUS_TYPE_UINT32, &activation_result, 1985 DBUS_TYPE_INVALID)) 1986 { 1987 if (!dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) 1988 { 1989 _dbus_warn ("Did not have activation result first argument to %s: %s\n", 1990 "StartServiceByName", error.message); 1991 goto out; 1992 } 1993 1994 dbus_error_free (&error); 1995 } 1996 else 1997 { 1998 if (activation_result == DBUS_START_REPLY_SUCCESS) 1999 ; /* Good */ 2000 else if (activation_result == DBUS_START_REPLY_ALREADY_RUNNING) 2001 ; /* Good also */ 2002 else 2003 { 2004 _dbus_warn ("Activation result was %u, no good.\n", 2005 activation_result); 2006 goto out; 2007 } 2008 } 2009 2010 dbus_message_unref (message); 2011 message = NULL; 2012 2013 if (!check_no_leftovers (context)) 2014 { 2015 _dbus_warn ("Messages were left over after verifying existent activation results\n"); 2016 goto out; 2017 } 2018 2019 retval = TRUE; 2020 2021 out: 2022 if (message) 2023 dbus_message_unref (message); 2024 dbus_error_free (&error); 2025 2026 return retval; 2027 } 2028 2029 static dbus_bool_t 2030 check_service_auto_activated (BusContext *context, 2031 DBusConnection *connection, 2032 const char *activated_name, 2033 const char *base_service_name, 2034 DBusMessage *initial_message) 2035 { 2036 DBusMessage *message; 2037 dbus_bool_t retval; 2038 DBusError error; 2039 2040 retval = FALSE; 2041 2042 dbus_error_init (&error); 2043 2044 message = initial_message; 2045 dbus_message_ref (message); 2046 2047 if (dbus_message_is_signal (message, 2048 DBUS_INTERFACE_DBUS, 2049 "NameOwnerChanged")) 2050 { 2051 const char *service_name; 2052 CheckServiceOwnerChangedData socd; 2053 2054 reget_service_name_arg: 2055 if (!dbus_message_get_args (message, &error, 2056 DBUS_TYPE_STRING, &service_name, 2057 DBUS_TYPE_INVALID)) 2058 { 2059 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) 2060 { 2061 dbus_error_free (&error); 2062 _dbus_wait_for_memory (); 2063 goto reget_service_name_arg; 2064 } 2065 else 2066 { 2067 _dbus_warn ("Message %s doesn't have a service name: %s\n", 2068 "NameOwnerChanged", 2069 error.message); 2070 dbus_error_free (&error); 2071 goto out; 2072 } 2073 } 2074 2075 if (strcmp (service_name, activated_name) != 0) 2076 { 2077 _dbus_warn ("Expected to see service %s created, saw %s instead\n", 2078 activated_name, service_name); 2079 goto out; 2080 } 2081 2082 socd.expected_kind = SERVICE_CREATED; 2083 socd.expected_service_name = service_name; 2084 socd.failed = FALSE; 2085 socd.skip_connection = connection; 2086 bus_test_clients_foreach (check_service_owner_changed_foreach, 2087 &socd); 2088 2089 if (socd.failed) 2090 goto out; 2091 2092 /* Note that this differs from regular activation in that we don't get a 2093 * reply to ActivateService here. 2094 */ 2095 2096 dbus_message_unref (message); 2097 message = NULL; 2098 service_name = NULL; 2099 } 2100 else 2101 { 2102 warn_unexpected (connection, message, "NameOwnerChanged for the activated name"); 2103 2104 goto out; 2105 } 2106 2107 retval = TRUE; 2108 2109 out: 2110 if (message) 2111 dbus_message_unref (message); 2112 2113 return retval; 2114 } 2115 2116 static dbus_bool_t 2117 check_service_deactivated (BusContext *context, 2118 DBusConnection *connection, 2119 const char *activated_name, 2120 const char *base_service) 2121 { 2122 dbus_bool_t retval; 2123 CheckServiceOwnerChangedData socd; 2124 2125 retval = FALSE; 2126 2127 /* Now we are expecting ServiceOwnerChanged (deletion) messages for the base 2128 * service and the activated_name. The base service 2129 * notification is required to come last. 2130 */ 2131 socd.expected_kind = SERVICE_DELETED; 2132 socd.expected_service_name = activated_name; 2133 socd.failed = FALSE; 2134 socd.skip_connection = NULL; 2135 bus_test_clients_foreach (check_service_owner_changed_foreach, 2136 &socd); 2137 2138 if (socd.failed) 2139 goto out; 2140 2141 socd.expected_kind = SERVICE_DELETED; 2142 socd.expected_service_name = base_service; 2143 socd.failed = FALSE; 2144 socd.skip_connection = NULL; 2145 bus_test_clients_foreach (check_service_owner_changed_foreach, 2146 &socd); 2147 2148 if (socd.failed) 2149 goto out; 2150 2151 retval = TRUE; 2152 2153 out: 2154 return retval; 2155 } 2156 2157 static dbus_bool_t 2158 check_send_exit_to_service (BusContext *context, 2159 DBusConnection *connection, 2160 const char *service_name, 2161 const char *base_service) 2162 { 2163 dbus_bool_t got_error; 2164 DBusMessage *message; 2165 dbus_uint32_t serial; 2166 dbus_bool_t retval; 2167 2168 _dbus_verbose ("Sending exit message to the test service\n"); 2169 2170 retval = FALSE; 2171 2172 /* Kill off the test service by sending it a quit message */ 2173 message = dbus_message_new_method_call (service_name, 2174 "/org/freedesktop/TestSuite", 2175 "org.freedesktop.TestSuite", 2176 "Exit"); 2177 2178 if (message == NULL) 2179 { 2180 /* Do this again; we still need the service to exit... */ 2181 if (!check_send_exit_to_service (context, connection, 2182 service_name, base_service)) 2183 goto out; 2184 2185 return TRUE; 2186 } 2187 2188 if (!dbus_connection_send (connection, message, &serial)) 2189 { 2190 dbus_message_unref (message); 2191 2192 /* Do this again; we still need the service to exit... */ 2193 if (!check_send_exit_to_service (context, connection, 2194 service_name, base_service)) 2195 goto out; 2196 2197 return TRUE; 2198 } 2199 2200 dbus_message_unref (message); 2201 message = NULL; 2202 2203 /* send message */ 2204 bus_test_run_clients_loop (SEND_PENDING (connection)); 2205 2206 /* read it in and write it out to test service */ 2207 bus_test_run_bus_loop (context, FALSE); 2208 2209 /* see if we got an error during message bus dispatching */ 2210 bus_test_run_clients_loop (FALSE); 2211 message = borrow_message_waiting_for_memory (connection); 2212 got_error = message != NULL && dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR; 2213 if (message) 2214 { 2215 dbus_connection_return_message (connection, message); 2216 message = NULL; 2217 } 2218 2219 if (!got_error) 2220 { 2221 /* If no error, wait for the test service to exit */ 2222 block_connection_until_message_from_bus (context, connection, "test service to exit"); 2223 2224 bus_test_run_everything (context); 2225 } 2226 2227 if (got_error) 2228 { 2229 message = pop_message_waiting_for_memory (connection); 2230 _dbus_assert (message != NULL); 2231 2232 if (dbus_message_get_reply_serial (message) != serial) 2233 { 2234 warn_unexpected (connection, message, 2235 "error with the correct reply serial"); 2236 goto out; 2237 } 2238 2239 if (!dbus_message_is_error (message, 2240 DBUS_ERROR_NO_MEMORY)) 2241 { 2242 warn_unexpected (connection, message, 2243 "a no memory error from asking test service to exit"); 2244 goto out; 2245 } 2246 2247 _dbus_verbose ("Got error %s when asking test service to exit\n", 2248 dbus_message_get_error_name (message)); 2249 2250 /* Do this again; we still need the service to exit... */ 2251 if (!check_send_exit_to_service (context, connection, 2252 service_name, base_service)) 2253 goto out; 2254 } 2255 else 2256 { 2257 if (!check_service_deactivated (context, connection, 2258 service_name, base_service)) 2259 goto out; 2260 2261 /* Should now have a NoReply error from the Exit() method 2262 * call; it should have come after all the deactivation 2263 * stuff. 2264 */ 2265 message = pop_message_waiting_for_memory (connection); 2266 2267 if (message == NULL) 2268 { 2269 warn_unexpected (connection, NULL, 2270 "reply to Exit() method call"); 2271 goto out; 2272 } 2273 if (!dbus_message_is_error (message, 2274 DBUS_ERROR_NO_REPLY)) 2275 { 2276 warn_unexpected (connection, message, 2277 "NoReply error from Exit() method call"); 2278 goto out; 2279 } 2280 2281 if (dbus_message_get_reply_serial (message) != serial) 2282 { 2283 warn_unexpected (connection, message, 2284 "error with the correct reply serial"); 2285 goto out; 2286 } 2287 2288 _dbus_verbose ("Got error %s after test service exited\n", 2289 dbus_message_get_error_name (message)); 2290 2291 if (!check_no_leftovers (context)) 2292 { 2293 _dbus_warn ("Messages were left over after %s\n", 2294 _DBUS_FUNCTION_NAME); 2295 goto out; 2296 } 2297 } 2298 2299 retval = TRUE; 2300 2301 out: 2302 if (message) 2303 dbus_message_unref (message); 2304 2305 return retval; 2306 } 2307 2308 static dbus_bool_t 2309 check_got_error (BusContext *context, 2310 DBusConnection *connection, 2311 const char *first_error_name, 2312 ...) 2313 { 2314 DBusMessage *message; 2315 dbus_bool_t retval; 2316 va_list ap; 2317 dbus_bool_t error_found; 2318 const char *error_name; 2319 2320 retval = FALSE; 2321 2322 message = pop_message_waiting_for_memory (connection); 2323 if (message == NULL) 2324 { 2325 _dbus_warn ("Did not get an expected error\n"); 2326 goto out; 2327 } 2328 2329 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR) 2330 { 2331 warn_unexpected (connection, message, "an error"); 2332 2333 goto out; 2334 } 2335 2336 error_found = FALSE; 2337 2338 va_start (ap, first_error_name); 2339 error_name = first_error_name; 2340 while (error_name != NULL) 2341 { 2342 if (dbus_message_is_error (message, error_name)) 2343 { 2344 error_found = TRUE; 2345 break; 2346 } 2347 error_name = va_arg (ap, char*); 2348 } 2349 va_end (ap); 2350 2351 if (!error_found) 2352 { 2353 _dbus_warn ("Expected error %s or other, got %s instead\n", 2354 first_error_name, 2355 dbus_message_get_error_name (message)); 2356 goto out; 2357 } 2358 2359 retval = TRUE; 2360 2361 out: 2362 if (message) 2363 dbus_message_unref (message); 2364 2365 return retval; 2366 } 2367 2368 typedef enum 2369 { 2370 GOT_SERVICE_CREATED, 2371 GOT_SERVICE_DELETED, 2372 GOT_ERROR, 2373 GOT_SOMETHING_ELSE 2374 } GotServiceInfo; 2375 2376 static GotServiceInfo 2377 check_got_service_info (DBusMessage *message) 2378 { 2379 GotServiceInfo message_kind; 2380 2381 if (dbus_message_is_signal (message, 2382 DBUS_INTERFACE_DBUS, 2383 "NameOwnerChanged")) 2384 { 2385 DBusError error; 2386 const char *service_name, *old_owner, *new_owner; 2387 dbus_error_init (&error); 2388 2389 reget_service_info_data: 2390 service_name = NULL; 2391 old_owner = NULL; 2392 new_owner = NULL; 2393 2394 dbus_message_get_args (message, &error, 2395 DBUS_TYPE_STRING, &service_name, 2396 DBUS_TYPE_STRING, &old_owner, 2397 DBUS_TYPE_STRING, &new_owner, 2398 DBUS_TYPE_INVALID); 2399 if (dbus_error_is_set (&error)) 2400 { 2401 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) 2402 { 2403 dbus_error_free (&error); 2404 goto reget_service_info_data; 2405 } 2406 else 2407 { 2408 _dbus_warn ("unexpected arguments for NameOwnerChanged message\n"); 2409 message_kind = GOT_SOMETHING_ELSE; 2410 } 2411 } 2412 else if (!old_owner[0]) 2413 message_kind = GOT_SERVICE_CREATED; 2414 else if (!new_owner[0]) 2415 message_kind = GOT_SERVICE_DELETED; 2416 else 2417 message_kind = GOT_SOMETHING_ELSE; 2418 2419 dbus_error_free (&error); 2420 } 2421 else if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR) 2422 message_kind = GOT_ERROR; 2423 else 2424 message_kind = GOT_SOMETHING_ELSE; 2425 2426 return message_kind; 2427 } 2428 2429 #define EXISTENT_SERVICE_NAME "org.freedesktop.DBus.TestSuiteEchoService" 2430 2431 /* returns TRUE if the correct thing happens, 2432 * but the correct thing may include OOM errors. 2433 */ 2434 static dbus_bool_t 2435 check_existent_service_no_auto_start (BusContext *context, 2436 DBusConnection *connection) 2437 { 2438 DBusMessage *message; 2439 DBusMessage *base_service_message; 2440 const char *base_service; 2441 dbus_uint32_t serial; 2442 dbus_bool_t retval; 2443 const char *existent = EXISTENT_SERVICE_NAME; 2444 dbus_uint32_t flags; 2445 2446 base_service_message = NULL; 2447 2448 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS, 2449 DBUS_PATH_DBUS, 2450 DBUS_INTERFACE_DBUS, 2451 "StartServiceByName"); 2452 2453 if (message == NULL) 2454 return TRUE; 2455 2456 dbus_message_set_auto_start (message, FALSE); 2457 2458 flags = 0; 2459 if (!dbus_message_append_args (message, 2460 DBUS_TYPE_STRING, &existent, 2461 DBUS_TYPE_UINT32, &flags, 2462 DBUS_TYPE_INVALID)) 2463 { 2464 dbus_message_unref (message); 2465 return TRUE; 2466 } 2467 2468 if (!dbus_connection_send (connection, message, &serial)) 2469 { 2470 dbus_message_unref (message); 2471 return TRUE; 2472 } 2473 2474 dbus_message_unref (message); 2475 message = NULL; 2476 2477 bus_test_run_everything (context); 2478 2479 /* now wait for the message bus to hear back from the activated 2480 * service. 2481 */ 2482 block_connection_until_message_from_bus (context, connection, "activated service to connect"); 2483 2484 bus_test_run_everything (context); 2485 2486 if (!dbus_connection_get_is_connected (connection)) 2487 { 2488 _dbus_verbose ("connection was disconnected\n"); 2489 return TRUE; 2490 } 2491 2492 retval = FALSE; 2493 2494 message = pop_message_waiting_for_memory (connection); 2495 if (message == NULL) 2496 { 2497 _dbus_warn ("Did not receive any messages after %s %d on %p\n", 2498 "StartServiceByName", serial, connection); 2499 goto out; 2500 } 2501 2502 verbose_message_received (connection, message); 2503 _dbus_verbose (" (after sending %s)\n", "StartServiceByName"); 2504 2505 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR) 2506 { 2507 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS)) 2508 { 2509 _dbus_warn ("Message has wrong sender %s\n", 2510 dbus_message_get_sender (message) ? 2511 dbus_message_get_sender (message) : "(none)"); 2512 goto out; 2513 } 2514 2515 if (dbus_message_is_error (message, 2516 DBUS_ERROR_NO_MEMORY)) 2517 { 2518 ; /* good, this is a valid response */ 2519 } 2520 else if (dbus_message_is_error (message, 2521 DBUS_ERROR_SPAWN_CHILD_EXITED) || 2522 dbus_message_is_error (message, 2523 DBUS_ERROR_SPAWN_CHILD_SIGNALED) || 2524 dbus_message_is_error (message, 2525 DBUS_ERROR_SPAWN_EXEC_FAILED)) 2526 { 2527 ; /* good, this is expected also */ 2528 } 2529 else 2530 { 2531 _dbus_warn ("Did not expect error %s\n", 2532 dbus_message_get_error_name (message)); 2533 goto out; 2534 } 2535 } 2536 else 2537 { 2538 GotServiceInfo message_kind; 2539 2540 if (!check_base_service_activated (context, connection, 2541 message, &base_service)) 2542 goto out; 2543 2544 base_service_message = message; 2545 message = NULL; 2546 2547 /* We may need to block here for the test service to exit or finish up */ 2548 block_connection_until_message_from_bus (context, connection, "test service to exit or finish up"); 2549 2550 message = dbus_connection_borrow_message (connection); 2551 if (message == NULL) 2552 { 2553 _dbus_warn ("Did not receive any messages after base service creation notification\n"); 2554 goto out; 2555 } 2556 2557 message_kind = check_got_service_info (message); 2558 2559 dbus_connection_return_message (connection, message); 2560 message = NULL; 2561 2562 switch (message_kind) 2563 { 2564 case GOT_SOMETHING_ELSE: 2565 _dbus_warn ("Unexpected message after ActivateService " 2566 "(should be an error or a service announcement"); 2567 goto out; 2568 2569 case GOT_ERROR: 2570 if (!check_got_error (context, connection, 2571 DBUS_ERROR_SPAWN_CHILD_EXITED, 2572 DBUS_ERROR_NO_MEMORY, 2573 NULL)) 2574 goto out; 2575 /* A service deleted should be coming along now after this error. 2576 * We can also get the error *after* the service deleted. 2577 */ 2578 2579 /* fall through */ 2580 2581 case GOT_SERVICE_DELETED: 2582 { 2583 /* The service started up and got a base address, but then 2584 * failed to register under EXISTENT_SERVICE_NAME 2585 */ 2586 CheckServiceOwnerChangedData socd; 2587 2588 socd.expected_kind = SERVICE_DELETED; 2589 socd.expected_service_name = base_service; 2590 socd.failed = FALSE; 2591 socd.skip_connection = NULL; 2592 2593 bus_test_clients_foreach (check_service_owner_changed_foreach, 2594 &socd); 2595 2596 if (socd.failed) 2597 goto out; 2598 2599 /* Now we should get an error about the service exiting 2600 * if we didn't get it before. 2601 */ 2602 if (message_kind != GOT_ERROR) 2603 { 2604 block_connection_until_message_from_bus (context, connection, "error about service exiting"); 2605 2606 /* and process everything again */ 2607 bus_test_run_everything (context); 2608 2609 if (!check_got_error (context, connection, 2610 DBUS_ERROR_SPAWN_CHILD_EXITED, 2611 DBUS_ERROR_NO_MEMORY, 2612 NULL)) 2613 goto out; 2614 } 2615 break; 2616 } 2617 2618 case GOT_SERVICE_CREATED: 2619 message = pop_message_waiting_for_memory (connection); 2620 if (message == NULL) 2621 { 2622 _dbus_warn ("Failed to pop message we just put back! " 2623 "should have been a NameOwnerChanged (creation)\n"); 2624 goto out; 2625 } 2626 2627 if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME, 2628 base_service, message)) 2629 goto out; 2630 2631 dbus_message_unref (message); 2632 message = NULL; 2633 2634 if (!check_no_leftovers (context)) 2635 { 2636 _dbus_warn ("Messages were left over after successful activation\n"); 2637 goto out; 2638 } 2639 2640 if (!check_send_exit_to_service (context, connection, 2641 EXISTENT_SERVICE_NAME, base_service)) 2642 goto out; 2643 2644 break; 2645 } 2646 } 2647 2648 retval = TRUE; 2649 2650 out: 2651 if (message) 2652 dbus_message_unref (message); 2653 2654 if (base_service_message) 2655 dbus_message_unref (base_service_message); 2656 2657 return retval; 2658 } 2659 2660 #ifndef DBUS_WIN_FIXME 2661 /* returns TRUE if the correct thing happens, 2662 * but the correct thing may include OOM errors. 2663 */ 2664 static dbus_bool_t 2665 check_segfault_service_no_auto_start (BusContext *context, 2666 DBusConnection *connection) 2667 { 2668 DBusMessage *message; 2669 dbus_uint32_t serial; 2670 dbus_bool_t retval; 2671 const char *segv_service; 2672 dbus_uint32_t flags; 2673 2674 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS, 2675 DBUS_PATH_DBUS, 2676 DBUS_INTERFACE_DBUS, 2677 "StartServiceByName"); 2678 2679 if (message == NULL) 2680 return TRUE; 2681 2682 dbus_message_set_auto_start (message, FALSE); 2683 2684 segv_service = "org.freedesktop.DBus.TestSuiteSegfaultService"; 2685 flags = 0; 2686 if (!dbus_message_append_args (message, 2687 DBUS_TYPE_STRING, &segv_service, 2688 DBUS_TYPE_UINT32, &flags, 2689 DBUS_TYPE_INVALID)) 2690 { 2691 dbus_message_unref (message); 2692 return TRUE; 2693 } 2694 2695 if (!dbus_connection_send (connection, message, &serial)) 2696 { 2697 dbus_message_unref (message); 2698 return TRUE; 2699 } 2700 2701 dbus_message_unref (message); 2702 message = NULL; 2703 2704 bus_test_run_everything (context); 2705 block_connection_until_message_from_bus (context, connection, "reply to activating segfault service"); 2706 bus_test_run_everything (context); 2707 2708 if (!dbus_connection_get_is_connected (connection)) 2709 { 2710 _dbus_verbose ("connection was disconnected\n"); 2711 return TRUE; 2712 } 2713 2714 retval = FALSE; 2715 2716 message = pop_message_waiting_for_memory (connection); 2717 if (message == NULL) 2718 { 2719 _dbus_warn ("Did not receive a reply to %s %d on %p\n", 2720 "StartServiceByName", serial, connection); 2721 goto out; 2722 } 2723 2724 verbose_message_received (connection, message); 2725 2726 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR) 2727 { 2728 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS)) 2729 { 2730 _dbus_warn ("Message has wrong sender %s\n", 2731 dbus_message_get_sender (message) ? 2732 dbus_message_get_sender (message) : "(none)"); 2733 goto out; 2734 } 2735 2736 if (dbus_message_is_error (message, 2737 DBUS_ERROR_NO_MEMORY)) 2738 { 2739 ; /* good, this is a valid response */ 2740 } 2741 else if (dbus_message_is_error (message, 2742 DBUS_ERROR_FAILED)) 2743 { 2744 const char *servicehelper; 2745 servicehelper = bus_context_get_servicehelper (context); 2746 /* make sure this only happens with the launch helper */ 2747 _dbus_assert (servicehelper != NULL); 2748 } 2749 else if (dbus_message_is_error (message, 2750 DBUS_ERROR_SPAWN_CHILD_SIGNALED)) 2751 { 2752 ; /* good, this is expected also */ 2753 } 2754 else 2755 { 2756 warn_unexpected (connection, message, "not this error"); 2757 2758 goto out; 2759 } 2760 } 2761 else 2762 { 2763 _dbus_warn ("Did not expect to successfully activate segfault service\n"); 2764 goto out; 2765 } 2766 2767 retval = TRUE; 2768 2769 out: 2770 if (message) 2771 dbus_message_unref (message); 2772 2773 return retval; 2774 } 2775 2776 2777 /* returns TRUE if the correct thing happens, 2778 * but the correct thing may include OOM errors. 2779 */ 2780 static dbus_bool_t 2781 check_segfault_service_auto_start (BusContext *context, 2782 DBusConnection *connection) 2783 { 2784 DBusMessage *message; 2785 dbus_uint32_t serial; 2786 dbus_bool_t retval; 2787 2788 message = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteSegfaultService", 2789 "/org/freedesktop/TestSuite", 2790 "org.freedesktop.TestSuite", 2791 "Echo"); 2792 2793 if (message == NULL) 2794 return TRUE; 2795 2796 if (!dbus_connection_send (connection, message, &serial)) 2797 { 2798 dbus_message_unref (message); 2799 return TRUE; 2800 } 2801 2802 dbus_message_unref (message); 2803 message = NULL; 2804 2805 bus_test_run_everything (context); 2806 block_connection_until_message_from_bus (context, connection, "reply to Echo on segfault service"); 2807 bus_test_run_everything (context); 2808 2809 if (!dbus_connection_get_is_connected (connection)) 2810 { 2811 _dbus_verbose ("connection was disconnected\n"); 2812 return TRUE; 2813 } 2814 2815 retval = FALSE; 2816 2817 message = pop_message_waiting_for_memory (connection); 2818 if (message == NULL) 2819 { 2820 _dbus_warn ("Did not receive a reply to %s %d on %p\n", 2821 "Echo message (auto activation)", serial, connection); 2822 goto out; 2823 } 2824 2825 verbose_message_received (connection, message); 2826 2827 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR) 2828 { 2829 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS)) 2830 { 2831 _dbus_warn ("Message has wrong sender %s\n", 2832 dbus_message_get_sender (message) ? 2833 dbus_message_get_sender (message) : "(none)"); 2834 goto out; 2835 } 2836 2837 if (dbus_message_is_error (message, 2838 DBUS_ERROR_NO_MEMORY)) 2839 { 2840 ; /* good, this is a valid response */ 2841 } 2842 else if (dbus_message_is_error (message, 2843 DBUS_ERROR_SPAWN_CHILD_SIGNALED)) 2844 { 2845 ; /* good, this is expected also */ 2846 } 2847 else 2848 { 2849 warn_unexpected (connection, message, "not this error"); 2850 2851 goto out; 2852 } 2853 } 2854 else 2855 { 2856 _dbus_warn ("Did not expect to successfully activate segfault service\n"); 2857 goto out; 2858 } 2859 2860 retval = TRUE; 2861 2862 out: 2863 if (message) 2864 dbus_message_unref (message); 2865 2866 return retval; 2867 } 2868 #endif 2869 2870 #define TEST_ECHO_MESSAGE "Test echo message" 2871 #define TEST_RUN_HELLO_FROM_SELF_MESSAGE "Test sending message to self" 2872 2873 /* returns TRUE if the correct thing happens, 2874 * but the correct thing may include OOM errors. 2875 */ 2876 static dbus_bool_t 2877 check_existent_hello_from_self (BusContext *context, 2878 DBusConnection *connection) 2879 { 2880 DBusMessage *message; 2881 dbus_uint32_t serial; 2882 const char *text; 2883 2884 message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME, 2885 "/org/freedesktop/TestSuite", 2886 "org.freedesktop.TestSuite", 2887 "RunHelloFromSelf"); 2888 2889 if (message == NULL) 2890 return TRUE; 2891 2892 text = TEST_RUN_HELLO_FROM_SELF_MESSAGE; 2893 if (!dbus_message_append_args (message, 2894 DBUS_TYPE_STRING, &text, 2895 DBUS_TYPE_INVALID)) 2896 { 2897 dbus_message_unref (message); 2898 return TRUE; 2899 } 2900 2901 if (!dbus_connection_send (connection, message, &serial)) 2902 { 2903 dbus_message_unref (message); 2904 return TRUE; 2905 } 2906 2907 dbus_message_unref (message); 2908 message = NULL; 2909 2910 bus_test_run_everything (context); 2911 2912 /* Note: if this test is run in OOM mode, it will block when the bus 2913 * doesn't send a reply due to OOM. 2914 */ 2915 block_connection_until_message_from_bus (context, connection, "reply from running hello from self"); 2916 2917 message = pop_message_waiting_for_memory (connection); 2918 if (message == NULL) 2919 { 2920 _dbus_warn ("Failed to pop message! Should have been reply from RunHelloFromSelf message\n"); 2921 return FALSE; 2922 } 2923 2924 if (dbus_message_get_reply_serial (message) != serial) 2925 { 2926 _dbus_warn ("Wrong reply serial\n"); 2927 dbus_message_unref (message); 2928 return FALSE; 2929 } 2930 2931 dbus_message_unref (message); 2932 message = NULL; 2933 2934 return TRUE; 2935 } 2936 2937 /* returns TRUE if the correct thing happens, 2938 * but the correct thing may include OOM errors. 2939 */ 2940 static dbus_bool_t 2941 check_existent_ping (BusContext *context, 2942 DBusConnection *connection) 2943 { 2944 DBusMessage *message; 2945 dbus_uint32_t serial; 2946 message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME, 2947 "/org/freedesktop/TestSuite", 2948 "org.freedesktop.DBus.Peer", 2949 "Ping"); 2950 2951 if (message == NULL) 2952 return TRUE; 2953 2954 if (!dbus_connection_send (connection, message, &serial)) 2955 { 2956 dbus_message_unref (message); 2957 return TRUE; 2958 } 2959 2960 dbus_message_unref (message); 2961 message = NULL; 2962 2963 bus_test_run_everything (context); 2964 2965 /* Note: if this test is run in OOM mode, it will block when the bus 2966 * doesn't send a reply due to OOM. 2967 */ 2968 block_connection_until_message_from_bus (context, connection, "reply from running Ping"); 2969 2970 message = pop_message_waiting_for_memory (connection); 2971 if (message == NULL) 2972 { 2973 _dbus_warn ("Failed to pop message! Should have been reply from Ping message\n"); 2974 return FALSE; 2975 } 2976 2977 if (dbus_message_get_reply_serial (message) != serial) 2978 { 2979 _dbus_warn ("Wrong reply serial\n"); 2980 dbus_message_unref (message); 2981 return FALSE; 2982 } 2983 2984 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN) 2985 { 2986 _dbus_warn ("Unexpected message return during Ping\n"); 2987 dbus_message_unref (message); 2988 return FALSE; 2989 } 2990 2991 dbus_message_unref (message); 2992 message = NULL; 2993 2994 return TRUE; 2995 } 2996 2997 /* returns TRUE if the correct thing happens, 2998 * but the correct thing may include OOM errors. 2999 */ 3000 static dbus_bool_t 3001 check_existent_get_machine_id (BusContext *context, 3002 DBusConnection *connection) 3003 { 3004 DBusMessage *message; 3005 dbus_uint32_t serial; 3006 const char *machine_id; 3007 3008 message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME, 3009 "/org/freedesktop/TestSuite", 3010 "org.freedesktop.DBus.Peer", 3011 "GetMachineId"); 3012 3013 if (message == NULL) 3014 return TRUE; 3015 3016 if (!dbus_connection_send (connection, message, &serial)) 3017 { 3018 dbus_message_unref (message); 3019 return TRUE; 3020 } 3021 3022 dbus_message_unref (message); 3023 message = NULL; 3024 3025 bus_test_run_everything (context); 3026 3027 /* Note: if this test is run in OOM mode, it will block when the bus 3028 * doesn't send a reply due to OOM. 3029 */ 3030 block_connection_until_message_from_bus (context, connection, "reply from running GetMachineId"); 3031 3032 message = pop_message_waiting_for_memory (connection); 3033 if (message == NULL) 3034 { 3035 _dbus_warn ("Failed to pop message! Should have been reply from GetMachineId message\n"); 3036 return FALSE; 3037 } 3038 3039 if (dbus_message_get_reply_serial (message) != serial) 3040 { 3041 _dbus_warn ("Wrong reply serial\n"); 3042 dbus_message_unref (message); 3043 return FALSE; 3044 } 3045 3046 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN) 3047 { 3048 _dbus_warn ("Unexpected message return during GetMachineId\n"); 3049 dbus_message_unref (message); 3050 return FALSE; 3051 } 3052 3053 machine_id = NULL; 3054 if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &machine_id, DBUS_TYPE_INVALID)) 3055 { 3056 _dbus_warn ("Did not get a machine ID in reply to GetMachineId\n"); 3057 dbus_message_unref (message); 3058 return FALSE; 3059 } 3060 3061 if (machine_id == NULL || strlen (machine_id) != 32) 3062 { 3063 _dbus_warn ("Machine id looks bogus: '%s'\n", machine_id ? machine_id : "null"); 3064 dbus_message_unref (message); 3065 return FALSE; 3066 } 3067 3068 /* We can't check that the machine id is correct because during make check it is 3069 * just made up for each process separately 3070 */ 3071 3072 dbus_message_unref (message); 3073 message = NULL; 3074 3075 return TRUE; 3076 } 3077 3078 /* returns TRUE if the correct thing happens, 3079 * but the correct thing may include OOM errors. 3080 */ 3081 static dbus_bool_t 3082 check_existent_service_auto_start (BusContext *context, 3083 DBusConnection *connection) 3084 { 3085 DBusMessage *message; 3086 DBusMessage *base_service_message; 3087 dbus_uint32_t serial; 3088 dbus_bool_t retval; 3089 const char *base_service; 3090 const char *text; 3091 3092 base_service_message = NULL; 3093 3094 message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME, 3095 "/org/freedesktop/TestSuite", 3096 "org.freedesktop.TestSuite", 3097 "Echo"); 3098 3099 if (message == NULL) 3100 return TRUE; 3101 3102 text = TEST_ECHO_MESSAGE; 3103 if (!dbus_message_append_args (message, 3104 DBUS_TYPE_STRING, &text, 3105 DBUS_TYPE_INVALID)) 3106 { 3107 dbus_message_unref (message); 3108 return TRUE; 3109 } 3110 3111 if (!dbus_connection_send (connection, message, &serial)) 3112 { 3113 dbus_message_unref (message); 3114 return TRUE; 3115 } 3116 3117 dbus_message_unref (message); 3118 message = NULL; 3119 3120 bus_test_run_everything (context); 3121 3122 /* now wait for the message bus to hear back from the activated 3123 * service. 3124 */ 3125 block_connection_until_message_from_bus (context, connection, "reply to Echo on existent service"); 3126 bus_test_run_everything (context); 3127 3128 if (!dbus_connection_get_is_connected (connection)) 3129 { 3130 _dbus_verbose ("connection was disconnected\n"); 3131 return TRUE; 3132 } 3133 3134 retval = FALSE; 3135 3136 message = pop_message_waiting_for_memory (connection); 3137 if (message == NULL) 3138 { 3139 _dbus_warn ("Did not receive any messages after auto start %d on %p\n", 3140 serial, connection); 3141 goto out; 3142 } 3143 3144 verbose_message_received (connection, message); 3145 _dbus_verbose (" (after sending %s)\n", "auto start"); 3146 3147 /* we should get zero or two ServiceOwnerChanged signals */ 3148 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL) 3149 { 3150 GotServiceInfo message_kind; 3151 3152 if (!check_base_service_activated (context, connection, 3153 message, &base_service)) 3154 goto out; 3155 3156 base_service_message = message; 3157 message = NULL; 3158 3159 /* We may need to block here for the test service to exit or finish up */ 3160 block_connection_until_message_from_bus (context, connection, "service to exit"); 3161 3162 /* Should get a service creation notification for the activated 3163 * service name, or a service deletion on the base service name 3164 */ 3165 message = dbus_connection_borrow_message (connection); 3166 if (message == NULL) 3167 { 3168 _dbus_warn ("No message after auto activation " 3169 "(should be a service announcement)\n"); 3170 dbus_connection_return_message (connection, message); 3171 message = NULL; 3172 goto out; 3173 } 3174 3175 message_kind = check_got_service_info (message); 3176 3177 dbus_connection_return_message (connection, message); 3178 message = NULL; 3179 3180 switch (message_kind) 3181 { 3182 case GOT_SERVICE_CREATED: 3183 message = pop_message_waiting_for_memory (connection); 3184 if (message == NULL) 3185 { 3186 _dbus_warn ("Failed to pop message we just put back! " 3187 "should have been a NameOwnerChanged (creation)\n"); 3188 goto out; 3189 } 3190 3191 /* Check that ServiceOwnerChanged (creation) was correctly received */ 3192 if (!check_service_auto_activated (context, connection, EXISTENT_SERVICE_NAME, 3193 base_service, message)) 3194 goto out; 3195 3196 dbus_message_unref (message); 3197 message = NULL; 3198 3199 break; 3200 3201 case GOT_SERVICE_DELETED: 3202 { 3203 /* The service started up and got a base address, but then 3204 * failed to register under EXISTENT_SERVICE_NAME 3205 */ 3206 CheckServiceOwnerChangedData socd; 3207 3208 socd.expected_kind = SERVICE_DELETED; 3209 socd.expected_service_name = base_service; 3210 socd.failed = FALSE; 3211 socd.skip_connection = NULL; 3212 bus_test_clients_foreach (check_service_owner_changed_foreach, 3213 &socd); 3214 3215 if (socd.failed) 3216 goto out; 3217 3218 break; 3219 } 3220 3221 case GOT_ERROR: 3222 case GOT_SOMETHING_ELSE: 3223 _dbus_warn ("Unexpected message after auto activation\n"); 3224 goto out; 3225 } 3226 } 3227 3228 /* OK, now we've dealt with ServiceOwnerChanged signals, now should 3229 * come the method reply (or error) from the initial method call 3230 */ 3231 3232 /* Note: if this test is run in OOM mode, it will block when the bus 3233 * doesn't send a reply due to OOM. 3234 */ 3235 block_connection_until_message_from_bus (context, connection, "reply from echo message after auto-activation"); 3236 3237 message = pop_message_waiting_for_memory (connection); 3238 if (message == NULL) 3239 { 3240 _dbus_warn ("Failed to pop message! Should have been reply from echo message\n"); 3241 goto out; 3242 } 3243 3244 if (dbus_message_get_reply_serial (message) != serial) 3245 { 3246 _dbus_warn ("Wrong reply serial\n"); 3247 goto out; 3248 } 3249 3250 dbus_message_unref (message); 3251 message = NULL; 3252 3253 if (!check_existent_ping (context, connection)) 3254 goto out; 3255 3256 if (!check_existent_get_machine_id (context, connection)) 3257 goto out; 3258 3259 if (!check_existent_hello_from_self (context, connection)) 3260 goto out; 3261 3262 if (!check_send_exit_to_service (context, connection, 3263 EXISTENT_SERVICE_NAME, 3264 base_service)) 3265 goto out; 3266 3267 retval = TRUE; 3268 3269 out: 3270 if (message) 3271 dbus_message_unref (message); 3272 3273 if (base_service_message) 3274 dbus_message_unref (base_service_message); 3275 3276 return retval; 3277 } 3278 3279 #define SERVICE_FILE_MISSING_NAME "org.freedesktop.DBus.TestSuiteEchoServiceDotServiceFileDoesNotExist" 3280 3281 /* returns TRUE if the correct thing happens, 3282 * but the correct thing may include OOM errors. 3283 */ 3284 static dbus_bool_t 3285 check_launch_service_file_missing (BusContext *context, 3286 DBusConnection *connection) 3287 { 3288 DBusMessage *message; 3289 dbus_uint32_t serial; 3290 dbus_bool_t retval; 3291 3292 message = dbus_message_new_method_call (SERVICE_FILE_MISSING_NAME, 3293 "/org/freedesktop/TestSuite", 3294 "org.freedesktop.TestSuite", 3295 "Echo"); 3296 3297 if (message == NULL) 3298 return TRUE; 3299 3300 if (!dbus_connection_send (connection, message, &serial)) 3301 { 3302 dbus_message_unref (message); 3303 return TRUE; 3304 } 3305 3306 dbus_message_unref (message); 3307 message = NULL; 3308 3309 bus_test_run_everything (context); 3310 block_connection_until_message_from_bus (context, connection, "reply to service file missing should fail to auto-start"); 3311 bus_test_run_everything (context); 3312 3313 if (!dbus_connection_get_is_connected (connection)) 3314 { 3315 _dbus_verbose ("connection was disconnected\n"); 3316 return TRUE; 3317 } 3318 3319 retval = FALSE; 3320 3321 message = pop_message_waiting_for_memory (connection); 3322 if (message == NULL) 3323 { 3324 _dbus_warn ("Did not receive a reply to %s %d on %p\n", 3325 "Echo message (auto activation)", serial, connection); 3326 goto out; 3327 } 3328 3329 verbose_message_received (connection, message); 3330 3331 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR) 3332 { 3333 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS)) 3334 { 3335 _dbus_warn ("Message has wrong sender %s\n", 3336 dbus_message_get_sender (message) ? 3337 dbus_message_get_sender (message) : "(none)"); 3338 goto out; 3339 } 3340 3341 if (dbus_message_is_error (message, 3342 DBUS_ERROR_NO_MEMORY)) 3343 { 3344 ; /* good, this is a valid response */ 3345 } 3346 else if (dbus_message_is_error (message, 3347 DBUS_ERROR_SERVICE_UNKNOWN)) 3348 { 3349 _dbus_verbose("got service unknown\n"); 3350 ; /* good, this is expected (only valid when using launch helper) */ 3351 } 3352 else 3353 { 3354 warn_unexpected (connection, message, "not this error"); 3355 3356 goto out; 3357 } 3358 } 3359 else 3360 { 3361 _dbus_warn ("Did not expect to successfully auto-start missing service\n"); 3362 goto out; 3363 } 3364 3365 retval = TRUE; 3366 3367 out: 3368 if (message) 3369 dbus_message_unref (message); 3370 3371 return retval; 3372 } 3373 3374 #define SERVICE_USER_MISSING_NAME "org.freedesktop.DBus.TestSuiteNoUser" 3375 3376 /* returns TRUE if the correct thing happens, 3377 * but the correct thing may include OOM errors. 3378 */ 3379 static dbus_bool_t 3380 check_launch_service_user_missing (BusContext *context, 3381 DBusConnection *connection) 3382 { 3383 DBusMessage *message; 3384 dbus_uint32_t serial; 3385 dbus_bool_t retval; 3386 3387 message = dbus_message_new_method_call (SERVICE_USER_MISSING_NAME, 3388 "/org/freedesktop/TestSuite", 3389 "org.freedesktop.TestSuite", 3390 "Echo"); 3391 3392 if (message == NULL) 3393 return TRUE; 3394 3395 if (!dbus_connection_send (connection, message, &serial)) 3396 { 3397 dbus_message_unref (message); 3398 return TRUE; 3399 } 3400 3401 dbus_message_unref (message); 3402 message = NULL; 3403 3404 bus_test_run_everything (context); 3405 block_connection_until_message_from_bus (context, connection, 3406 "reply to service which should fail to auto-start (missing User)"); 3407 bus_test_run_everything (context); 3408 3409 if (!dbus_connection_get_is_connected (connection)) 3410 { 3411 _dbus_warn ("connection was disconnected\n"); 3412 return TRUE; 3413 } 3414 3415 retval = FALSE; 3416 3417 message = pop_message_waiting_for_memory (connection); 3418 if (message == NULL) 3419 { 3420 _dbus_warn ("Did not receive a reply to %s %d on %p\n", 3421 "Echo message (auto activation)", serial, connection); 3422 goto out; 3423 } 3424 3425 verbose_message_received (connection, message); 3426 3427 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR) 3428 { 3429 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS)) 3430 { 3431 _dbus_warn ("Message has wrong sender %s\n", 3432 dbus_message_get_sender (message) ? 3433 dbus_message_get_sender (message) : "(none)"); 3434 goto out; 3435 } 3436 3437 if (dbus_message_is_error (message, 3438 DBUS_ERROR_NO_MEMORY)) 3439 { 3440 ; /* good, this is a valid response */ 3441 } 3442 else if (dbus_message_is_error (message, 3443 DBUS_ERROR_SPAWN_FILE_INVALID)) 3444 { 3445 _dbus_verbose("got service file invalid\n"); 3446 ; /* good, this is expected (only valid when using launch helper) */ 3447 } 3448 else 3449 { 3450 warn_unexpected (connection, message, "not this error"); 3451 3452 goto out; 3453 } 3454 } 3455 else 3456 { 3457 _dbus_warn ("Did not expect to successfully auto-start missing service\n"); 3458 goto out; 3459 } 3460 3461 retval = TRUE; 3462 3463 out: 3464 if (message) 3465 dbus_message_unref (message); 3466 3467 return retval; 3468 } 3469 3470 #define SERVICE_EXEC_MISSING_NAME "org.freedesktop.DBus.TestSuiteNoExec" 3471 3472 /* returns TRUE if the correct thing happens, 3473 * but the correct thing may include OOM errors. 3474 */ 3475 static dbus_bool_t 3476 check_launch_service_exec_missing (BusContext *context, 3477 DBusConnection *connection) 3478 { 3479 DBusMessage *message; 3480 dbus_uint32_t serial; 3481 dbus_bool_t retval; 3482 3483 message = dbus_message_new_method_call (SERVICE_EXEC_MISSING_NAME, 3484 "/org/freedesktop/TestSuite", 3485 "org.freedesktop.TestSuite", 3486 "Echo"); 3487 3488 if (message == NULL) 3489 return TRUE; 3490 3491 if (!dbus_connection_send (connection, message, &serial)) 3492 { 3493 dbus_message_unref (message); 3494 return TRUE; 3495 } 3496 3497 dbus_message_unref (message); 3498 message = NULL; 3499 3500 bus_test_run_everything (context); 3501 block_connection_until_message_from_bus (context, connection, 3502 "reply to service which should fail to auto-start (missing Exec)"); 3503 bus_test_run_everything (context); 3504 3505 if (!dbus_connection_get_is_connected (connection)) 3506 { 3507 _dbus_warn ("connection was disconnected\n"); 3508 return TRUE; 3509 } 3510 3511 retval = FALSE; 3512 3513 message = pop_message_waiting_for_memory (connection); 3514 if (message == NULL) 3515 { 3516 _dbus_warn ("Did not receive a reply to %s %d on %p\n", 3517 "Echo message (auto activation)", serial, connection); 3518 goto out; 3519 } 3520 3521 verbose_message_received (connection, message); 3522 3523 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR) 3524 { 3525 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS)) 3526 { 3527 _dbus_warn ("Message has wrong sender %s\n", 3528 dbus_message_get_sender (message) ? 3529 dbus_message_get_sender (message) : "(none)"); 3530 goto out; 3531 } 3532 3533 if (dbus_message_is_error (message, 3534 DBUS_ERROR_NO_MEMORY)) 3535 { 3536 ; /* good, this is a valid response */ 3537 } 3538 else if (dbus_message_is_error (message, 3539 DBUS_ERROR_SERVICE_UNKNOWN)) 3540 { 3541 _dbus_verbose("could not activate as invalid service file was not added\n"); 3542 ; /* good, this is expected as we shouldn't have been added to 3543 * the activation list with a missing Exec key */ 3544 } 3545 else if (dbus_message_is_error (message, 3546 DBUS_ERROR_SPAWN_FILE_INVALID)) 3547 { 3548 _dbus_verbose("got service file invalid\n"); 3549 ; /* good, this is allowed, and is the message passed back from the 3550 * launch helper */ 3551 } 3552 else 3553 { 3554 warn_unexpected (connection, message, "not this error"); 3555 3556 goto out; 3557 } 3558 } 3559 else 3560 { 3561 _dbus_warn ("Did not expect to successfully auto-start missing service\n"); 3562 goto out; 3563 } 3564 3565 retval = TRUE; 3566 3567 out: 3568 if (message) 3569 dbus_message_unref (message); 3570 3571 return retval; 3572 } 3573 3574 #define SERVICE_SERVICE_MISSING_NAME "org.freedesktop.DBus.TestSuiteNoService" 3575 3576 /* returns TRUE if the correct thing happens, 3577 * but the correct thing may include OOM errors. 3578 */ 3579 static dbus_bool_t 3580 check_launch_service_service_missing (BusContext *context, 3581 DBusConnection *connection) 3582 { 3583 DBusMessage *message; 3584 dbus_uint32_t serial; 3585 dbus_bool_t retval; 3586 3587 message = dbus_message_new_method_call (SERVICE_SERVICE_MISSING_NAME, 3588 "/org/freedesktop/TestSuite", 3589 "org.freedesktop.TestSuite", 3590 "Echo"); 3591 3592 if (message == NULL) 3593 return TRUE; 3594 3595 if (!dbus_connection_send (connection, message, &serial)) 3596 { 3597 dbus_message_unref (message); 3598 return TRUE; 3599 } 3600 3601 dbus_message_unref (message); 3602 message = NULL; 3603 3604 bus_test_run_everything (context); 3605 block_connection_until_message_from_bus (context, connection, 3606 "reply to service which should fail to auto-start (missing Service)"); 3607 bus_test_run_everything (context); 3608 3609 if (!dbus_connection_get_is_connected (connection)) 3610 { 3611 _dbus_warn ("connection was disconnected\n"); 3612 return TRUE; 3613 } 3614 3615 retval = FALSE; 3616 3617 message = pop_message_waiting_for_memory (connection); 3618 if (message == NULL) 3619 { 3620 _dbus_warn ("Did not receive a reply to %s %d on %p\n", 3621 "Echo message (auto activation)", serial, connection); 3622 goto out; 3623 } 3624 3625 verbose_message_received (connection, message); 3626 3627 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR) 3628 { 3629 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS)) 3630 { 3631 _dbus_warn ("Message has wrong sender %s\n", 3632 dbus_message_get_sender (message) ? 3633 dbus_message_get_sender (message) : "(none)"); 3634 goto out; 3635 } 3636 3637 if (dbus_message_is_error (message, 3638 DBUS_ERROR_NO_MEMORY)) 3639 { 3640 ; /* good, this is a valid response */ 3641 } 3642 else if (dbus_message_is_error (message, 3643 DBUS_ERROR_SERVICE_UNKNOWN)) 3644 { 3645 _dbus_verbose("could not activate as invalid service file was not added\n"); 3646 ; /* good, this is expected as we shouldn't have been added to 3647 * the activation list with a missing Exec key */ 3648 } 3649 else if (dbus_message_is_error (message, 3650 DBUS_ERROR_SPAWN_FILE_INVALID)) 3651 { 3652 _dbus_verbose("got service file invalid\n"); 3653 ; /* good, this is allowed, and is the message passed back from the 3654 * launch helper */ 3655 } 3656 else 3657 { 3658 warn_unexpected (connection, message, "not this error"); 3659 3660 goto out; 3661 } 3662 } 3663 else 3664 { 3665 _dbus_warn ("Did not expect to successfully auto-start missing service\n"); 3666 goto out; 3667 } 3668 3669 retval = TRUE; 3670 3671 out: 3672 if (message) 3673 dbus_message_unref (message); 3674 3675 return retval; 3676 } 3677 3678 #define SHELL_FAIL_SERVICE_NAME "org.freedesktop.DBus.TestSuiteShellEchoServiceFail" 3679 3680 /* returns TRUE if the correct thing happens, 3681 * but the correct thing may include OOM errors. 3682 */ 3683 static dbus_bool_t 3684 check_shell_fail_service_auto_start (BusContext *context, 3685 DBusConnection *connection) 3686 { 3687 DBusMessage *message; 3688 dbus_uint32_t serial; 3689 dbus_bool_t retval; 3690 3691 message = dbus_message_new_method_call (SHELL_FAIL_SERVICE_NAME, 3692 "/org/freedesktop/TestSuite", 3693 "org.freedesktop.TestSuite", 3694 "Echo"); 3695 3696 if (message == NULL) 3697 return TRUE; 3698 3699 if (!dbus_connection_send (connection, message, &serial)) 3700 { 3701 dbus_message_unref (message); 3702 return TRUE; 3703 } 3704 3705 dbus_message_unref (message); 3706 message = NULL; 3707 3708 bus_test_run_everything (context); 3709 block_connection_until_message_from_bus (context, connection, "reply to shell Echo on service which should fail to auto-start"); 3710 bus_test_run_everything (context); 3711 3712 if (!dbus_connection_get_is_connected (connection)) 3713 { 3714 _dbus_verbose ("connection was disconnected\n"); 3715 return TRUE; 3716 } 3717 3718 retval = FALSE; 3719 3720 message = pop_message_waiting_for_memory (connection); 3721 if (message == NULL) 3722 { 3723 _dbus_warn ("Did not receive a reply to %s %d on %p\n", 3724 "Echo message (auto activation)", serial, connection); 3725 goto out; 3726 } 3727 3728 verbose_message_received (connection, message); 3729 3730 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR) 3731 { 3732 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS)) 3733 { 3734 _dbus_warn ("Message has wrong sender %s\n", 3735 dbus_message_get_sender (message) ? 3736 dbus_message_get_sender (message) : "(none)"); 3737 goto out; 3738 } 3739 3740 if (dbus_message_is_error (message, 3741 DBUS_ERROR_NO_MEMORY)) 3742 { 3743 ; /* good, this is a valid response */ 3744 } 3745 else if (dbus_message_is_error (message, 3746 DBUS_ERROR_INVALID_ARGS)) 3747 { 3748 _dbus_verbose("got invalid args\n"); 3749 ; /* good, this is expected also */ 3750 } 3751 else 3752 { 3753 warn_unexpected (connection, message, "not this error"); 3754 3755 goto out; 3756 } 3757 } 3758 else 3759 { 3760 _dbus_warn ("Did not expect to successfully auto-start shell fail service\n"); 3761 goto out; 3762 } 3763 3764 retval = TRUE; 3765 3766 out: 3767 if (message) 3768 dbus_message_unref (message); 3769 3770 return retval; 3771 } 3772 3773 #define SHELL_SUCCESS_SERVICE_NAME "org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess" 3774 3775 /* returns TRUE if the correct thing happens, 3776 * but the correct thing may include OOM errors. 3777 */ 3778 static dbus_bool_t 3779 check_shell_service_success_auto_start (BusContext *context, 3780 DBusConnection *connection) 3781 { 3782 DBusMessage *message; 3783 DBusMessage *base_service_message; 3784 dbus_uint32_t serial; 3785 dbus_bool_t retval; 3786 const char *base_service; 3787 const char *argv[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL}; 3788 3789 base_service_message = NULL; 3790 3791 message = dbus_message_new_method_call (SHELL_SUCCESS_SERVICE_NAME, 3792 "/org/freedesktop/TestSuite", 3793 "org.freedesktop.TestSuite", 3794 "Echo"); 3795 3796 if (message == NULL) 3797 return TRUE; 3798 3799 if (!dbus_connection_send (connection, message, &serial)) 3800 { 3801 dbus_message_unref (message); 3802 return TRUE; 3803 } 3804 3805 dbus_message_unref (message); 3806 message = NULL; 3807 3808 bus_test_run_everything (context); 3809 3810 /* now wait for the message bus to hear back from the activated 3811 * service. 3812 */ 3813 block_connection_until_message_from_bus (context, connection, "reply to Echo on shell success service"); 3814 bus_test_run_everything (context); 3815 3816 if (!dbus_connection_get_is_connected (connection)) 3817 { 3818 _dbus_verbose ("connection was disconnected\n"); 3819 return TRUE; 3820 } 3821 3822 retval = FALSE; 3823 3824 message = pop_message_waiting_for_memory (connection); 3825 if (message == NULL) 3826 { 3827 _dbus_warn ("Did not receive any messages after auto start %d on %p\n", 3828 serial, connection); 3829 goto out; 3830 } 3831 3832 verbose_message_received (connection, message); 3833 _dbus_verbose (" (after sending %s)\n", "auto start"); 3834 3835 /* we should get zero or two ServiceOwnerChanged signals */ 3836 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL) 3837 { 3838 GotServiceInfo message_kind; 3839 3840 if (!check_base_service_activated (context, connection, 3841 message, &base_service)) 3842 goto out; 3843 3844 base_service_message = message; 3845 message = NULL; 3846 3847 /* We may need to block here for the test service to exit or finish up */ 3848 block_connection_until_message_from_bus (context, connection, "service to exit"); 3849 3850 /* Should get a service creation notification for the activated 3851 * service name, or a service deletion on the base service name 3852 */ 3853 message = dbus_connection_borrow_message (connection); 3854 if (message == NULL) 3855 { 3856 _dbus_warn ("No message after auto activation " 3857 "(should be a service announcement)\n"); 3858 dbus_connection_return_message (connection, message); 3859 message = NULL; 3860 goto out; 3861 } 3862 3863 message_kind = check_got_service_info (message); 3864 3865 dbus_connection_return_message (connection, message); 3866 message = NULL; 3867 3868 switch (message_kind) 3869 { 3870 case GOT_SERVICE_CREATED: 3871 message = pop_message_waiting_for_memory (connection); 3872 if (message == NULL) 3873 { 3874 _dbus_warn ("Failed to pop message we just put back! " 3875 "should have been a NameOwnerChanged (creation)\n"); 3876 goto out; 3877 } 3878 3879 /* Check that ServiceOwnerChanged (creation) was correctly received */ 3880 if (!check_service_auto_activated (context, connection, SHELL_SUCCESS_SERVICE_NAME, 3881 base_service, message)) 3882 goto out; 3883 3884 dbus_message_unref (message); 3885 message = NULL; 3886 3887 break; 3888 3889 case GOT_SERVICE_DELETED: 3890 { 3891 /* The service started up and got a base address, but then 3892 * failed to register under SHELL_SUCCESS_SERVICE_NAME 3893 */ 3894 CheckServiceOwnerChangedData socd; 3895 3896 socd.expected_kind = SERVICE_DELETED; 3897 socd.expected_service_name = base_service; 3898 socd.failed = FALSE; 3899 socd.skip_connection = NULL; 3900 bus_test_clients_foreach (check_service_owner_changed_foreach, 3901 &socd); 3902 3903 if (socd.failed) 3904 goto out; 3905 3906 break; 3907 } 3908 3909 case GOT_ERROR: 3910 case GOT_SOMETHING_ELSE: 3911 _dbus_warn ("Unexpected message after auto activation\n"); 3912 goto out; 3913 } 3914 } 3915 3916 /* OK, now we've dealt with ServiceOwnerChanged signals, now should 3917 * come the method reply (or error) from the initial method call 3918 */ 3919 3920 /* Note: if this test is run in OOM mode, it will block when the bus 3921 * doesn't send a reply due to OOM. 3922 */ 3923 block_connection_until_message_from_bus (context, connection, "reply from echo message after auto-activation"); 3924 3925 message = pop_message_waiting_for_memory (connection); 3926 if (message == NULL) 3927 { 3928 _dbus_warn ("Failed to pop message! Should have been reply from echo message\n"); 3929 goto out; 3930 } 3931 3932 if (dbus_message_get_reply_serial (message) != serial) 3933 { 3934 _dbus_warn ("Wrong reply serial\n"); 3935 goto out; 3936 } 3937 3938 if (!dbus_message_get_args (message, NULL, 3939 DBUS_TYPE_STRING, &argv[0], 3940 DBUS_TYPE_STRING, &argv[1], 3941 DBUS_TYPE_STRING, &argv[2], 3942 DBUS_TYPE_STRING, &argv[3], 3943 DBUS_TYPE_STRING, &argv[4], 3944 DBUS_TYPE_STRING, &argv[5], 3945 DBUS_TYPE_STRING, &argv[6], 3946 DBUS_TYPE_INVALID)) 3947 { 3948 _dbus_warn ("Error getting arguments from return\n"); 3949 goto out; 3950 } 3951 3952 /* don't worry about arg[0] as it may be different 3953 depending on the path to the tests 3954 */ 3955 if (strcmp("-test", argv[1]) != 0) 3956 { 3957 _dbus_warn ("Unexpected argv[1] in shell success service test (expected: %s, got: %s)\n", 3958 "-test", argv[1]); 3959 goto out; 3960 } 3961 3962 if (strcmp("that", argv[2]) != 0) 3963 { 3964 _dbus_warn ("Unexpected argv[2] in shell success service test (expected: %s, got: %s)\n", 3965 "that", argv[2]); 3966 goto out; 3967 } 3968 3969 if (strcmp("we get", argv[3]) != 0) 3970 { 3971 _dbus_warn ("Unexpected argv[3] in shell success service test (expected: %s, got: %s)\n", 3972 "we get", argv[3]); 3973 goto out; 3974 } 3975 3976 if (strcmp("back", argv[4]) != 0) 3977 { 3978 _dbus_warn ("Unexpected argv[4] in shell success service test (expected: %s, got: %s)\n", 3979 "back", argv[4]); 3980 goto out; 3981 } 3982 3983 if (strcmp("--what", argv[5]) != 0) 3984 { 3985 _dbus_warn ("Unexpected argv[5] in shell success service test (expected: %s, got: %s)\n", 3986 "--what", argv[5]); 3987 goto out; 3988 } 3989 3990 if (strcmp("we put in", argv[6]) != 0) 3991 { 3992 _dbus_warn ("Unexpected argv[6] in shell success service test (expected: %s, got: %s)\n", 3993 "we put in", argv[6]); 3994 goto out; 3995 } 3996 3997 dbus_message_unref (message); 3998 message = NULL; 3999 4000 if (!check_send_exit_to_service (context, connection, 4001 SHELL_SUCCESS_SERVICE_NAME, 4002 base_service)) 4003 goto out; 4004 4005 retval = TRUE; 4006 4007 out: 4008 if (message) 4009 dbus_message_unref (message); 4010 4011 if (base_service_message) 4012 dbus_message_unref (base_service_message); 4013 4014 return retval; 4015 } 4016 4017 typedef struct 4018 { 4019 Check1Func func; 4020 BusContext *context; 4021 } Check1Data; 4022 4023 static dbus_bool_t 4024 check_oom_check1_func (void *data) 4025 { 4026 Check1Data *d = data; 4027 4028 if (! (* d->func) (d->context)) 4029 return FALSE; 4030 4031 if (!check_no_leftovers (d->context)) 4032 { 4033 _dbus_warn ("Messages were left over, should be covered by test suite\n"); 4034 return FALSE; 4035 } 4036 4037 return TRUE; 4038 } 4039 4040 static void 4041 check1_try_iterations (BusContext *context, 4042 const char *description, 4043 Check1Func func) 4044 { 4045 Check1Data d; 4046 4047 d.func = func; 4048 d.context = context; 4049 4050 if (!_dbus_test_oom_handling (description, check_oom_check1_func, 4051 &d)) 4052 _dbus_assert_not_reached ("test failed"); 4053 } 4054 4055 static dbus_bool_t 4056 check_get_services (BusContext *context, 4057 DBusConnection *connection, 4058 const char *method, 4059 char ***services, 4060 int *len) 4061 { 4062 DBusMessage *message; 4063 dbus_uint32_t serial; 4064 dbus_bool_t retval; 4065 DBusError error; 4066 char **srvs; 4067 int l; 4068 4069 retval = FALSE; 4070 dbus_error_init (&error); 4071 message = NULL; 4072 4073 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS, 4074 DBUS_PATH_DBUS, 4075 DBUS_INTERFACE_DBUS, 4076 method); 4077 4078 if (message == NULL) 4079 return TRUE; 4080 4081 if (!dbus_connection_send (connection, message, &serial)) 4082 { 4083 dbus_message_unref (message); 4084 return TRUE; 4085 } 4086 4087 /* send our message */ 4088 bus_test_run_clients_loop (SEND_PENDING (connection)); 4089 4090 dbus_message_unref (message); 4091 message = NULL; 4092 4093 dbus_connection_ref (connection); /* because we may get disconnected */ 4094 block_connection_until_message_from_bus (context, connection, "reply to ListActivatableNames/ListNames"); 4095 4096 if (!dbus_connection_get_is_connected (connection)) 4097 { 4098 _dbus_verbose ("connection was disconnected\n"); 4099 4100 dbus_connection_unref (connection); 4101 4102 return TRUE; 4103 } 4104 4105 dbus_connection_unref (connection); 4106 4107 message = pop_message_waiting_for_memory (connection); 4108 if (message == NULL) 4109 { 4110 _dbus_warn ("Did not receive a reply to %s %d on %p\n", 4111 method, serial, connection); 4112 goto out; 4113 } 4114 4115 verbose_message_received (connection, message); 4116 4117 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR) 4118 { 4119 if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY)) 4120 { 4121 ; /* good, this is a valid response */ 4122 } 4123 else 4124 { 4125 warn_unexpected (connection, message, "not this error"); 4126 4127 goto out; 4128 } 4129 } 4130 else 4131 { 4132 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN) 4133 { 4134 ; /* good, expected */ 4135 } 4136 else 4137 { 4138 warn_unexpected (connection, message, 4139 "method_return for ListActivatableNames/ListNames"); 4140 4141 goto out; 4142 } 4143 4144 retry_get_property: 4145 4146 if (!dbus_message_get_args (message, &error, 4147 DBUS_TYPE_ARRAY, 4148 DBUS_TYPE_STRING, 4149 &srvs, &l, 4150 DBUS_TYPE_INVALID)) 4151 { 4152 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) 4153 { 4154 _dbus_verbose ("no memory to list services by %s\n", method); 4155 dbus_error_free (&error); 4156 _dbus_wait_for_memory (); 4157 goto retry_get_property; 4158 } 4159 else 4160 { 4161 _dbus_assert (dbus_error_is_set (&error)); 4162 _dbus_warn ("Did not get the expected DBUS_TYPE_ARRAY from %s\n", method); 4163 goto out; 4164 } 4165 } else { 4166 *services = srvs; 4167 *len = l; 4168 } 4169 } 4170 4171 if (!check_no_leftovers (context)) 4172 goto out; 4173 4174 retval = TRUE; 4175 4176 out: 4177 dbus_error_free (&error); 4178 4179 if (message) 4180 dbus_message_unref (message); 4181 4182 return retval; 4183 } 4184 4185 /* returns TRUE if the correct thing happens, 4186 * but the correct thing may include OOM errors. 4187 */ 4188 static dbus_bool_t 4189 check_list_services (BusContext *context, 4190 DBusConnection *connection) 4191 { 4192 DBusMessage *message; 4193 DBusMessage *base_service_message; 4194 const char *base_service; 4195 dbus_uint32_t serial; 4196 dbus_bool_t retval; 4197 const char *existent = EXISTENT_SERVICE_NAME; 4198 dbus_uint32_t flags; 4199 char **services; 4200 int len; 4201 4202 _dbus_verbose ("check_list_services for %p\n", connection); 4203 4204 if (!check_get_services (context, connection, "ListActivatableNames", &services, &len)) 4205 { 4206 return TRUE; 4207 } 4208 4209 if (!_dbus_string_array_contains ((const char **)services, existent)) 4210 { 4211 _dbus_warn ("Did not get the expected %s from ListActivatableNames\n", existent); 4212 dbus_free_string_array (services); 4213 return FALSE; 4214 } 4215 4216 dbus_free_string_array (services); 4217 4218 base_service_message = NULL; 4219 4220 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS, 4221 DBUS_PATH_DBUS, 4222 DBUS_INTERFACE_DBUS, 4223 "StartServiceByName"); 4224 4225 if (message == NULL) 4226 return TRUE; 4227 4228 dbus_message_set_auto_start (message, FALSE); 4229 4230 flags = 0; 4231 if (!dbus_message_append_args (message, 4232 DBUS_TYPE_STRING, &existent, 4233 DBUS_TYPE_UINT32, &flags, 4234 DBUS_TYPE_INVALID)) 4235 { 4236 dbus_message_unref (message); 4237 return TRUE; 4238 } 4239 4240 if (!dbus_connection_send (connection, message, &serial)) 4241 { 4242 dbus_message_unref (message); 4243 return TRUE; 4244 } 4245 4246 dbus_message_unref (message); 4247 message = NULL; 4248 4249 bus_test_run_everything (context); 4250 4251 /* now wait for the message bus to hear back from the activated 4252 * service. 4253 */ 4254 block_connection_until_message_from_bus (context, connection, "activated service to connect"); 4255 4256 bus_test_run_everything (context); 4257 4258 if (!dbus_connection_get_is_connected (connection)) 4259 { 4260 _dbus_verbose ("connection was disconnected\n"); 4261 return TRUE; 4262 } 4263 4264 retval = FALSE; 4265 4266 message = pop_message_waiting_for_memory (connection); 4267 if (message == NULL) 4268 { 4269 _dbus_warn ("Did not receive any messages after %s %d on %p\n", 4270 "StartServiceByName", serial, connection); 4271 goto out; 4272 } 4273 4274 verbose_message_received (connection, message); 4275 _dbus_verbose (" (after sending %s)\n", "StartServiceByName"); 4276 4277 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR) 4278 { 4279 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS)) 4280 { 4281 _dbus_warn ("Message has wrong sender %s\n", 4282 dbus_message_get_sender (message) ? 4283 dbus_message_get_sender (message) : "(none)"); 4284 goto out; 4285 } 4286 4287 if (dbus_message_is_error (message, 4288 DBUS_ERROR_NO_MEMORY)) 4289 { 4290 ; /* good, this is a valid response */ 4291 } 4292 else if (dbus_message_is_error (message, 4293 DBUS_ERROR_SPAWN_CHILD_EXITED) || 4294 dbus_message_is_error (message, 4295 DBUS_ERROR_SPAWN_CHILD_SIGNALED) || 4296 dbus_message_is_error (message, 4297 DBUS_ERROR_SPAWN_EXEC_FAILED)) 4298 { 4299 ; /* good, this is expected also */ 4300 } 4301 else 4302 { 4303 _dbus_warn ("Did not expect error %s\n", 4304 dbus_message_get_error_name (message)); 4305 goto out; 4306 } 4307 } 4308 else 4309 { 4310 GotServiceInfo message_kind; 4311 4312 if (!check_base_service_activated (context, connection, 4313 message, &base_service)) 4314 goto out; 4315 4316 base_service_message = message; 4317 message = NULL; 4318 4319 /* We may need to block here for the test service to exit or finish up */ 4320 block_connection_until_message_from_bus (context, connection, "test service to exit or finish up"); 4321 4322 message = dbus_connection_borrow_message (connection); 4323 if (message == NULL) 4324 { 4325 _dbus_warn ("Did not receive any messages after base service creation notification\n"); 4326 goto out; 4327 } 4328 4329 message_kind = check_got_service_info (message); 4330 4331 dbus_connection_return_message (connection, message); 4332 message = NULL; 4333 4334 switch (message_kind) 4335 { 4336 case GOT_SOMETHING_ELSE: 4337 case GOT_ERROR: 4338 case GOT_SERVICE_DELETED: 4339 _dbus_warn ("Unexpected message after ActivateService " 4340 "(should be an error or a service announcement)\n"); 4341 goto out; 4342 4343 case GOT_SERVICE_CREATED: 4344 message = pop_message_waiting_for_memory (connection); 4345 if (message == NULL) 4346 { 4347 _dbus_warn ("Failed to pop message we just put back! " 4348 "should have been a NameOwnerChanged (creation)\n"); 4349 goto out; 4350 } 4351 4352 if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME, 4353 base_service, message)) 4354 goto out; 4355 4356 dbus_message_unref (message); 4357 message = NULL; 4358 4359 if (!check_no_leftovers (context)) 4360 { 4361 _dbus_warn ("Messages were left over after successful activation\n"); 4362 goto out; 4363 } 4364 4365 break; 4366 } 4367 } 4368 4369 if (!check_get_services (context, connection, "ListNames", &services, &len)) 4370 { 4371 return TRUE; 4372 } 4373 4374 if (!_dbus_string_array_contains ((const char **)services, existent)) 4375 { 4376 _dbus_warn ("Did not get the expected %s from ListNames\n", existent); 4377 goto out; 4378 } 4379 4380 dbus_free_string_array (services); 4381 4382 if (!check_send_exit_to_service (context, connection, 4383 EXISTENT_SERVICE_NAME, base_service)) 4384 goto out; 4385 4386 retval = TRUE; 4387 4388 out: 4389 if (message) 4390 dbus_message_unref (message); 4391 4392 if (base_service_message) 4393 dbus_message_unref (base_service_message); 4394 4395 return retval; 4396 } 4397 4398 typedef struct 4399 { 4400 Check2Func func; 4401 BusContext *context; 4402 DBusConnection *connection; 4403 } Check2Data; 4404 4405 static dbus_bool_t 4406 check_oom_check2_func (void *data) 4407 { 4408 Check2Data *d = data; 4409 4410 if (! (* d->func) (d->context, d->connection)) 4411 return FALSE; 4412 4413 if (!check_no_leftovers (d->context)) 4414 { 4415 _dbus_warn ("Messages were left over, should be covered by test suite\n"); 4416 return FALSE; 4417 } 4418 4419 return TRUE; 4420 } 4421 4422 static void 4423 check2_try_iterations (BusContext *context, 4424 DBusConnection *connection, 4425 const char *description, 4426 Check2Func func) 4427 { 4428 Check2Data d; 4429 4430 d.func = func; 4431 d.context = context; 4432 d.connection = connection; 4433 4434 if (!_dbus_test_oom_handling (description, check_oom_check2_func, 4435 &d)) 4436 { 4437 _dbus_warn ("%s failed during oom\n", description); 4438 _dbus_assert_not_reached ("test failed"); 4439 } 4440 } 4441 4442 static dbus_bool_t 4443 setenv_TEST_LAUNCH_HELPER_CONFIG(const DBusString *test_data_dir, 4444 const char *filename) 4445 { 4446 DBusString full; 4447 DBusString file; 4448 4449 if (!_dbus_string_init (&full)) 4450 return FALSE; 4451 4452 if (!_dbus_string_copy (test_data_dir, 0, &full, 0)) 4453 { 4454 _dbus_string_free (&full); 4455 return FALSE; 4456 } 4457 4458 _dbus_string_init_const (&file, filename); 4459 4460 if (!_dbus_concat_dir_and_file (&full, &file)) 4461 { 4462 _dbus_string_free (&full); 4463 return FALSE; 4464 } 4465 4466 _dbus_verbose ("Setting TEST_LAUNCH_HELPER_CONFIG to '%s'\n", 4467 _dbus_string_get_const_data (&full)); 4468 4469 _dbus_setenv ("TEST_LAUNCH_HELPER_CONFIG", _dbus_string_get_const_data (&full)); 4470 4471 _dbus_string_free (&full); 4472 4473 return TRUE; 4474 } 4475 4476 static dbus_bool_t 4477 bus_dispatch_test_conf (const DBusString *test_data_dir, 4478 const char *filename, 4479 dbus_bool_t use_launcher) 4480 { 4481 BusContext *context; 4482 DBusConnection *foo; 4483 DBusConnection *bar; 4484 DBusConnection *baz; 4485 DBusError error; 4486 4487 /* save the config name for the activation helper */ 4488 if (!setenv_TEST_LAUNCH_HELPER_CONFIG (test_data_dir, filename)) 4489 _dbus_assert_not_reached ("no memory setting TEST_LAUNCH_HELPER_CONFIG"); 4490 4491 dbus_error_init (&error); 4492 4493 context = bus_context_new_test (test_data_dir, filename); 4494 if (context == NULL) 4495 return FALSE; 4496 4497 foo = dbus_connection_open_private (TEST_DEBUG_PIPE, &error); 4498 if (foo == NULL) 4499 _dbus_assert_not_reached ("could not alloc connection"); 4500 4501 if (!bus_setup_debug_client (foo)) 4502 _dbus_assert_not_reached ("could not set up connection"); 4503 4504 spin_connection_until_authenticated (context, foo); 4505 4506 if (!check_hello_message (context, foo)) 4507 _dbus_assert_not_reached ("hello message failed"); 4508 4509 if (!check_double_hello_message (context, foo)) 4510 _dbus_assert_not_reached ("double hello message failed"); 4511 4512 if (!check_add_match_all (context, foo)) 4513 _dbus_assert_not_reached ("AddMatch message failed"); 4514 4515 bar = dbus_connection_open_private (TEST_DEBUG_PIPE, &error); 4516 if (bar == NULL) 4517 _dbus_assert_not_reached ("could not alloc connection"); 4518 4519 if (!bus_setup_debug_client (bar)) 4520 _dbus_assert_not_reached ("could not set up connection"); 4521 4522 spin_connection_until_authenticated (context, bar); 4523 4524 if (!check_hello_message (context, bar)) 4525 _dbus_assert_not_reached ("hello message failed"); 4526 4527 if (!check_add_match_all (context, bar)) 4528 _dbus_assert_not_reached ("AddMatch message failed"); 4529 4530 baz = dbus_connection_open_private (TEST_DEBUG_PIPE, &error); 4531 if (baz == NULL) 4532 _dbus_assert_not_reached ("could not alloc connection"); 4533 4534 if (!bus_setup_debug_client (baz)) 4535 _dbus_assert_not_reached ("could not set up connection"); 4536 4537 spin_connection_until_authenticated (context, baz); 4538 4539 if (!check_hello_message (context, baz)) 4540 _dbus_assert_not_reached ("hello message failed"); 4541 4542 if (!check_add_match_all (context, baz)) 4543 _dbus_assert_not_reached ("AddMatch message failed"); 4544 4545 #ifdef DBUS_WIN_FIXME 4546 _dbus_warn("TODO: testing of GetConnectionUnixUser message skipped for now\n"); 4547 _dbus_warn("TODO: testing of GetConnectionUnixProcessID message skipped for now\n"); 4548 #else 4549 if (!check_get_connection_unix_user (context, baz)) 4550 _dbus_assert_not_reached ("GetConnectionUnixUser message failed"); 4551 4552 if (!check_get_connection_unix_process_id (context, baz)) 4553 _dbus_assert_not_reached ("GetConnectionUnixProcessID message failed"); 4554 #endif 4555 4556 if (!check_list_services (context, baz)) 4557 _dbus_assert_not_reached ("ListActivatableNames message failed"); 4558 4559 if (!check_no_leftovers (context)) 4560 { 4561 _dbus_warn ("Messages were left over after setting up initial connections\n"); 4562 _dbus_assert_not_reached ("initial connection setup failed"); 4563 } 4564 4565 check1_try_iterations (context, "create_and_hello", 4566 check_hello_connection); 4567 4568 check2_try_iterations (context, foo, "nonexistent_service_no_auto_start", 4569 check_nonexistent_service_no_auto_start); 4570 4571 #ifdef DBUS_WIN_FIXME 4572 _dbus_warn("TODO: dispatch.c segfault_service_no_auto_start test\n"); 4573 #else 4574 check2_try_iterations (context, foo, "segfault_service_no_auto_start", 4575 check_segfault_service_no_auto_start); 4576 #endif 4577 4578 check2_try_iterations (context, foo, "existent_service_no_auto_start", 4579 check_existent_service_no_auto_start); 4580 4581 check2_try_iterations (context, foo, "nonexistent_service_auto_start", 4582 check_nonexistent_service_auto_start); 4583 4584 4585 #ifdef DBUS_WIN_FIXME 4586 _dbus_warn("TODO: dispatch.c segfault_service_auto_start test\n"); 4587 #else 4588 /* only do the segfault test if we are not using the launcher */ 4589 check2_try_iterations (context, foo, "segfault_service_auto_start", 4590 check_segfault_service_auto_start); 4591 #endif 4592 4593 /* only do the shell fail test if we are not using the launcher */ 4594 check2_try_iterations (context, foo, "shell_fail_service_auto_start", 4595 check_shell_fail_service_auto_start); 4596 4597 /* specific to launcher */ 4598 if (use_launcher) 4599 if (!check_launch_service_file_missing (context, foo)) 4600 _dbus_assert_not_reached ("did not get service file not found error"); 4601 4602 #if 0 4603 /* Note: need to resolve some issues with the testing code in order to run 4604 * this in oom (handle that we sometimes don't get replies back from the bus 4605 * when oom happens, without blocking the test). 4606 */ 4607 check2_try_iterations (context, foo, "existent_service_auto_auto_start", 4608 check_existent_service_auto_start); 4609 #endif 4610 4611 if (!check_existent_service_auto_start (context, foo)) 4612 _dbus_assert_not_reached ("existent service auto start failed"); 4613 4614 if (!check_shell_service_success_auto_start (context, foo)) 4615 _dbus_assert_not_reached ("shell success service auto start failed"); 4616 4617 _dbus_verbose ("Disconnecting foo, bar, and baz\n"); 4618 4619 kill_client_connection_unchecked (foo); 4620 kill_client_connection_unchecked (bar); 4621 kill_client_connection_unchecked (baz); 4622 4623 bus_context_unref (context); 4624 4625 return TRUE; 4626 } 4627 4628 static dbus_bool_t 4629 bus_dispatch_test_conf_fail (const DBusString *test_data_dir, 4630 const char *filename) 4631 { 4632 BusContext *context; 4633 DBusConnection *foo; 4634 DBusError error; 4635 4636 /* save the config name for the activation helper */ 4637 if (!setenv_TEST_LAUNCH_HELPER_CONFIG (test_data_dir, filename)) 4638 _dbus_assert_not_reached ("no memory setting TEST_LAUNCH_HELPER_CONFIG"); 4639 4640 dbus_error_init (&error); 4641 4642 context = bus_context_new_test (test_data_dir, filename); 4643 if (context == NULL) 4644 return FALSE; 4645 4646 foo = dbus_connection_open_private (TEST_DEBUG_PIPE, &error); 4647 if (foo == NULL) 4648 _dbus_assert_not_reached ("could not alloc connection"); 4649 4650 if (!bus_setup_debug_client (foo)) 4651 _dbus_assert_not_reached ("could not set up connection"); 4652 4653 spin_connection_until_authenticated (context, foo); 4654 4655 if (!check_hello_message (context, foo)) 4656 _dbus_assert_not_reached ("hello message failed"); 4657 4658 if (!check_double_hello_message (context, foo)) 4659 _dbus_assert_not_reached ("double hello message failed"); 4660 4661 if (!check_add_match_all (context, foo)) 4662 _dbus_assert_not_reached ("AddMatch message failed"); 4663 4664 /* this only tests the activation.c user check */ 4665 if (!check_launch_service_user_missing (context, foo)) 4666 _dbus_assert_not_reached ("user missing did not trigger error"); 4667 4668 /* this only tests the desktop.c exec check */ 4669 if (!check_launch_service_exec_missing (context, foo)) 4670 _dbus_assert_not_reached ("exec missing did not trigger error"); 4671 4672 /* this only tests the desktop.c service check */ 4673 if (!check_launch_service_service_missing (context, foo)) 4674 _dbus_assert_not_reached ("service missing did not trigger error"); 4675 4676 _dbus_verbose ("Disconnecting foo\n"); 4677 4678 kill_client_connection_unchecked (foo); 4679 4680 bus_context_unref (context); 4681 4682 return TRUE; 4683 } 4684 4685 dbus_bool_t 4686 bus_dispatch_test (const DBusString *test_data_dir) 4687 { 4688 /* run normal activation tests */ 4689 _dbus_verbose ("Normal activation tests\n"); 4690 if (!bus_dispatch_test_conf (test_data_dir, 4691 "valid-config-files/debug-allow-all.conf", FALSE)) 4692 return FALSE; 4693 4694 #ifdef DBUS_WIN 4695 _dbus_warn("Info: Launch helper activation tests skipped because launch-helper is not supported yet\n"); 4696 #else 4697 /* run launch-helper activation tests */ 4698 _dbus_verbose ("Launch helper activation tests\n"); 4699 if (!bus_dispatch_test_conf (test_data_dir, 4700 "valid-config-files-system/debug-allow-all-pass.conf", TRUE)) 4701 return FALSE; 4702 4703 /* run select launch-helper activation tests on broken service files */ 4704 if (!bus_dispatch_test_conf_fail (test_data_dir, 4705 "valid-config-files-system/debug-allow-all-fail.conf")) 4706 return FALSE; 4707 #endif 4708 4709 return TRUE; 4710 } 4711 4712 dbus_bool_t 4713 bus_dispatch_sha1_test (const DBusString *test_data_dir) 4714 { 4715 BusContext *context; 4716 DBusConnection *foo; 4717 DBusError error; 4718 4719 dbus_error_init (&error); 4720 4721 /* Test SHA1 authentication */ 4722 _dbus_verbose ("Testing SHA1 context\n"); 4723 4724 context = bus_context_new_test (test_data_dir, 4725 "valid-config-files/debug-allow-all-sha1.conf"); 4726 if (context == NULL) 4727 return FALSE; 4728 4729 foo = dbus_connection_open_private (TEST_DEBUG_PIPE, &error); 4730 if (foo == NULL) 4731 _dbus_assert_not_reached ("could not alloc connection"); 4732 4733 if (!bus_setup_debug_client (foo)) 4734 _dbus_assert_not_reached ("could not set up connection"); 4735 4736 spin_connection_until_authenticated (context, foo); 4737 4738 if (!check_hello_message (context, foo)) 4739 _dbus_assert_not_reached ("hello message failed"); 4740 4741 if (!check_add_match_all (context, foo)) 4742 _dbus_assert_not_reached ("addmatch message failed"); 4743 4744 if (!check_no_leftovers (context)) 4745 { 4746 _dbus_warn ("Messages were left over after setting up initial SHA-1 connection\n"); 4747 _dbus_assert_not_reached ("initial connection setup failed"); 4748 } 4749 4750 check1_try_iterations (context, "create_and_hello_sha1", 4751 check_hello_connection); 4752 4753 kill_client_connection_unchecked (foo); 4754 4755 bus_context_unref (context); 4756 4757 return TRUE; 4758 } 4759 4760 #ifdef HAVE_UNIX_FD_PASSING 4761 4762 dbus_bool_t 4763 bus_unix_fds_passing_test(const DBusString *test_data_dir) 4764 { 4765 BusContext *context; 4766 DBusConnection *foo, *bar; 4767 DBusError error; 4768 DBusMessage *m; 4769 int one[2], two[2], x, y, z; 4770 char r; 4771 4772 dbus_error_init (&error); 4773 4774 context = bus_context_new_test (test_data_dir, "valid-config-files/debug-allow-all.conf"); 4775 if (context == NULL) 4776 _dbus_assert_not_reached ("could not alloc context"); 4777 4778 foo = dbus_connection_open_private (TEST_DEBUG_PIPE, &error); 4779 if (foo == NULL) 4780 _dbus_assert_not_reached ("could not alloc connection"); 4781 4782 if (!bus_setup_debug_client (foo)) 4783 _dbus_assert_not_reached ("could not set up connection"); 4784 4785 spin_connection_until_authenticated (context, foo); 4786 4787 if (!check_hello_message (context, foo)) 4788 _dbus_assert_not_reached ("hello message failed"); 4789 4790 if (!check_add_match_all (context, foo)) 4791 _dbus_assert_not_reached ("AddMatch message failed"); 4792 4793 bar = dbus_connection_open_private (TEST_DEBUG_PIPE, &error); 4794 if (bar == NULL) 4795 _dbus_assert_not_reached ("could not alloc connection"); 4796 4797 if (!bus_setup_debug_client (bar)) 4798 _dbus_assert_not_reached ("could not set up connection"); 4799 4800 spin_connection_until_authenticated (context, bar); 4801 4802 if (!check_hello_message (context, bar)) 4803 _dbus_assert_not_reached ("hello message failed"); 4804 4805 if (!check_add_match_all (context, bar)) 4806 _dbus_assert_not_reached ("AddMatch message failed"); 4807 4808 if (!(m = dbus_message_new_signal("/", "a.b.c", "d"))) 4809 _dbus_assert_not_reached ("could not alloc message"); 4810 4811 if (!(_dbus_full_duplex_pipe(one, one+1, TRUE, &error))) 4812 _dbus_assert_not_reached("Failed to allocate pipe #1"); 4813 4814 if (!(_dbus_full_duplex_pipe(two, two+1, TRUE, &error))) 4815 _dbus_assert_not_reached("Failed to allocate pipe #2"); 4816 4817 if (!dbus_message_append_args(m, 4818 DBUS_TYPE_UNIX_FD, one, 4819 DBUS_TYPE_UNIX_FD, two, 4820 DBUS_TYPE_UNIX_FD, two, 4821 DBUS_TYPE_INVALID)) 4822 _dbus_assert_not_reached("Failed to attach fds."); 4823 4824 if (!_dbus_close(one[0], &error)) 4825 _dbus_assert_not_reached("Failed to close pipe #1 "); 4826 if (!_dbus_close(two[0], &error)) 4827 _dbus_assert_not_reached("Failed to close pipe #2 "); 4828 4829 if (!(dbus_connection_can_send_type(foo, DBUS_TYPE_UNIX_FD))) 4830 _dbus_assert_not_reached("Connection cannot do fd passing"); 4831 4832 if (!(dbus_connection_can_send_type(bar, DBUS_TYPE_UNIX_FD))) 4833 _dbus_assert_not_reached("Connection cannot do fd passing"); 4834 4835 if (!dbus_connection_send (foo, m, NULL)) 4836 _dbus_assert_not_reached("Failed to send fds"); 4837 4838 dbus_message_unref(m); 4839 4840 bus_test_run_clients_loop (SEND_PENDING (foo)); 4841 4842 bus_test_run_everything (context); 4843 4844 block_connection_until_message_from_bus (context, foo, "unix fd reception on foo"); 4845 4846 if (!(m = pop_message_waiting_for_memory (foo))) 4847 _dbus_assert_not_reached("Failed to receive msg"); 4848 4849 if (!dbus_message_is_signal(m, "a.b.c", "d")) 4850 _dbus_assert_not_reached("bogus message received"); 4851 4852 dbus_message_unref(m); 4853 4854 block_connection_until_message_from_bus (context, bar, "unix fd reception on bar"); 4855 4856 if (!(m = pop_message_waiting_for_memory (bar))) 4857 _dbus_assert_not_reached("Failed to receive msg"); 4858 4859 if (!dbus_message_is_signal(m, "a.b.c", "d")) 4860 _dbus_assert_not_reached("bogus message received"); 4861 4862 if (!dbus_message_get_args(m, 4863 &error, 4864 DBUS_TYPE_UNIX_FD, &x, 4865 DBUS_TYPE_UNIX_FD, &y, 4866 DBUS_TYPE_UNIX_FD, &z, 4867 DBUS_TYPE_INVALID)) 4868 _dbus_assert_not_reached("Failed to parse fds."); 4869 4870 dbus_message_unref(m); 4871 4872 if (write(x, "X", 1) != 1) 4873 _dbus_assert_not_reached("Failed to write to pipe #1"); 4874 if (write(y, "Y", 1) != 1) 4875 _dbus_assert_not_reached("Failed to write to pipe #2"); 4876 if (write(z, "Z", 1) != 1) 4877 _dbus_assert_not_reached("Failed to write to pipe #2/2nd fd"); 4878 4879 if (!_dbus_close(x, &error)) 4880 _dbus_assert_not_reached("Failed to close pipe #1/other side "); 4881 if (!_dbus_close(y, &error)) 4882 _dbus_assert_not_reached("Failed to close pipe #2/other side "); 4883 if (!_dbus_close(z, &error)) 4884 _dbus_assert_not_reached("Failed to close pipe #2/other size 2nd fd "); 4885 4886 if (read(one[1], &r, 1) != 1 || r != 'X') 4887 _dbus_assert_not_reached("Failed to read value from pipe."); 4888 if (read(two[1], &r, 1) != 1 || r != 'Y') 4889 _dbus_assert_not_reached("Failed to read value from pipe."); 4890 if (read(two[1], &r, 1) != 1 || r != 'Z') 4891 _dbus_assert_not_reached("Failed to read value from pipe."); 4892 4893 if (!_dbus_close(one[1], &error)) 4894 _dbus_assert_not_reached("Failed to close pipe #1 "); 4895 if (!_dbus_close(two[1], &error)) 4896 _dbus_assert_not_reached("Failed to close pipe #2 "); 4897 4898 _dbus_verbose ("Disconnecting foo\n"); 4899 kill_client_connection_unchecked (foo); 4900 4901 _dbus_verbose ("Disconnecting bar\n"); 4902 kill_client_connection_unchecked (bar); 4903 4904 bus_context_unref (context); 4905 4906 return TRUE; 4907 } 4908 #endif 4909 4910 #endif /* DBUS_BUILD_TESTS */ 4911