diff options
author | David Zeuthen <davidz@redhat.com> | 2010-04-26 19:06:01 -0400 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2010-04-26 19:06:01 -0400 |
commit | d7c2b7391a5bbcb1fee2972be23c5a920e00031a (patch) | |
tree | f8e05117f159b4cff35befd8fdbfa1906f5edeb6 | |
parent | 9149eccf89f98e86902ce3487d5dfa38c70d5762 (diff) |
Add example-unix-fd-client.c
It should work like this:
$ ./example-server
On Mon Apr 26 19:06:28 2010, example-unix-fd-client with pid 27957 was here!
On Mon Apr 26 19:06:30 2010, example-unix-fd-client with pid 27974 was here!
$ ./example-unix-fd-client
Wrote the following on server's stdout:
On Mon Apr 26 19:06:28 2010, example-unix-fd-client with pid 27957 was here!
$ ./example-unix-fd-client
Wrote the following on server's stdout:
On Mon Apr 26 19:06:30 2010, example-unix-fd-client with pid 27974 was here!
$
-rw-r--r-- | docs/reference/gdbus/gdbus-standalone-sections.txt | 1 | ||||
-rw-r--r-- | gdbus/Makefile.am | 5 | ||||
-rw-r--r-- | gdbus/example-server.c | 46 | ||||
-rw-r--r-- | gdbus/example-unix-fd-client.c | 132 | ||||
-rw-r--r-- | gdbus/gdbusconnection.c | 48 | ||||
-rw-r--r-- | gdbus/gdbusmessage.c | 68 | ||||
-rw-r--r-- | gdbus/gdbusmessage.h | 3 |
7 files changed, 256 insertions, 47 deletions
diff --git a/docs/reference/gdbus/gdbus-standalone-sections.txt b/docs/reference/gdbus/gdbus-standalone-sections.txt index a2d0819..e91f948 100644 --- a/docs/reference/gdbus/gdbus-standalone-sections.txt +++ b/docs/reference/gdbus/gdbus-standalone-sections.txt @@ -62,6 +62,7 @@ g_dbus_message_get_arg0 g_dbus_message_to_blob g_dbus_message_bytes_needed g_dbus_message_new_from_blob +g_dbus_message_to_gerror <SUBSECTION Standard> G_DBUS_MESSAGE G_IS_DBUS_MESSAGE diff --git a/gdbus/Makefile.am b/gdbus/Makefile.am index 21e6155..3122307 100644 --- a/gdbus/Makefile.am +++ b/gdbus/Makefile.am @@ -142,6 +142,7 @@ noinst_PROGRAMS += example-own-name noinst_PROGRAMS += example-watch-name noinst_PROGRAMS += example-watch-proxy noinst_PROGRAMS += example-server +noinst_PROGRAMS += example-unix-fd-client noinst_PROGRAMS += example-subtree example_watch_name_SOURCES = example-watch-name.c @@ -160,6 +161,10 @@ example_server_SOURCES = example-server.c example_server_CFLAGS = $(GLIB2_CFLAGS) $(GOBJECT2_CFLAGS) $(GIO2_CFLAGS) $(GIO_UNIX2_CFLAGS) example_server_LDADD = libgdbus-standalone.la $(GLIB2_LIBS) $(GOBJECT2_LIBS) $(GIO2_LIBS) $(GIO_UNIX2_LIBS) +example_unix_fd_client_SOURCES = example-unix-fd-client.c +example_unix_fd_client_CFLAGS = $(GLIB2_CFLAGS) $(GOBJECT2_CFLAGS) $(GIO2_CFLAGS) $(GIO_UNIX2_CFLAGS) +example_unix_fd_client_LDADD = libgdbus-standalone.la $(GLIB2_LIBS) $(GOBJECT2_LIBS) $(GIO2_LIBS) $(GIO_UNIX2_LIBS) + example_subtree_SOURCES = example-subtree.c example_subtree_CFLAGS = $(GLIB2_CFLAGS) $(GOBJECT2_CFLAGS) $(GIO2_CFLAGS) $(GIO_UNIX2_CFLAGS) example_subtree_LDADD = libgdbus-standalone.la $(GLIB2_LIBS) $(GOBJECT2_LIBS) $(GIO2_LIBS) $(GIO_UNIX2_LIBS) diff --git a/gdbus/example-server.c b/gdbus/example-server.c index 7b4a420..2601c09 100644 --- a/gdbus/example-server.c +++ b/gdbus/example-server.c @@ -2,6 +2,11 @@ #include <gdbus/gdbus.h> #include <stdlib.h> +#ifdef G_OS_UNIX +/* For STDOUT_FILENO */ +#include <unistd.h> +#endif + /* ---------------------------------------------------------------------------------------------------- */ static GDBusNodeInfo *introspection_data = NULL; @@ -17,6 +22,7 @@ static const gchar introspection_xml[] = " <method name='EmitSignal'>" " <arg type='d' name='speed_in_mph' direction='in'/>" " </method>" + " <method name='GimmeStdout'/>" " <signal name='VelocityChanged'>" " <arg type='d' name='speed_in_mph'/>" " <arg type='s' name='speed_as_string'/>" @@ -102,6 +108,46 @@ handle_method_call (GDBusConnection *connection, g_dbus_method_invocation_return_value (invocation, NULL); } + else if (g_strcmp0 (method_name, "GimmeStdout") == 0) + { +#ifdef G_OS_UNIX + if (g_dbus_connection_get_capabilities (connection) & G_DBUS_CONNECTION_CAPABILITY_FLAGS_UNIX_FD_PASSING) + { + GDBusMessage *reply; + GUnixFDList *fd_list; + GError *error; + + fd_list = g_unix_fd_list_new (); + error = NULL; + g_unix_fd_list_append (fd_list, STDOUT_FILENO, &error); + g_assert_no_error (error); + + reply = g_dbus_message_new_method_reply (g_dbus_method_invocation_get_message (invocation)); + g_dbus_message_set_unix_fd_list (reply, fd_list); + + error = NULL; + g_dbus_connection_send_message (connection, + reply, + NULL, /* out_serial */ + &error); + g_assert_no_error (error); + + g_object_unref (invocation); + g_object_unref (fd_list); + g_object_unref (reply); + } + else + { + g_dbus_method_invocation_return_dbus_error (invocation, + "org.gtk.GDBus.Failed", + "Your message bus daemon does not support file descriptor passing (need D-Bus >= 1.3.0)"); + } +#else + g_dbus_method_invocation_return_dbus_error (invocation, + "org.gtk.GDBus.NotOnUnix", + "Your OS does not support file descriptor passing"); +#endif + } } static gchar *_global_title = NULL; diff --git a/gdbus/example-unix-fd-client.c b/gdbus/example-unix-fd-client.c new file mode 100644 index 0000000..6729913 --- /dev/null +++ b/gdbus/example-unix-fd-client.c @@ -0,0 +1,132 @@ + +#include <string.h> +#include <stdlib.h> + +#include <sys/types.h> +#include <unistd.h> + +#include <time.h> + +#include <gdbus/gdbus.h> + +/* see example-server.c for the server implementation */ +static gint +get_server_stdout (GDBusConnection *connection, + const gchar *name_owner, + GError **error) +{ + GDBusMessage *method_call_message; + GDBusMessage *method_reply_message; + GUnixFDList *fd_list; + gint fd; + + fd = -1; + method_call_message = NULL; + method_reply_message = NULL; + + method_call_message = g_dbus_message_new_method_call (name_owner, + "/org/gtk/GDBus/TestObject", + "org.gtk.GDBus.TestInterface", + "GimmeStdout"); + method_reply_message = g_dbus_connection_send_message_with_reply_sync (connection, + method_call_message, + -1, + NULL, /* out_serial */ + NULL, /* cancellable */ + error); + if (method_reply_message == NULL) + goto out; + + if (g_dbus_message_get_type (method_reply_message) == G_DBUS_MESSAGE_TYPE_ERROR) + { + g_dbus_message_to_gerror (method_reply_message, error); + goto out; + } + + fd_list = g_dbus_message_get_unix_fd_list (method_reply_message); + fd = g_unix_fd_list_get (fd_list, 0, error); + + out: + g_object_unref (method_call_message); + g_object_unref (method_reply_message); + + return fd; +} + +static void +on_name_appeared (GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + gpointer user_data) +{ + gint fd; + GError *error; + + error = NULL; + fd = get_server_stdout (connection, name_owner, &error); + if (fd == -1) + { + g_printerr ("Error invoking GimmeStdout(): %s\n", + error->message); + g_error_free (error); + exit (1); + } + else + { + gchar now_buf[256]; + time_t now; + gssize len; + gchar *str; + + now = time (NULL); + strftime (now_buf, + sizeof now_buf, + "%c", + localtime (&now)); + + str = g_strdup_printf ("On %s, example-unix-fd-client with pid %d was here!\n", + now_buf, + (gint) getpid ()); + len = strlen (str); + g_assert (write (fd, str, len) == len); + close (fd); + + g_print ("Wrote the following on server's stdout:\n%s", str); + + g_free (str); + exit (0); + } +} + +static void +on_name_vanished (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + g_printerr ("Failed to get name owner for %s\n" + "Is ./example-server running?\n", + name); + exit (1); +} + +int +main (int argc, char *argv[]) +{ + guint watcher_id; + GMainLoop *loop; + + g_type_init (); + + watcher_id = g_bus_watch_name (G_BUS_TYPE_SESSION, + "org.gtk.GDBus.TestServer", + on_name_appeared, + on_name_vanished, + NULL, + NULL); + + loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (loop); + + g_bus_unwatch_name (watcher_id); + return 0; +} diff --git a/gdbus/gdbusconnection.c b/gdbus/gdbusconnection.c index fb5e9d6..a2dd318 100644 --- a/gdbus/gdbusconnection.c +++ b/gdbus/gdbusconnection.c @@ -3883,7 +3883,6 @@ static GVariant * decode_method_reply (GDBusMessage *reply, GError **error) { GVariant *result; - const gchar *error_name; result = NULL; switch (g_dbus_message_get_type (reply)) @@ -3901,52 +3900,7 @@ decode_method_reply (GDBusMessage *reply, GError **error) } break; case G_DBUS_MESSAGE_TYPE_ERROR: - error_name = g_dbus_message_get_error_name (reply); - if (error_name != NULL) - { - GVariant *body; - - body = g_dbus_message_get_body (reply); - - if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)"))) - { - const gchar *error_message; - g_variant_get (body, "(s)", &error_message); - g_dbus_error_set_dbus_error (error, - error_name, - error_message, - NULL); - } - else - { - /* these two situations are valid, yet pretty rare */ - if (body != NULL) - { - g_dbus_error_set_dbus_error (error, - error_name, - "", - _("Error return with body of type `%s'"), - g_variant_get_type_string (body)); - } - else - { - g_dbus_error_set_dbus_error (error, - error_name, - "", - _("Error return with empty body")); - } - } - } - else - { - /* TOOD: this shouldn't happen - should check this at message serialization - * time and disconnect the peer - */ - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "Error return without error-name header!"); - } + g_dbus_message_to_gerror (reply, error); break; default: diff --git a/gdbus/gdbusmessage.c b/gdbus/gdbusmessage.c index 2bf5f84..d01c801 100644 --- a/gdbus/gdbusmessage.c +++ b/gdbus/gdbusmessage.c @@ -1670,3 +1670,71 @@ g_dbus_message_set_num_unix_fds (GDBusMessage *message, } /* ---------------------------------------------------------------------------------------------------- */ + +gboolean +g_dbus_message_to_gerror (GDBusMessage *message, + GError **error) +{ + gboolean ret; + const gchar *error_name; + + g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE); + + ret = FALSE; + if (message->priv->type != G_DBUS_MESSAGE_TYPE_ERROR) + goto out; + + error_name = g_dbus_message_get_error_name (message); + if (error_name != NULL) + { + GVariant *body; + + body = g_dbus_message_get_body (message); + + if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)"))) + { + const gchar *error_message; + g_variant_get (body, "(s)", &error_message); + g_dbus_error_set_dbus_error (error, + error_name, + error_message, + NULL); + } + else + { + /* these two situations are valid, yet pretty rare */ + if (body != NULL) + { + g_dbus_error_set_dbus_error (error, + error_name, + "", + _("Error return with body of type `%s'"), + g_variant_get_type_string (body)); + } + else + { + g_dbus_error_set_dbus_error (error, + error_name, + "", + _("Error return with empty body")); + } + } + } + else + { + /* TOOD: this shouldn't happen - should check this at message serialization + * time and disconnect the peer. + */ + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_FAILED, + "Error return without error-name header!"); + } + + ret = TRUE; + + out: + return ret; +} + +/* ---------------------------------------------------------------------------------------------------- */ diff --git a/gdbus/gdbusmessage.h b/gdbus/gdbusmessage.h index 499d158..2ca6618 100644 --- a/gdbus/gdbusmessage.h +++ b/gdbus/gdbusmessage.h @@ -153,6 +153,9 @@ guchar *g_dbus_message_to_blob (GDBusMessage gsize *out_size, GError **error); +gboolean g_dbus_message_to_gerror (GDBusMessage *message, + GError **error); + G_END_DECLS #endif /* __G_DBUS_MESSAGE_H__ */ |