summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2010-04-26 19:06:01 -0400
committerDavid Zeuthen <davidz@redhat.com>2010-04-26 19:06:01 -0400
commitd7c2b7391a5bbcb1fee2972be23c5a920e00031a (patch)
treef8e05117f159b4cff35befd8fdbfa1906f5edeb6
parent9149eccf89f98e86902ce3487d5dfa38c70d5762 (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.txt1
-rw-r--r--gdbus/Makefile.am5
-rw-r--r--gdbus/example-server.c46
-rw-r--r--gdbus/example-unix-fd-client.c132
-rw-r--r--gdbus/gdbusconnection.c48
-rw-r--r--gdbus/gdbusmessage.c68
-rw-r--r--gdbus/gdbusmessage.h3
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__ */