#include <config.h> #include "test-utils.h" #ifdef HAVE_UNISTD_H #include <unistd.h> #endif static DBusLoop *loop; static dbus_bool_t already_quit = FALSE; static dbus_bool_t hello_from_self_reply_received = FALSE; static void quit (void) { if (!already_quit) { _dbus_loop_quit (loop); already_quit = TRUE; } } static void die (const char *message) { fprintf (stderr, "*** test-service: %s", message); exit (1); } static void check_hello_from_self_reply (DBusPendingCall *pcall, void *user_data) { DBusMessage *reply; DBusMessage *echo_message, *echo_reply = NULL; DBusError error; DBusConnection *connection; int type; dbus_error_init (&error); connection = dbus_bus_get (DBUS_BUS_STARTER, &error); if (connection == NULL) { fprintf (stderr, "*** Failed to open connection to activating message bus: %s\n", error.message); dbus_error_free (&error); die("no memory"); } echo_message = (DBusMessage *)user_data; reply = dbus_pending_call_steal_reply (pcall); type = dbus_message_get_type (reply); if (type == DBUS_MESSAGE_TYPE_METHOD_RETURN) { const char *s; printf ("Reply from HelloFromSelf received\n"); if (!dbus_message_get_args (echo_message, &error, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID)) { echo_reply = dbus_message_new_error (echo_message, error.name, error.message); if (echo_reply == NULL) die ("No memory\n"); } else { echo_reply = dbus_message_new_method_return (echo_message); if (echo_reply == NULL) die ("No memory\n"); if (!dbus_message_append_args (echo_reply, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID)) die ("No memory"); } if (!dbus_connection_send (connection, echo_reply, NULL)) die ("No memory\n"); dbus_message_unref (echo_reply); } else if (type == DBUS_MESSAGE_TYPE_ERROR) { dbus_set_error_from_message (&error, reply); printf ("Error type in reply: %s\n", error.message); if (strcmp (error.name, DBUS_ERROR_NO_MEMORY) != 0) { echo_reply = dbus_message_new_error (echo_reply, error.name, error.message); if (echo_reply == NULL) die ("No memory\n"); if (!dbus_connection_send (connection, echo_reply, NULL)) die ("No memory\n"); dbus_message_unref (echo_reply); } dbus_error_free (&error); } else _dbus_assert_not_reached ("Unexpected message received\n"); hello_from_self_reply_received = TRUE; dbus_message_unref (reply); dbus_message_unref (echo_message); dbus_pending_call_unref (pcall); dbus_connection_unref (connection); } static DBusHandlerResult handle_run_hello_from_self (DBusConnection *connection, DBusMessage *message) { DBusError error; DBusMessage *reply, *self_message; DBusPendingCall *pcall; char *s; _dbus_verbose ("sending reply to Echo method\n"); dbus_error_init (&error); if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID)) { reply = dbus_message_new_error (message, error.name, error.message); if (reply == NULL) die ("No memory\n"); if (!dbus_connection_send (connection, reply, NULL)) die ("No memory\n"); dbus_message_unref (reply); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } printf ("Sending HelloFromSelf\n"); _dbus_verbose ("*** Sending message to self\n"); self_message = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteEchoService", "/org/freedesktop/TestSuite", "org.freedesktop.TestSuite", "HelloFromSelf"); if (self_message == NULL) die ("No memory"); if (!dbus_connection_send_with_reply (connection, self_message, &pcall, -1)) die("No memory"); dbus_message_ref (message); if (!dbus_pending_call_set_notify (pcall, check_hello_from_self_reply, (void *)message, NULL)) die("No memory"); printf ("Sent HelloFromSelf\n"); return DBUS_HANDLER_RESULT_HANDLED; } static DBusHandlerResult handle_echo (DBusConnection *connection, DBusMessage *message) { DBusError error; DBusMessage *reply; char *s; _dbus_verbose ("sending reply to Echo method\n"); dbus_error_init (&error); if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID)) { reply = dbus_message_new_error (message, error.name, error.message); if (reply == NULL) die ("No memory\n"); if (!dbus_connection_send (connection, reply, NULL)) die ("No memory\n"); dbus_message_unref (reply); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } reply = dbus_message_new_method_return (message); if (reply == NULL) die ("No memory\n"); if (!dbus_message_append_args (reply, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID)) die ("No memory"); if (!dbus_connection_send (connection, reply, NULL)) die ("No memory\n"); fprintf (stderr, "Echo service echoed string: \"%s\"\n", s); dbus_message_unref (reply); return DBUS_HANDLER_RESULT_HANDLED; } static DBusHandlerResult handle_delay_echo (DBusConnection *connection, DBusMessage *message) { DBusError error; DBusMessage *reply; char *s; _dbus_verbose ("sleeping for a short time\n"); _dbus_sleep_milliseconds (50); _dbus_verbose ("sending reply to DelayEcho method\n"); dbus_error_init (&error); if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID)) { reply = dbus_message_new_error (message, error.name, error.message); if (reply == NULL) die ("No memory\n"); if (!dbus_connection_send (connection, reply, NULL)) die ("No memory\n"); dbus_message_unref (reply); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } reply = dbus_message_new_method_return (message); if (reply == NULL) die ("No memory\n"); if (!dbus_message_append_args (reply, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID)) die ("No memory"); if (!dbus_connection_send (connection, reply, NULL)) die ("No memory\n"); fprintf (stderr, "DelayEcho service echoed string: \"%s\"\n", s); dbus_message_unref (reply); return DBUS_HANDLER_RESULT_HANDLED; } static void path_unregistered_func (DBusConnection *connection, void *user_data) { /* connection was finalized */ } static DBusHandlerResult path_message_func (DBusConnection *connection, DBusMessage *message, void *user_data) { if (dbus_message_is_method_call (message, "org.freedesktop.TestSuite", "Echo")) return handle_echo (connection, message); else if (dbus_message_is_method_call (message, "org.freedesktop.TestSuite", "DelayEcho")) return handle_delay_echo (connection, message); else if (dbus_message_is_method_call (message, "org.freedesktop.TestSuite", "Exit")) { quit (); return DBUS_HANDLER_RESULT_HANDLED; } else if (dbus_message_is_method_call (message, "org.freedesktop.TestSuite", "EmitFoo")) { /* Emit the Foo signal */ DBusMessage *signal; double v_DOUBLE; _dbus_verbose ("emitting signal Foo\n"); signal = dbus_message_new_signal ("/org/freedesktop/TestSuite", "org.freedesktop.TestSuite", "Foo"); if (signal == NULL) die ("No memory\n"); v_DOUBLE = 42.6; if (!dbus_message_append_args (signal, DBUS_TYPE_DOUBLE, &v_DOUBLE, DBUS_TYPE_INVALID)) die ("No memory"); if (!dbus_connection_send (connection, signal, NULL)) die ("No memory\n"); return DBUS_HANDLER_RESULT_HANDLED; } else if (dbus_message_is_method_call (message, "org.freedesktop.TestSuite", "RunHelloFromSelf")) { return handle_run_hello_from_self (connection, message); } else if (dbus_message_is_method_call (message, "org.freedesktop.TestSuite", "HelloFromSelf")) { DBusMessage *reply; printf ("Received the HelloFromSelf message\n"); reply = dbus_message_new_method_return (message); if (reply == NULL) die ("No memory"); if (!dbus_connection_send (connection, reply, NULL)) die ("No memory"); return DBUS_HANDLER_RESULT_HANDLED; } else return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } static DBusObjectPathVTable echo_vtable = { path_unregistered_func, path_message_func, NULL, }; static const char* echo_path = "/org/freedesktop/TestSuite" ; static DBusHandlerResult filter_func (DBusConnection *connection, DBusMessage *message, void *user_data) { if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected")) { quit (); return DBUS_HANDLER_RESULT_HANDLED; } else { return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } } int main (int argc, char **argv) { DBusError error; int result; DBusConnection *connection; const char *name; dbus_bool_t do_fork; if (argc != 3) { name = "org.freedesktop.DBus.TestSuiteEchoService"; do_fork = FALSE; } else { name = argv[1]; #ifndef DBUS_WIN do_fork = strcmp (argv[2], "fork") == 0; #else do_fork = FALSE; #endif } /* The bare minimum for simulating a program "daemonizing"; the intent * is to test services which move from being legacy init scripts to * activated services. * https://bugzilla.redhat.com/show_bug.cgi?id=545267 */ #ifndef DBUS_WIN if (do_fork) { pid_t pid = fork (); if (pid != 0) exit (0); sleep (1); } #endif dbus_error_init (&error); connection = dbus_bus_get (DBUS_BUS_STARTER, &error); if (connection == NULL) { fprintf (stderr, "*** Failed to open connection to activating message bus: %s\n", error.message); dbus_error_free (&error); return 1; } loop = _dbus_loop_new (); if (loop == NULL) die ("No memory\n"); if (!test_connection_setup (loop, connection)) die ("No memory\n"); if (!dbus_connection_add_filter (connection, filter_func, NULL, NULL)) die ("No memory"); if (!dbus_connection_register_object_path (connection, echo_path, &echo_vtable, (void*) 0xdeadbeef)) die ("No memory"); { void *d; if (!dbus_connection_get_object_path_data (connection, echo_path, &d)) die ("No memory"); if (d != (void*) 0xdeadbeef) die ("dbus_connection_get_object_path_data() doesn't seem to work right\n"); } result = dbus_bus_request_name (connection, name, 0, &error); if (dbus_error_is_set (&error)) { fprintf (stderr, "Error %s\n", error.message); _dbus_verbose ("*** Failed to acquire service: %s\n", error.message); dbus_error_free (&error); exit (1); } _dbus_verbose ("*** Test service entering main loop\n"); _dbus_loop_run (loop); test_connection_shutdown (loop, connection); dbus_connection_remove_filter (connection, filter_func, NULL); dbus_connection_unref (connection); _dbus_loop_unref (loop); loop = NULL; dbus_shutdown (); _dbus_verbose ("*** Test service exiting\n"); return 0; }