[glib] gdbus-codegen: Add support for new org.gtk.GDBus.C.UnixFD annotation
- From: David Zeuthen <davidz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] gdbus-codegen: Add support for new org.gtk.GDBus.C.UnixFD annotation
- Date: Thu, 21 Jul 2011 20:06:30 +0000 (UTC)
commit c404dbed11bc8bf4212d15719ef3a87ebf76efff
Author: David Zeuthen <davidz redhat com>
Date: Thu Jul 21 16:03:27 2011 -0400
gdbus-codegen: Add support for new org.gtk.GDBus.C.UnixFD annotation
Also add convenience _with_unix_fd_list variants to GDBusConnection,
GDBusProxy and GDBusMethodInvocation types to easily support this.
Signed-off-by: David Zeuthen <davidz redhat com>
docs/reference/gio/gdbus-codegen.xml | 21 +-
docs/reference/gio/gio-sections.txt | 7 +
gio/gdbus-codegen/codegen.py | 148 ++++++++--
gio/gdbusconnection.c | 557 +++++++++++++++++++++++-----------
gio/gdbusconnection.h | 30 ++
gio/gdbusmethodinvocation.c | 76 ++++-
gio/gdbusmethodinvocation.h | 3 +
gio/gdbusproxy.c | 495 ++++++++++++++++++++++---------
gio/gdbusproxy.h | 23 ++
gio/gio.symbols | 7 +
gio/tests/test-codegen.xml | 8 +
11 files changed, 1012 insertions(+), 363 deletions(-)
---
diff --git a/docs/reference/gio/gdbus-codegen.xml b/docs/reference/gio/gdbus-codegen.xml
index 33c4617..3a741e6 100644
--- a/docs/reference/gio/gdbus-codegen.xml
+++ b/docs/reference/gio/gdbus-codegen.xml
@@ -332,6 +332,18 @@ gdbus-codegen --c-namespace MyApp \
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><literal>org.gtk.GDBus.C.UnixFD</literal></term>
+ <listitem>
+ <para>
+ If set to a non-empty string, the generated code will
+ include parameters to exchange file descriptors using the
+ #GUnixFDList type. This annotation can be used on
+ <literal><method></literal> elements.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
<para>
@@ -744,8 +756,7 @@ on_handle_hello_world (MyAppFrobber *interface,
<link linkend="G-VARIANT-TYPE-INT32:CAPS">'i'</link>,
<link linkend="G-VARIANT-TYPE-UINT32:CAPS">'u'</link>,
<link linkend="G-VARIANT-TYPE-INT64:CAPS">'x'</link>,
- <link linkend="G-VARIANT-TYPE-UINT64:CAPS">'t'</link>,
- <link linkend="G-VARIANT-TYPE-HANDLE:CAPS">'h'</link> and
+ <link linkend="G-VARIANT-TYPE-UINT64:CAPS">'t'</link> and
<link linkend="G-VARIANT-TYPE-DOUBLE:CAPS">'d'</link>)
),
strings (type-strings
@@ -780,11 +791,7 @@ on_handle_hello_world (MyAppFrobber *interface,
The generated C functions are guaranteed to not change their ABI
that is, if a method, signal or property does not change its
signature in the introspection XML, the generated C functions will
- not change its C ABI either. One exception to this guarantee is if
- you are using type <link
- linkend="G-VARIANT-TYPE-HANDLE:CAPS">'h'</link> for passing file
- descriptors on Unix. Future versions of gdbus-codegen will include
- guarantees for this type as well.
+ not change its C ABI either.
</para>
<para>
The ABI of the generated #GType<!-- -->s will be preserved only if
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
index 87617a6..29f10c1 100644
--- a/docs/reference/gio/gio-sections.txt
+++ b/docs/reference/gio/gio-sections.txt
@@ -2468,6 +2468,9 @@ GDBusCallFlags
g_dbus_connection_call
g_dbus_connection_call_finish
g_dbus_connection_call_sync
+g_dbus_connection_call_with_unix_fd_list
+g_dbus_connection_call_with_unix_fd_list_finish
+g_dbus_connection_call_with_unix_fd_list_sync
g_dbus_connection_emit_signal
GDBusSignalFlags
GDBusSignalCallback
@@ -2522,6 +2525,7 @@ g_dbus_method_invocation_return_error_literal
g_dbus_method_invocation_return_gerror
g_dbus_method_invocation_return_dbus_error
g_dbus_method_invocation_take_error
+g_dbus_method_invocation_return_value_with_unix_fd_list
<SUBSECTION Standard>
G_DBUS_METHOD_INVOCATION
G_IS_DBUS_METHOD_INVOCATION
@@ -2602,6 +2606,9 @@ g_dbus_proxy_get_interface_info
g_dbus_proxy_call
g_dbus_proxy_call_finish
g_dbus_proxy_call_sync
+g_dbus_proxy_call_with_unix_fd_list
+g_dbus_proxy_call_with_unix_fd_list_finish
+g_dbus_proxy_call_with_unix_fd_list_sync
<SUBSECTION Standard>
G_DBUS_PROXY
G_IS_DBUS_PROXY
diff --git a/gio/gdbus-codegen/codegen.py b/gio/gdbus-codegen/codegen.py
index 3d29e56..00c59b8 100644
--- a/gio/gdbus-codegen/codegen.py
+++ b/gio/gdbus-codegen/codegen.py
@@ -63,6 +63,11 @@ class CodeGenerator:
'#include "%s"\n'
'\n'%(self.h.name))
+ self.c.write('#ifdef G_OS_UNIX\n'
+ '# include <gio/gunixfdlist.h>\n'
+ '#endif\n'
+ '\n')
+
self.c.write('typedef struct\n'
'{\n'
' GDBusArgInfo parent_struct;\n'
@@ -74,6 +79,7 @@ class CodeGenerator:
'{\n'
' GDBusMethodInfo parent_struct;\n'
' const gchar *signal_name;\n'
+ ' gboolean pass_fdlist;\n'
'} _ExtendedGDBusMethodInfo;\n'
'\n')
@@ -242,10 +248,15 @@ class CodeGenerator:
if len(i.methods) > 0:
self.h.write('\n')
for m in i.methods:
+ unix_fd = False
+ if utils.lookup_annotation(m.annotations, 'org.gtk.GDBus.C.UnixFD'):
+ unix_fd = True
key = (m.since, '_method_%s'%m.name_lower)
value = ' gboolean (*handle_%s) (\n'%(m.name_lower)
value += ' %s *object,\n'%(i.camel_name)
value += ' GDBusMethodInvocation *invocation'%()
+ if unix_fd:
+ value += ',\n GUnixFDList *fd_list'
for a in m.in_args:
value += ',\n %s%s'%(a.ctype_in, a.name)
value += ');\n\n'
@@ -291,11 +302,16 @@ class CodeGenerator:
self.h.write('\n')
self.h.write('/* D-Bus method call completion functions: */\n')
for m in i.methods:
+ unix_fd = False
+ if utils.lookup_annotation(m.annotations, 'org.gtk.GDBus.C.UnixFD'):
+ unix_fd = True
if m.deprecated:
self.h.write('G_GNUC_DEPRECATED ')
self.h.write('void %s_complete_%s (\n'
' %s *object,\n'
' GDBusMethodInvocation *invocation'%(i.name_lower, m.name_lower, i.camel_name))
+ if unix_fd:
+ self.h.write(',\n GUnixFDList *fd_list')
for a in m.out_args:
self.h.write(',\n %s%s'%(a.ctype_in, a.name))
self.h.write(');\n')
@@ -322,6 +338,9 @@ class CodeGenerator:
self.h.write('\n')
self.h.write('/* D-Bus method calls: */\n')
for m in i.methods:
+ unix_fd = False
+ if utils.lookup_annotation(m.annotations, 'org.gtk.GDBus.C.UnixFD'):
+ unix_fd = True
# async begin
if m.deprecated:
self.h.write('G_GNUC_DEPRECATED ')
@@ -329,6 +348,8 @@ class CodeGenerator:
' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name))
for a in m.in_args:
self.h.write(',\n %s%s'%(a.ctype_in, a.name))
+ if unix_fd:
+ self.h.write(',\n GUnixFDList *fd_list')
self.h.write(',\n'
' GCancellable *cancellable,\n'
' GAsyncReadyCallback callback,\n'
@@ -341,6 +362,8 @@ class CodeGenerator:
' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name))
for a in m.out_args:
self.h.write(',\n %sout_%s'%(a.ctype_out, a.name))
+ if unix_fd:
+ self.h.write(',\n GUnixFDList **out_fd_list')
self.h.write(',\n'
' GAsyncResult *res,\n'
' GError **error);\n')
@@ -352,8 +375,12 @@ class CodeGenerator:
' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name))
for a in m.in_args:
self.h.write(',\n %s%s'%(a.ctype_in, a.name))
+ if unix_fd:
+ self.h.write(',\n GUnixFDList *fd_list')
for a in m.out_args:
self.h.write(',\n %sout_%s'%(a.ctype_out, a.name))
+ if unix_fd:
+ self.h.write(',\n GUnixFDList **out_fd_list')
self.h.write(',\n'
' GCancellable *cancellable,\n'
' GError **error);\n')
@@ -749,6 +776,9 @@ class CodeGenerator:
if len(i.methods) > 0:
for m in i.methods:
+ unix_fd = False
+ if utils.lookup_annotation(m.annotations, 'org.gtk.GDBus.C.UnixFD'):
+ unix_fd = True
self.generate_args('_%s_method_info_%s_IN_ARG'%(i.name_lower, m.name_lower), m.in_args)
self.generate_args('_%s_method_info_%s_OUT_ARG'%(i.name_lower, m.name_lower), m.out_args)
@@ -772,8 +802,9 @@ class CodeGenerator:
else:
self.c.write(' (GDBusAnnotationInfo **) &_%s_method_%s_annotation_info_pointers\n'%(i.name_lower, m.name_lower))
self.c.write(' },\n'
- ' "handle-%s"\n'
- %(m.name_hyphen))
+ ' "handle-%s",\n'
+ ' %s\n'
+ %(m.name_hyphen, 'TRUE' if unix_fd else 'FALSE'))
self.c.write('};\n'
'\n')
@@ -980,12 +1011,17 @@ class CodeGenerator:
if len(i.methods) > 0:
self.c.write(' /* GObject signals for incoming D-Bus method calls: */\n')
for m in i.methods:
+ unix_fd = False
+ if utils.lookup_annotation(m.annotations, 'org.gtk.GDBus.C.UnixFD'):
+ unix_fd = True
self.c.write(self.docbook_gen.expand(
' /**\n'
' * %s::handle-%s:\n'
' * @object: A #%s.\n'
' * @invocation: A #GDBusMethodInvocation.\n'
%(i.camel_name, m.name_hyphen, i.camel_name), False))
+ if unix_fd:
+ self.c.write (' * @fd_list: (allow-none): A #GUnixFDList or %NULL.\n')
for a in m.in_args:
self.c.write (' * @%s: Argument passed by remote caller.\n'%(a.name))
self.c.write(self.docbook_gen.expand(
@@ -997,6 +1033,10 @@ class CodeGenerator:
' * Returns: %%TRUE if the invocation was handled, %%FALSE to let other signal handlers run.\n'
%(i.name, m.name, i.name_lower, m.name_lower), False))
self.write_gtkdoc_deprecated_and_since_and_close(m, self.c, 2)
+ if unix_fd:
+ extra_args = 2
+ else:
+ extra_args = 1
self.c.write(' g_signal_new ("handle-%s",\n'
' G_TYPE_FROM_INTERFACE (iface),\n'
' G_SIGNAL_RUN_LAST,\n'
@@ -1007,7 +1047,9 @@ class CodeGenerator:
' G_TYPE_BOOLEAN,\n'
' %d,\n'
' G_TYPE_DBUS_METHOD_INVOCATION'
- %(m.name_hyphen, i.camel_name, m.name_lower, len(m.in_args) + 1))
+ %(m.name_hyphen, i.camel_name, m.name_lower, len(m.in_args) + extra_args))
+ if unix_fd:
+ self.c.write(', G_TYPE_UNIX_FD_LIST')
for a in m.in_args:
self.c.write (', %s'%(a.gtype))
self.c.write(');\n')
@@ -1212,6 +1254,9 @@ class CodeGenerator:
def generate_method_calls(self, i):
for m in i.methods:
+ unix_fd = False
+ if utils.lookup_annotation(m.annotations, 'org.gtk.GDBus.C.UnixFD'):
+ unix_fd = True
# async begin
self.c.write('/**\n'
' * %s_call_%s:\n'
@@ -1219,6 +1264,8 @@ class CodeGenerator:
%(i.name_lower, m.name_lower, i.camel_name))
for a in m.in_args:
self.c.write(' * @%s: Argument to pass with the method invocation.\n'%(a.name))
+ if unix_fd:
+ self.c.write(' * @fd_list: (allow-none): A #GUnixFDList or %NULL.\n')
self.c.write(self.docbook_gen.expand(
' * @cancellable: (allow-none): A #GCancellable or %%NULL.\n'
' * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %%NULL.\n'
@@ -1236,13 +1283,18 @@ class CodeGenerator:
' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name))
for a in m.in_args:
self.c.write(',\n %s%s'%(a.ctype_in, a.name))
+ if unix_fd:
+ self.c.write(',\n GUnixFDList *fd_list')
self.c.write(',\n'
' GCancellable *cancellable,\n'
' GAsyncReadyCallback callback,\n'
' gpointer user_data)\n'
'{\n')
- self.c.write(' g_dbus_proxy_call (G_DBUS_PROXY (proxy),\n'
- ' "%s",\n'
+ if unix_fd:
+ self.c.write(' g_dbus_proxy_call_with_unix_fd_list (G_DBUS_PROXY (proxy),\n')
+ else:
+ self.c.write(' g_dbus_proxy_call (G_DBUS_PROXY (proxy),\n')
+ self.c.write(' "%s",\n'
' g_variant_new ("('%(m.name))
for a in m.in_args:
self.c.write('%s'%(a.format_in))
@@ -1251,8 +1303,10 @@ class CodeGenerator:
self.c.write(',\n %s'%(a.name))
self.c.write('),\n'
' G_DBUS_CALL_FLAGS_NONE,\n'
- ' -1,\n'
- ' cancellable,\n'
+ ' -1,\n')
+ if unix_fd:
+ self.c.write(' fd_list,\n')
+ self.c.write(' cancellable,\n'
' callback,\n'
' user_data);\n')
self.c.write('}\n'
@@ -1264,6 +1318,8 @@ class CodeGenerator:
%(i.name_lower, m.name_lower, i.camel_name))
for a in m.out_args:
self.c.write(' * @out_%s: (out): Return location for return parameter or %%NULL to ignore.\n'%(a.name))
+ if unix_fd:
+ self.c.write(' * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL.\n')
self.c.write(self.docbook_gen.expand(
' * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to %s_call_%s().\n'
' * @error: Return location for error or %%NULL.\n'
@@ -1278,13 +1334,18 @@ class CodeGenerator:
' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name))
for a in m.out_args:
self.c.write(',\n %sout_%s'%(a.ctype_out, a.name))
+ if unix_fd:
+ self.c.write(',\n GUnixFDList **out_fd_list')
self.c.write(',\n'
' GAsyncResult *res,\n'
' GError **error)\n'
'{\n'
- ' GVariant *_ret;\n'
- ' _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);\n'
- ' if (_ret == NULL)\n'
+ ' GVariant *_ret;\n')
+ if unix_fd:
+ self.c.write(' _ret = g_dbus_proxy_call_with_unix_fd_list_finish (G_DBUS_PROXY (proxy), out_fd_list, res, error);\n')
+ else:
+ self.c.write(' _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);\n')
+ self.c.write(' if (_ret == NULL)\n'
' goto _out;\n')
self.c.write(' g_variant_get (_ret,\n'
' \"(')
@@ -1308,8 +1369,12 @@ class CodeGenerator:
%(i.name_lower, m.name_lower, i.camel_name))
for a in m.in_args:
self.c.write(' * @%s: Argument to pass with the method invocation.\n'%(a.name))
+ if unix_fd:
+ self.c.write(' * @fd_list: (allow-none): A #GUnixFDList or %NULL.\n')
for a in m.out_args:
self.c.write(' * @out_%s: (out): Return location for return parameter or %%NULL to ignore.\n'%(a.name))
+ if unix_fd:
+ self.c.write(' * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL.\n')
self.c.write(self.docbook_gen.expand(
' * @cancellable: (allow-none): A #GCancellable or %%NULL.\n'
' * @error: Return location for error or %%NULL.\n'
@@ -1326,15 +1391,22 @@ class CodeGenerator:
' %s *proxy'%(i.name_lower, m.name_lower, i.camel_name))
for a in m.in_args:
self.c.write(',\n %s%s'%(a.ctype_in, a.name))
+ if unix_fd:
+ self.c.write(',\n GUnixFDList *fd_list')
for a in m.out_args:
self.c.write(',\n %sout_%s'%(a.ctype_out, a.name))
+ if unix_fd:
+ self.c.write(',\n GUnixFDList **out_fd_list')
self.c.write(',\n'
' GCancellable *cancellable,\n'
' GError **error)\n'
'{\n'
' GVariant *_ret;\n')
- self.c.write(' _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),\n'
- ' "%s",\n'
+ if unix_fd:
+ self.c.write(' _ret = g_dbus_proxy_call_with_unix_fd_list_sync (G_DBUS_PROXY (proxy),\n')
+ else:
+ self.c.write(' _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),\n')
+ self.c.write(' "%s",\n'
' g_variant_new ("('%(m.name))
for a in m.in_args:
self.c.write('%s'%(a.format_in))
@@ -1343,8 +1415,11 @@ class CodeGenerator:
self.c.write(',\n %s'%(a.name))
self.c.write('),\n'
' G_DBUS_CALL_FLAGS_NONE,\n'
- ' -1,\n'
- ' cancellable,\n'
+ ' -1,\n')
+ if unix_fd:
+ self.c.write(' fd_list,\n'
+ ' out_fd_list,\n')
+ self.c.write(' cancellable,\n'
' error);\n'
' if (_ret == NULL)\n'
' goto _out;\n')
@@ -1366,11 +1441,16 @@ class CodeGenerator:
def generate_method_completers(self, i):
for m in i.methods:
+ unix_fd = False
+ if utils.lookup_annotation(m.annotations, 'org.gtk.GDBus.C.UnixFD'):
+ unix_fd = True
self.c.write('/**\n'
' * %s_complete_%s:\n'
' * @object: A #%s.\n'
' * @invocation: (transfer full): A #GDBusMethodInvocation.\n'
%(i.name_lower, m.name_lower, i.camel_name))
+ if unix_fd:
+ self.c.write (' * @fd_list: (allow-none): A #GUnixFDList or %NULL.\n')
for a in m.out_args:
self.c.write(' * @%s: Parameter to return.\n'%(a.name))
self.c.write(self.docbook_gen.expand(
@@ -1384,20 +1464,29 @@ class CodeGenerator:
'%s_complete_%s (\n'
' %s *object,\n'
' GDBusMethodInvocation *invocation'%(i.name_lower, m.name_lower, i.camel_name))
+ if unix_fd:
+ self.c.write(',\n GUnixFDList *fd_list')
for a in m.out_args:
self.c.write(',\n %s%s'%(a.ctype_in, a.name))
self.c.write(')\n'
'{\n')
- self.c.write(' g_dbus_method_invocation_return_value (invocation,\n'
- ' g_variant_new ("(')
+ if unix_fd:
+ self.c.write(' g_dbus_method_invocation_return_value_with_unix_fd_list (invocation,\n'
+ ' g_variant_new ("(')
+ else:
+ self.c.write(' g_dbus_method_invocation_return_value (invocation,\n'
+ ' g_variant_new ("(')
for a in m.out_args:
self.c.write('%s'%(a.format_in))
self.c.write(')"')
for a in m.out_args:
self.c.write(',\n %s'%(a.name))
- self.c.write('));\n'
- '}\n'
+ if unix_fd:
+ self.c.write('),\n fd_list);\n')
+ else:
+ self.c.write('));\n')
+ self.c.write('}\n'
'\n')
# ---------------------------------------------------------------------------------------------------
@@ -1868,6 +1957,7 @@ class CodeGenerator:
' GVariant *child;\n'
' GValue *paramv;\n'
' guint num_params;\n'
+ ' guint num_extra;\n'
' guint n;\n'
' guint signal_id;\n'
' GValue return_value = {0};\n'
@@ -1876,17 +1966,23 @@ class CodeGenerator:
' g_assert (info != NULL);\n'
%())
self.c.write (' num_params = g_variant_n_children (parameters);\n'
- ' paramv = g_new0 (GValue, num_params + 2);\n'
- ' g_value_init (¶mv[0], %sTYPE_%s);\n'
- ' g_value_set_object (¶mv[0], skeleton);\n'
- ' g_value_init (¶mv[1], G_TYPE_DBUS_METHOD_INVOCATION);\n'
- ' g_value_set_object (¶mv[1], invocation);\n'
+ ' num_extra = info->pass_fdlist ? 3 : 2;'
+ ' paramv = g_new0 (GValue, num_params + num_extra);\n'
+ ' n = 0;\n'
+ ' g_value_init (¶mv[n], %sTYPE_%s);\n'
+ ' g_value_set_object (¶mv[n++], skeleton);\n'
+ ' g_value_init (¶mv[n], G_TYPE_DBUS_METHOD_INVOCATION);\n'
+ ' g_value_set_object (¶mv[n++], invocation);\n'
+ ' if (info->pass_fdlist)\n'
+ ' {\n'
+ ' g_value_init (¶mv[n], G_TYPE_UNIX_FD_LIST);\n'
+ ' g_value_set_object (¶mv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation)));\n'
+ ' }\n'
%(i.ns_upper, i.name_upper))
self.c.write(' g_variant_iter_init (&iter, parameters);\n'
- ' n = 2;\n'
' while ((child = g_variant_iter_next_value (&iter)) != NULL)\n'
' {\n'
- ' _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - 2];\n'
+ ' _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra];\n'
' if (arg_info->use_gvariant)\n'
' {\n'
' g_value_init (¶mv[n], G_TYPE_VARIANT);\n'
@@ -1906,7 +2002,7 @@ class CodeGenerator:
' g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name);\n'
' g_value_unset (&return_value);\n'
)
- self.c.write(' for (n = 0; n < num_params + 2; n++)\n'
+ self.c.write(' for (n = 0; n < num_params + num_extra; n++)\n'
' g_value_unset (¶mv[n]);\n'
' g_free (paramv);\n')
self.c.write('}\n'
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
index fe12408..6aba57f 100644
--- a/gio/gdbusconnection.c
+++ b/gio/gdbusconnection.c
@@ -4901,6 +4901,7 @@ static GVariant *
decode_method_reply (GDBusMessage *reply,
const gchar *method_name,
const GVariantType *reply_type,
+ GUnixFDList **out_fd_list,
GError **error)
{
GVariant *result;
@@ -4934,6 +4935,18 @@ decode_method_reply (GDBusMessage *reply,
g_free (type_string);
result = NULL;
}
+
+#ifdef G_OS_UNIX
+ if (result != NULL)
+ {
+ if (out_fd_list != NULL)
+ {
+ *out_fd_list = g_dbus_message_get_unix_fd_list (reply);
+ if (*out_fd_list != NULL)
+ g_object_ref (*out_fd_list);
+ }
+ }
+#endif
break;
case G_DBUS_MESSAGE_TYPE_ERROR:
@@ -4955,18 +4968,38 @@ typedef struct
GVariantType *reply_type;
gchar *method_name; /* for error message */
guint32 serial;
+
+ GVariant *value;
+#ifdef G_OS_UNIX
+ GUnixFDList *fd_list;
+#endif
} CallState;
static void
+call_state_free (CallState *state)
+{
+ g_variant_type_free (state->reply_type);
+ g_free (state->method_name);
+
+ if (state->value != NULL)
+ g_variant_unref (state->value);
+#ifdef G_OS_UNIX
+ if (state->fd_list != NULL)
+ g_object_unref (state->fd_list);
+#endif
+ g_slice_free (CallState, state);
+}
+
+static void
g_dbus_connection_call_done (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
+ GSimpleAsyncResult *simple;
GDBusConnection *connection = G_DBUS_CONNECTION (source);
CallState *state = user_data;
GError *error;
GDBusMessage *reply;
- GVariant *value;
error = NULL;
reply = g_dbus_connection_send_message_with_reply_finish (connection,
@@ -4994,30 +5027,247 @@ g_dbus_connection_call_done (GObject *source,
_g_dbus_debug_print_unlock ();
}
-
if (reply != NULL)
+ state->value = decode_method_reply (reply, state->method_name, state->reply_type, &state->fd_list, &error);
+
+ simple = state->simple; /* why? because state is freed before we unref simple.. */
+ if (error != NULL)
{
- value = decode_method_reply (reply, state->method_name,
- state->reply_type, &error);
- g_object_unref (reply);
+ g_simple_async_result_take_error (state->simple, error);
+ g_simple_async_result_complete (state->simple);
+ call_state_free (state);
}
else
- value = NULL;
+ {
+ g_simple_async_result_set_op_res_gpointer (state->simple, state, (GDestroyNotify) call_state_free);
+ g_simple_async_result_complete (state->simple);
+ g_object_unref (reply);
+ }
+ g_object_unref (simple);
+}
- if (value == NULL)
- g_simple_async_result_take_error (state->simple, error);
- else
- g_simple_async_result_set_op_res_gpointer (state->simple, value,
- (GDestroyNotify) g_variant_unref);
+static void
+g_dbus_connection_call_internal (GDBusConnection *connection,
+ const gchar *bus_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ const GVariantType *reply_type,
+ GDBusCallFlags flags,
+ gint timeout_msec,
+ GUnixFDList *fd_list,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GDBusMessage *message;
+ CallState *state;
- g_simple_async_result_complete (state->simple);
- g_variant_type_free (state->reply_type);
- g_object_unref (state->simple);
- g_free (state->method_name);
+ g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
+ g_return_if_fail (bus_name == NULL || g_dbus_is_name (bus_name));
+ g_return_if_fail (object_path != NULL && g_variant_is_object_path (object_path));
+ g_return_if_fail (interface_name != NULL && g_dbus_is_interface_name (interface_name));
+ g_return_if_fail (method_name != NULL && g_dbus_is_member_name (method_name));
+ g_return_if_fail (timeout_msec >= 0 || timeout_msec == -1);
+ g_return_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE));
+ g_return_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list));
- g_slice_free (CallState, state);
+ state = g_slice_new0 (CallState);
+ state->simple = g_simple_async_result_new (G_OBJECT (connection),
+ callback, user_data,
+ g_dbus_connection_call_internal);
+ state->method_name = g_strjoin (".", interface_name, method_name, NULL);
+
+ if (reply_type == NULL)
+ reply_type = G_VARIANT_TYPE_ANY;
+
+ state->reply_type = g_variant_type_copy (reply_type);
+
+ message = g_dbus_message_new_method_call (bus_name,
+ object_path,
+ interface_name,
+ method_name);
+ add_call_flags (message, flags);
+ if (parameters != NULL)
+ g_dbus_message_set_body (message, parameters);
+
+#ifdef G_OS_UNIX
+ if (fd_list != NULL)
+ g_dbus_message_set_unix_fd_list (message, fd_list);
+#endif
+
+ g_dbus_connection_send_message_with_reply (connection,
+ message,
+ G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+ timeout_msec,
+ &state->serial,
+ cancellable,
+ g_dbus_connection_call_done,
+ state);
+
+ if (G_UNLIKELY (_g_dbus_debug_call ()))
+ {
+ _g_dbus_debug_print_lock ();
+ g_print ("========================================================================\n"
+ "GDBus-debug:Call:\n"
+ " >>>> ASYNC %s.%s()\n"
+ " on object %s\n"
+ " owned by name %s (serial %d)\n",
+ interface_name,
+ method_name,
+ object_path,
+ bus_name != NULL ? bus_name : "(none)",
+ state->serial);
+ _g_dbus_debug_print_unlock ();
+ }
+
+ if (message != NULL)
+ g_object_unref (message);
+}
+
+static GVariant *
+g_dbus_connection_call_finish_internal (GDBusConnection *connection,
+ GUnixFDList **out_fd_list,
+ GAsyncResult *res,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ CallState *state;
+
+ g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
+ g_return_val_if_fail (g_simple_async_result_is_valid (res, G_OBJECT (connection),
+ g_dbus_connection_call_internal), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ simple = G_SIMPLE_ASYNC_RESULT (res);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return NULL;
+
+ state = g_simple_async_result_get_op_res_gpointer (simple);
+ if (out_fd_list != NULL)
+ *out_fd_list = state->fd_list != NULL ? g_object_ref (state->fd_list) : NULL;
+ return g_variant_ref (state->value);
+}
+
+static GVariant *
+g_dbus_connection_call_sync_internal (GDBusConnection *connection,
+ const gchar *bus_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ const GVariantType *reply_type,
+ GDBusCallFlags flags,
+ gint timeout_msec,
+ GUnixFDList *fd_list,
+ GUnixFDList **out_fd_list,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GDBusMessage *message;
+ GDBusMessage *reply;
+ GVariant *result;
+ GError *local_error;
+
+ message = NULL;
+ reply = NULL;
+ result = NULL;
+
+ g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
+ g_return_val_if_fail (bus_name == NULL || g_dbus_is_name (bus_name), NULL);
+ g_return_val_if_fail (object_path != NULL && g_variant_is_object_path (object_path), NULL);
+ g_return_val_if_fail (interface_name != NULL && g_dbus_is_interface_name (interface_name), NULL);
+ g_return_val_if_fail (method_name != NULL && g_dbus_is_member_name (method_name), NULL);
+ g_return_val_if_fail (timeout_msec >= 0 || timeout_msec == -1, NULL);
+ g_return_val_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), NULL);
+ g_return_val_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ if (reply_type == NULL)
+ reply_type = G_VARIANT_TYPE_ANY;
+
+ message = g_dbus_message_new_method_call (bus_name,
+ object_path,
+ interface_name,
+ method_name);
+ add_call_flags (message, flags);
+ if (parameters != NULL)
+ g_dbus_message_set_body (message, parameters);
+
+#ifdef G_OS_UNIX
+ if (fd_list != NULL)
+ g_dbus_message_set_unix_fd_list (message, fd_list);
+#endif
+
+ if (G_UNLIKELY (_g_dbus_debug_call ()))
+ {
+ _g_dbus_debug_print_lock ();
+ g_print ("========================================================================\n"
+ "GDBus-debug:Call:\n"
+ " >>>> SYNC %s.%s()\n"
+ " on object %s\n"
+ " owned by name %s\n",
+ interface_name,
+ method_name,
+ object_path,
+ bus_name != NULL ? bus_name : "(none)");
+ _g_dbus_debug_print_unlock ();
+ }
+
+ local_error = NULL;
+ reply = g_dbus_connection_send_message_with_reply_sync (connection,
+ message,
+ G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+ timeout_msec,
+ NULL, /* volatile guint32 *out_serial */
+ cancellable,
+ &local_error);
+
+ if (G_UNLIKELY (_g_dbus_debug_call ()))
+ {
+ _g_dbus_debug_print_lock ();
+ g_print ("========================================================================\n"
+ "GDBus-debug:Call:\n"
+ " <<<< SYNC COMPLETE %s.%s()\n"
+ " ",
+ interface_name,
+ method_name);
+ if (reply != NULL)
+ {
+ g_print ("SUCCESS\n");
+ }
+ else
+ {
+ g_print ("FAILED: %s\n",
+ local_error->message);
+ }
+ _g_dbus_debug_print_unlock ();
+ }
+
+ if (reply == NULL)
+ {
+ if (error != NULL)
+ *error = local_error;
+ else
+ g_error_free (local_error);
+ goto out;
+ }
+
+ result = decode_method_reply (reply, method_name, reply_type, out_fd_list, error);
+
+ out:
+ if (message != NULL)
+ g_object_unref (message);
+ if (reply != NULL)
+ g_object_unref (reply);
+
+ return result;
}
+/* ---------------------------------------------------------------------------------------------------- */
+
/**
* g_dbus_connection_call:
* @connection: A #GDBusConnection.
@@ -5094,63 +5344,7 @@ g_dbus_connection_call (GDBusConnection *connection,
GAsyncReadyCallback callback,
gpointer user_data)
{
- GDBusMessage *message;
- CallState *state;
-
- g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
- g_return_if_fail (bus_name == NULL || g_dbus_is_name (bus_name));
- g_return_if_fail (object_path != NULL && g_variant_is_object_path (object_path));
- g_return_if_fail (interface_name != NULL && g_dbus_is_interface_name (interface_name));
- g_return_if_fail (method_name != NULL && g_dbus_is_member_name (method_name));
- g_return_if_fail (timeout_msec >= 0 || timeout_msec == -1);
- g_return_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE));
-
- state = g_slice_new (CallState);
- state->simple = g_simple_async_result_new (G_OBJECT (connection),
- callback, user_data,
- g_dbus_connection_call);
- state->method_name = g_strjoin (".", interface_name, method_name, NULL);
-
- if (reply_type == NULL)
- reply_type = G_VARIANT_TYPE_ANY;
-
- state->reply_type = g_variant_type_copy (reply_type);
-
- message = g_dbus_message_new_method_call (bus_name,
- object_path,
- interface_name,
- method_name);
- add_call_flags (message, flags);
- if (parameters != NULL)
- g_dbus_message_set_body (message, parameters);
-
- g_dbus_connection_send_message_with_reply (connection,
- message,
- G_DBUS_SEND_MESSAGE_FLAGS_NONE,
- timeout_msec,
- &state->serial,
- cancellable,
- g_dbus_connection_call_done,
- state);
-
- if (G_UNLIKELY (_g_dbus_debug_call ()))
- {
- _g_dbus_debug_print_lock ();
- g_print ("========================================================================\n"
- "GDBus-debug:Call:\n"
- " >>>> ASYNC %s.%s()\n"
- " on object %s\n"
- " owned by name %s (serial %d)\n",
- interface_name,
- method_name,
- object_path,
- bus_name != NULL ? bus_name : "(none)",
- state->serial);
- _g_dbus_debug_print_unlock ();
- }
-
- if (message != NULL)
- g_object_unref (message);
+ return g_dbus_connection_call_internal (connection, bus_name, object_path, interface_name, method_name, parameters, reply_type, flags, timeout_msec, NULL, cancellable, callback, user_data);
}
/**
@@ -5171,23 +5365,9 @@ g_dbus_connection_call_finish (GDBusConnection *connection,
GAsyncResult *res,
GError **error)
{
- GSimpleAsyncResult *simple;
-
- g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
- g_return_val_if_fail (g_simple_async_result_is_valid (res, G_OBJECT (connection),
- g_dbus_connection_call), NULL);
- g_return_val_if_fail (error == NULL || *error == NULL, NULL);
-
- simple = G_SIMPLE_ASYNC_RESULT (res);
-
- if (g_simple_async_result_propagate_error (simple, error))
- return NULL;
-
- return g_variant_ref (g_simple_async_result_get_op_res_gpointer (simple));
+ return g_dbus_connection_call_finish_internal (connection, NULL, res, error);
}
-/* ---------------------------------------------------------------------------------------------------- */
-
/**
* g_dbus_connection_call_sync:
* @connection: A #GDBusConnection.
@@ -5259,99 +5439,128 @@ g_dbus_connection_call_sync (GDBusConnection *connection,
GCancellable *cancellable,
GError **error)
{
- GDBusMessage *message;
- GDBusMessage *reply;
- GVariant *result;
- GError *local_error;
-
- message = NULL;
- reply = NULL;
- result = NULL;
-
- g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
- g_return_val_if_fail (bus_name == NULL || g_dbus_is_name (bus_name), NULL);
- g_return_val_if_fail (object_path != NULL && g_variant_is_object_path (object_path), NULL);
- g_return_val_if_fail (interface_name != NULL && g_dbus_is_interface_name (interface_name), NULL);
- g_return_val_if_fail (method_name != NULL && g_dbus_is_member_name (method_name), NULL);
- g_return_val_if_fail (timeout_msec >= 0 || timeout_msec == -1, NULL);
- g_return_val_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), NULL);
-
- if (reply_type == NULL)
- reply_type = G_VARIANT_TYPE_ANY;
-
- message = g_dbus_message_new_method_call (bus_name,
- object_path,
- interface_name,
- method_name);
- add_call_flags (message, flags);
- if (parameters != NULL)
- g_dbus_message_set_body (message, parameters);
-
- if (G_UNLIKELY (_g_dbus_debug_call ()))
- {
- _g_dbus_debug_print_lock ();
- g_print ("========================================================================\n"
- "GDBus-debug:Call:\n"
- " >>>> SYNC %s.%s()\n"
- " on object %s\n"
- " owned by name %s\n",
- interface_name,
- method_name,
- object_path,
- bus_name != NULL ? bus_name : "(none)");
- _g_dbus_debug_print_unlock ();
- }
-
- local_error = NULL;
- reply = g_dbus_connection_send_message_with_reply_sync (connection,
- message,
- G_DBUS_SEND_MESSAGE_FLAGS_NONE,
- timeout_msec,
- NULL, /* volatile guint32 *out_serial */
- cancellable,
- &local_error);
+ return g_dbus_connection_call_sync_internal (connection, bus_name, object_path, interface_name, method_name, parameters, reply_type, flags, timeout_msec, NULL, NULL, cancellable, error);
+}
- if (G_UNLIKELY (_g_dbus_debug_call ()))
- {
- _g_dbus_debug_print_lock ();
- g_print ("========================================================================\n"
- "GDBus-debug:Call:\n"
- " <<<< SYNC COMPLETE %s.%s()\n"
- " ",
- interface_name,
- method_name);
- if (reply != NULL)
- {
- g_print ("SUCCESS\n");
- }
- else
- {
- g_print ("FAILED: %s\n",
- local_error->message);
- }
- _g_dbus_debug_print_unlock ();
- }
+/* ---------------------------------------------------------------------------------------------------- */
- if (reply == NULL)
- {
- if (error != NULL)
- *error = local_error;
- else
- g_error_free (local_error);
- goto out;
- }
+#ifdef G_OS_UNIX
- result = decode_method_reply (reply, method_name, reply_type, error);
+/**
+ * g_dbus_connection_call_with_unix_fd_list:
+ * @connection: A #GDBusConnection.
+ * @bus_name: (allow-none): A unique or well-known bus name or %NULL if
+ * @connection is not a message bus connection.
+ * @object_path: Path of remote object.
+ * @interface_name: D-Bus interface to invoke method on.
+ * @method_name: The name of the method to invoke.
+ * @parameters: (allow-none): A #GVariant tuple with parameters for the method
+ * or %NULL if not passing parameters.
+ * @reply_type: (allow-none): The expected type of the reply, or %NULL.
+ * @flags: Flags from the #GDBusCallFlags enumeration.
+ * @timeout_msec: The timeout in milliseconds, -1 to use the default
+ * timeout or %G_MAXINT for no timeout.
+ * @fd_list: (allow-none): A #GUnixFDList or %NULL.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: (allow-none): A #GAsyncReadyCallback to call when the request is
+ * satisfied or %NULL if you don't * care about the result of the
+ * method invocation.
+ * @user_data: The data to pass to @callback.
+ *
+ * Like g_dbus_connection_call() but also takes a #GUnixFDList object.
+ *
+ * This method is only available on UNIX.
+ *
+ * Since: 2.30
+ */
+void
+g_dbus_connection_call_with_unix_fd_list (GDBusConnection *connection,
+ const gchar *bus_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ const GVariantType *reply_type,
+ GDBusCallFlags flags,
+ gint timeout_msec,
+ GUnixFDList *fd_list,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ return g_dbus_connection_call_internal (connection, bus_name, object_path, interface_name, method_name, parameters, reply_type, flags, timeout_msec, fd_list, cancellable, callback, user_data);
+}
- out:
- if (message != NULL)
- g_object_unref (message);
- if (reply != NULL)
- g_object_unref (reply);
+/**
+ * g_dbus_connection_call_with_unix_fd_list_finish:
+ * @connection: A #GDBusConnection.
+ * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL.
+ * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_connection_call_with_unix_fd_list().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with g_dbus_connection_call_with_unix_fd_list().
+ *
+ * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
+ * return values. Free with g_variant_unref().
+ *
+ * Since: 2.30
+ */
+GVariant *
+g_dbus_connection_call_with_unix_fd_list_finish (GDBusConnection *connection,
+ GUnixFDList **out_fd_list,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_dbus_connection_call_finish_internal (connection, out_fd_list, res, error);
+}
- return result;
+/**
+ * g_dbus_connection_call_with_unix_fd_list_sync:
+ * @connection: A #GDBusConnection.
+ * @bus_name: A unique or well-known bus name.
+ * @object_path: Path of remote object.
+ * @interface_name: D-Bus interface to invoke method on.
+ * @method_name: The name of the method to invoke.
+ * @parameters: (allow-none): A #GVariant tuple with parameters for the method
+ * or %NULL if not passing parameters.
+ * @reply_type: (allow-none): The expected type of the reply, or %NULL.
+ * @flags: Flags from the #GDBusCallFlags enumeration.
+ * @timeout_msec: The timeout in milliseconds, -1 to use the default
+ * timeout or %G_MAXINT for no timeout.
+ * @fd_list: (allow-none): A #GUnixFDList or %NULL.
+ * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Like g_dbus_connection_call_sync() but also takes and returns #GUnixFDList objects.
+ *
+ * This method is only available on UNIX.
+ *
+ * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
+ * return values. Free with g_variant_unref().
+ *
+ * Since: 2.30
+ */
+GVariant *
+g_dbus_connection_call_with_unix_fd_list_sync (GDBusConnection *connection,
+ const gchar *bus_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ const GVariantType *reply_type,
+ GDBusCallFlags flags,
+ gint timeout_msec,
+ GUnixFDList *fd_list,
+ GUnixFDList **out_fd_list,
+ GCancellable *cancellable,
+ GError **error)
+{
+ return g_dbus_connection_call_sync_internal (connection, bus_name, object_path, interface_name, method_name, parameters, reply_type, flags, timeout_msec, fd_list, out_fd_list, cancellable, error);
}
+#endif /* G_OS_UNIX */
+
/* ---------------------------------------------------------------------------------------------------- */
struct ExportedSubtree
diff --git a/gio/gdbusconnection.h b/gio/gdbusconnection.h
index eb3e0f3..ac131dc 100644
--- a/gio/gdbusconnection.h
+++ b/gio/gdbusconnection.h
@@ -181,6 +181,36 @@ GVariant *g_dbus_connection_call_sync (GDBusConnection
gint timeout_msec,
GCancellable *cancellable,
GError **error);
+void g_dbus_connection_call_with_unix_fd_list (GDBusConnection *connection,
+ const gchar *bus_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ const GVariantType *reply_type,
+ GDBusCallFlags flags,
+ gint timeout_msec,
+ GUnixFDList *fd_list,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GVariant *g_dbus_connection_call_with_unix_fd_list_finish (GDBusConnection *connection,
+ GUnixFDList **out_fd_list,
+ GAsyncResult *res,
+ GError **error);
+GVariant *g_dbus_connection_call_with_unix_fd_list_sync (GDBusConnection *connection,
+ const gchar *bus_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ const GVariantType *reply_type,
+ GDBusCallFlags flags,
+ gint timeout_msec,
+ GUnixFDList *fd_list,
+ GUnixFDList **out_fd_list,
+ GCancellable *cancellable,
+ GError **error);
/* ---------------------------------------------------------------------------------------------------- */
diff --git a/gio/gdbusmethodinvocation.c b/gio/gdbusmethodinvocation.c
index 6dd7155..fae234f 100644
--- a/gio/gdbusmethodinvocation.c
+++ b/gio/gdbusmethodinvocation.c
@@ -32,6 +32,10 @@
#include "gdbuserror.h"
#include "gdbusprivate.h"
+#ifdef G_OS_UNIX
+#include "gunixfdlist.h"
+#endif
+
#include "glibintl.h"
/**
@@ -335,23 +339,10 @@ _g_dbus_method_invocation_new (const gchar *sender,
/* ---------------------------------------------------------------------------------------------------- */
-/**
- * g_dbus_method_invocation_return_value:
- * @invocation: (transfer full): A #GDBusMethodInvocation.
- * @parameters: (allow-none): A #GVariant tuple with out parameters for the method or %NULL if not passing any parameters.
- *
- * Finishes handling a D-Bus method call by returning @parameters.
- * If the @parameters GVariant is floating, it is consumed.
- *
- * It is an error if @parameters is not of the right format.
- *
- * This method will free @invocation, you cannot use it afterwards.
- *
- * Since: 2.26
- */
-void
-g_dbus_method_invocation_return_value (GDBusMethodInvocation *invocation,
- GVariant *parameters)
+static void
+g_dbus_method_invocation_return_value_internal (GDBusMethodInvocation *invocation,
+ GVariant *parameters,
+ GUnixFDList *fd_list)
{
GDBusMessage *reply;
GError *error;
@@ -401,6 +392,12 @@ g_dbus_method_invocation_return_value (GDBusMethodInvocation *invocation,
reply = g_dbus_message_new_method_reply (invocation->message);
g_dbus_message_set_body (reply, parameters);
+
+#ifdef G_OS_UNIX
+ if (fd_list != NULL)
+ g_dbus_message_set_unix_fd_list (reply, fd_list);
+#endif
+
error = NULL;
if (!g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error))
{
@@ -413,6 +410,51 @@ g_dbus_method_invocation_return_value (GDBusMethodInvocation *invocation,
g_object_unref (invocation);
}
+/**
+ * g_dbus_method_invocation_return_value:
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ * @parameters: (allow-none): A #GVariant tuple with out parameters for the method or %NULL if not passing any parameters.
+ *
+ * Finishes handling a D-Bus method call by returning @parameters.
+ * If the @parameters GVariant is floating, it is consumed.
+ *
+ * It is an error if @parameters is not of the right format.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ *
+ * Since: 2.26
+ */
+void
+g_dbus_method_invocation_return_value (GDBusMethodInvocation *invocation,
+ GVariant *parameters)
+{
+ return g_dbus_method_invocation_return_value_internal (invocation, parameters, NULL);
+}
+
+#ifdef G_OS_UNIX
+/**
+ * g_dbus_method_invocation_return_value_with_unix_fd_list:
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ * @parameters: (allow-none): A #GVariant tuple with out parameters for the method or %NULL if not passing any parameters.
+ * @fd_list: (allow-none): A #GUnixFDList or %NULL.
+ *
+ * Like g_dbus_method_invocation_return_value() but also takes a #GUnixFDList.
+ *
+ * This method is only available on UNIX.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ *
+ * Since: 2.30
+ */
+void
+g_dbus_method_invocation_return_value_with_unix_fd_list (GDBusMethodInvocation *invocation,
+ GVariant *parameters,
+ GUnixFDList *fd_list)
+{
+ return g_dbus_method_invocation_return_value_internal (invocation, parameters, fd_list);
+}
+#endif
+
/* ---------------------------------------------------------------------------------------------------- */
/**
diff --git a/gio/gdbusmethodinvocation.h b/gio/gdbusmethodinvocation.h
index 8b8d050..b1a87ac 100644
--- a/gio/gdbusmethodinvocation.h
+++ b/gio/gdbusmethodinvocation.h
@@ -48,6 +48,9 @@ gpointer g_dbus_method_invocation_get_user_data (GDBusMetho
void g_dbus_method_invocation_return_value (GDBusMethodInvocation *invocation,
GVariant *parameters);
+void g_dbus_method_invocation_return_value_with_unix_fd_list (GDBusMethodInvocation *invocation,
+ GVariant *parameters,
+ GUnixFDList *fd_list);
void g_dbus_method_invocation_return_error (GDBusMethodInvocation *invocation,
GQuark domain,
gint code,
diff --git a/gio/gdbusproxy.c b/gio/gdbusproxy.c
index 73359dc..cc77bb9 100644
--- a/gio/gdbusproxy.c
+++ b/gio/gdbusproxy.c
@@ -39,6 +39,10 @@
#include "gcancellable.h"
#include "gdbusinterface.h"
+#ifdef G_OS_UNIX
+#include "gunixfdlist.h"
+#endif
+
#include "glibintl.h"
/**
@@ -2325,6 +2329,24 @@ maybe_split_method_name (const gchar *method_name,
return was_split;
}
+typedef struct
+{
+ GVariant *value;
+#ifdef G_OS_UNIX
+ GUnixFDList *fd_list;
+#endif
+} ReplyData;
+
+static void
+reply_data_free (ReplyData *data)
+{
+ g_variant_unref (data->value);
+#ifdef G_OS_UNIX
+ if (data->fd_list != NULL)
+ g_object_unref (data->fd_list);
+#endif
+ g_slice_free (ReplyData, data);
+}
static void
reply_cb (GDBusConnection *connection,
@@ -2334,20 +2356,34 @@ reply_cb (GDBusConnection *connection,
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
GVariant *value;
GError *error;
+#ifdef G_OS_UNIX
+ GUnixFDList *fd_list;
+#endif
error = NULL;
+#ifdef G_OS_UNIX
+ value = g_dbus_connection_call_with_unix_fd_list_finish (connection,
+ &fd_list,
+ res,
+ &error);
+#else
value = g_dbus_connection_call_finish (connection,
res,
&error);
+#endif
if (error != NULL)
{
g_simple_async_result_take_error (simple, error);
}
else
{
- g_simple_async_result_set_op_res_gpointer (simple,
- value,
- (GDestroyNotify) g_variant_unref);
+ ReplyData *data;
+ data = g_slice_new0 (ReplyData);
+ data->value = value;
+#ifdef G_OS_UNIX
+ data->fd_list = fd_list;
+#endif
+ g_simple_async_result_set_op_res_gpointer (simple, data, (GDestroyNotify) reply_data_free);
}
/* no need to complete in idle since the method GDBusConnection already does */
@@ -2399,66 +2435,18 @@ get_destination_for_call (GDBusProxy *proxy)
return ret;
}
-/**
- * g_dbus_proxy_call:
- * @proxy: A #GDBusProxy.
- * @method_name: Name of method to invoke.
- * @parameters: (allow-none): A #GVariant tuple with parameters for the signal or %NULL if not passing parameters.
- * @flags: Flags from the #GDBusCallFlags enumeration.
- * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning
- * "infinite") or -1 to use the proxy default timeout.
- * @cancellable: A #GCancellable or %NULL.
- * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL if you don't
- * care about the result of the method invocation.
- * @user_data: The data to pass to @callback.
- *
- * Asynchronously invokes the @method_name method on @proxy.
- *
- * If @method_name contains any dots, then @name is split into interface and
- * method name parts. This allows using @proxy for invoking methods on
- * other interfaces.
- *
- * If the #GDBusConnection associated with @proxy is closed then
- * the operation will fail with %G_IO_ERROR_CLOSED. If
- * @cancellable is canceled, the operation will fail with
- * %G_IO_ERROR_CANCELLED. If @parameters contains a value not
- * compatible with the D-Bus protocol, the operation fails with
- * %G_IO_ERROR_INVALID_ARGUMENT.
- *
- * If the @parameters #GVariant is floating, it is consumed. This allows
- * convenient 'inline' use of g_variant_new(), e.g.:
- * |[
- * g_dbus_proxy_call (proxy,
- * "TwoStrings",
- * g_variant_new ("(ss)",
- * "Thing One",
- * "Thing Two"),
- * G_DBUS_CALL_FLAGS_NONE,
- * -1,
- * NULL,
- * (GAsyncReadyCallback) two_strings_done,
- * &data);
- * ]|
- *
- * This is an asynchronous method. When the operation is finished,
- * @callback will be invoked in the
- * <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
- * of the thread you are calling this method from.
- * You can then call g_dbus_proxy_call_finish() to get the result of
- * the operation. See g_dbus_proxy_call_sync() for the synchronous
- * version of this method.
- *
- * Since: 2.26
- */
-void
-g_dbus_proxy_call (GDBusProxy *proxy,
- const gchar *method_name,
- GVariant *parameters,
- GDBusCallFlags flags,
- gint timeout_msec,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+g_dbus_proxy_call_internal (GDBusProxy *proxy,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusCallFlags flags,
+ gint timeout_msec,
+ GUnixFDList *fd_list,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
GSimpleAsyncResult *simple;
gboolean was_split;
@@ -2473,6 +2461,7 @@ g_dbus_proxy_call (GDBusProxy *proxy,
g_return_if_fail (g_dbus_is_member_name (method_name) || g_dbus_is_interface_name (method_name));
g_return_if_fail (parameters == NULL || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE));
g_return_if_fail (timeout_msec == -1 || timeout_msec >= 0);
+ g_return_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list));
reply_type = NULL;
split_interface_name = NULL;
@@ -2480,7 +2469,7 @@ g_dbus_proxy_call (GDBusProxy *proxy,
simple = g_simple_async_result_new (G_OBJECT (proxy),
callback,
user_data,
- g_dbus_proxy_call);
+ g_dbus_proxy_call_internal);
was_split = maybe_split_method_name (method_name, &split_interface_name, &split_method_name);
target_method_name = was_split ? split_method_name : method_name;
@@ -2509,6 +2498,21 @@ g_dbus_proxy_call (GDBusProxy *proxy,
}
}
+#ifdef G_OS_UNIX
+ g_dbus_connection_call_with_unix_fd_list (proxy->priv->connection,
+ destination,
+ proxy->priv->object_path,
+ target_interface_name,
+ target_method_name,
+ parameters,
+ reply_type,
+ flags,
+ timeout_msec == -1 ? proxy->priv->timeout_msec : timeout_msec,
+ fd_list,
+ cancellable,
+ (GAsyncReadyCallback) reply_cb,
+ simple);
+#else
g_dbus_connection_call (proxy->priv->connection,
destination,
proxy->priv->object_path,
@@ -2521,6 +2525,7 @@ g_dbus_proxy_call (GDBusProxy *proxy,
cancellable,
(GAsyncReadyCallback) reply_cb,
simple);
+#endif
out:
if (reply_type != NULL)
@@ -2529,100 +2534,48 @@ g_dbus_proxy_call (GDBusProxy *proxy,
g_free (split_interface_name);
}
-/**
- * g_dbus_proxy_call_finish:
- * @proxy: A #GDBusProxy.
- * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_proxy_call().
- * @error: Return location for error or %NULL.
- *
- * Finishes an operation started with g_dbus_proxy_call().
- *
- * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
- * return values. Free with g_variant_unref().
- *
- * Since: 2.26
- */
-GVariant *
-g_dbus_proxy_call_finish (GDBusProxy *proxy,
- GAsyncResult *res,
- GError **error)
+static GVariant *
+g_dbus_proxy_call_finish_internal (GDBusProxy *proxy,
+ GUnixFDList **out_fd_list,
+ GAsyncResult *res,
+ GError **error)
{
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
GVariant *value;
+ ReplyData *data;
g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), NULL);
g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
- g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_dbus_proxy_call);
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_dbus_proxy_call_internal);
value = NULL;
if (g_simple_async_result_propagate_error (simple, error))
goto out;
- value = g_variant_ref (g_simple_async_result_get_op_res_gpointer (simple));
+ data = g_simple_async_result_get_op_res_gpointer (simple);
+ value = g_variant_ref (data->value);
+#ifdef G_OS_UNIX
+ if (out_fd_list != NULL)
+ *out_fd_list = data->fd_list != NULL ? g_object_ref (data->fd_list) : NULL;
+#endif
out:
return value;
}
-/**
- * g_dbus_proxy_call_sync:
- * @proxy: A #GDBusProxy.
- * @method_name: Name of method to invoke.
- * @parameters: (allow-none): A #GVariant tuple with parameters for the signal
- * or %NULL if not passing parameters.
- * @flags: Flags from the #GDBusCallFlags enumeration.
- * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning
- * "infinite") or -1 to use the proxy default timeout.
- * @cancellable: A #GCancellable or %NULL.
- * @error: Return location for error or %NULL.
- *
- * Synchronously invokes the @method_name method on @proxy.
- *
- * If @method_name contains any dots, then @name is split into interface and
- * method name parts. This allows using @proxy for invoking methods on
- * other interfaces.
- *
- * If the #GDBusConnection associated with @proxy is disconnected then
- * the operation will fail with %G_IO_ERROR_CLOSED. If
- * @cancellable is canceled, the operation will fail with
- * %G_IO_ERROR_CANCELLED. If @parameters contains a value not
- * compatible with the D-Bus protocol, the operation fails with
- * %G_IO_ERROR_INVALID_ARGUMENT.
- *
- * If the @parameters #GVariant is floating, it is consumed. This allows
- * convenient 'inline' use of g_variant_new(), e.g.:
- * |[
- * g_dbus_proxy_call_sync (proxy,
- * "TwoStrings",
- * g_variant_new ("(ss)",
- * "Thing One",
- * "Thing Two"),
- * G_DBUS_CALL_FLAGS_NONE,
- * -1,
- * NULL,
- * &error);
- * ]|
- *
- * The calling thread is blocked until a reply is received. See
- * g_dbus_proxy_call() for the asynchronous version of this
- * method.
- *
- * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
- * return values. Free with g_variant_unref().
- *
- * Since: 2.26
- */
-GVariant *
-g_dbus_proxy_call_sync (GDBusProxy *proxy,
- const gchar *method_name,
- GVariant *parameters,
- GDBusCallFlags flags,
- gint timeout_msec,
- GCancellable *cancellable,
- GError **error)
+static GVariant *
+g_dbus_proxy_call_sync_internal (GDBusProxy *proxy,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusCallFlags flags,
+ gint timeout_msec,
+ GUnixFDList *fd_list,
+ GUnixFDList **out_fd_list,
+ GCancellable *cancellable,
+ GError **error)
{
GVariant *ret;
gboolean was_split;
@@ -2637,6 +2590,7 @@ g_dbus_proxy_call_sync (GDBusProxy *proxy,
g_return_val_if_fail (g_dbus_is_member_name (method_name) || g_dbus_is_interface_name (method_name), NULL);
g_return_val_if_fail (parameters == NULL || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), NULL);
g_return_val_if_fail (timeout_msec == -1 || timeout_msec >= 0, NULL);
+ g_return_val_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
reply_type = NULL;
@@ -2669,6 +2623,21 @@ g_dbus_proxy_call_sync (GDBusProxy *proxy,
}
}
+#ifdef G_OS_UNIX
+ ret = g_dbus_connection_call_with_unix_fd_list_sync (proxy->priv->connection,
+ destination,
+ proxy->priv->object_path,
+ target_interface_name,
+ target_method_name,
+ parameters,
+ reply_type,
+ flags,
+ timeout_msec == -1 ? proxy->priv->timeout_msec : timeout_msec,
+ fd_list,
+ out_fd_list,
+ cancellable,
+ error);
+#else
ret = g_dbus_connection_call_sync (proxy->priv->connection,
destination,
proxy->priv->object_path,
@@ -2680,6 +2649,7 @@ g_dbus_proxy_call_sync (GDBusProxy *proxy,
timeout_msec == -1 ? proxy->priv->timeout_msec : timeout_msec,
cancellable,
error);
+#endif
out:
if (reply_type != NULL)
@@ -2692,6 +2662,253 @@ g_dbus_proxy_call_sync (GDBusProxy *proxy,
/* ---------------------------------------------------------------------------------------------------- */
+/**
+ * g_dbus_proxy_call:
+ * @proxy: A #GDBusProxy.
+ * @method_name: Name of method to invoke.
+ * @parameters: (allow-none): A #GVariant tuple with parameters for the signal or %NULL if not passing parameters.
+ * @flags: Flags from the #GDBusCallFlags enumeration.
+ * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning
+ * "infinite") or -1 to use the proxy default timeout.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL if you don't
+ * care about the result of the method invocation.
+ * @user_data: The data to pass to @callback.
+ *
+ * Asynchronously invokes the @method_name method on @proxy.
+ *
+ * If @method_name contains any dots, then @name is split into interface and
+ * method name parts. This allows using @proxy for invoking methods on
+ * other interfaces.
+ *
+ * If the #GDBusConnection associated with @proxy is closed then
+ * the operation will fail with %G_IO_ERROR_CLOSED. If
+ * @cancellable is canceled, the operation will fail with
+ * %G_IO_ERROR_CANCELLED. If @parameters contains a value not
+ * compatible with the D-Bus protocol, the operation fails with
+ * %G_IO_ERROR_INVALID_ARGUMENT.
+ *
+ * If the @parameters #GVariant is floating, it is consumed. This allows
+ * convenient 'inline' use of g_variant_new(), e.g.:
+ * |[
+ * g_dbus_proxy_call (proxy,
+ * "TwoStrings",
+ * g_variant_new ("(ss)",
+ * "Thing One",
+ * "Thing Two"),
+ * G_DBUS_CALL_FLAGS_NONE,
+ * -1,
+ * NULL,
+ * (GAsyncReadyCallback) two_strings_done,
+ * &data);
+ * ]|
+ *
+ * This is an asynchronous method. When the operation is finished,
+ * @callback will be invoked in the
+ * <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
+ * of the thread you are calling this method from.
+ * You can then call g_dbus_proxy_call_finish() to get the result of
+ * the operation. See g_dbus_proxy_call_sync() for the synchronous
+ * version of this method.
+ *
+ * Since: 2.26
+ */
+void
+g_dbus_proxy_call (GDBusProxy *proxy,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusCallFlags flags,
+ gint timeout_msec,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ return g_dbus_proxy_call_internal (proxy, method_name, parameters, flags, timeout_msec, NULL, cancellable, callback, user_data);
+}
+
+/**
+ * g_dbus_proxy_call_finish:
+ * @proxy: A #GDBusProxy.
+ * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_proxy_call().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with g_dbus_proxy_call().
+ *
+ * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
+ * return values. Free with g_variant_unref().
+ *
+ * Since: 2.26
+ */
+GVariant *
+g_dbus_proxy_call_finish (GDBusProxy *proxy,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_dbus_proxy_call_finish_internal (proxy, NULL, res, error);
+}
+
+/**
+ * g_dbus_proxy_call_sync:
+ * @proxy: A #GDBusProxy.
+ * @method_name: Name of method to invoke.
+ * @parameters: (allow-none): A #GVariant tuple with parameters for the signal
+ * or %NULL if not passing parameters.
+ * @flags: Flags from the #GDBusCallFlags enumeration.
+ * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning
+ * "infinite") or -1 to use the proxy default timeout.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the @method_name method on @proxy.
+ *
+ * If @method_name contains any dots, then @name is split into interface and
+ * method name parts. This allows using @proxy for invoking methods on
+ * other interfaces.
+ *
+ * If the #GDBusConnection associated with @proxy is disconnected then
+ * the operation will fail with %G_IO_ERROR_CLOSED. If
+ * @cancellable is canceled, the operation will fail with
+ * %G_IO_ERROR_CANCELLED. If @parameters contains a value not
+ * compatible with the D-Bus protocol, the operation fails with
+ * %G_IO_ERROR_INVALID_ARGUMENT.
+ *
+ * If the @parameters #GVariant is floating, it is consumed. This allows
+ * convenient 'inline' use of g_variant_new(), e.g.:
+ * |[
+ * g_dbus_proxy_call_sync (proxy,
+ * "TwoStrings",
+ * g_variant_new ("(ss)",
+ * "Thing One",
+ * "Thing Two"),
+ * G_DBUS_CALL_FLAGS_NONE,
+ * -1,
+ * NULL,
+ * &error);
+ * ]|
+ *
+ * The calling thread is blocked until a reply is received. See
+ * g_dbus_proxy_call() for the asynchronous version of this
+ * method.
+ *
+ * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
+ * return values. Free with g_variant_unref().
+ *
+ * Since: 2.26
+ */
+GVariant *
+g_dbus_proxy_call_sync (GDBusProxy *proxy,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusCallFlags flags,
+ gint timeout_msec,
+ GCancellable *cancellable,
+ GError **error)
+{
+ return g_dbus_proxy_call_sync_internal (proxy, method_name, parameters, flags, timeout_msec, NULL, NULL, cancellable, error);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+#ifdef G_OS_UNIX
+
+/**
+ * g_dbus_proxy_call_with_unix_fd_list:
+ * @proxy: A #GDBusProxy.
+ * @method_name: Name of method to invoke.
+ * @parameters: (allow-none): A #GVariant tuple with parameters for the signal or %NULL if not passing parameters.
+ * @flags: Flags from the #GDBusCallFlags enumeration.
+ * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning
+ * "infinite") or -1 to use the proxy default timeout.
+ * @fd_list: (allow-none): A #GUnixFDList or %NULL.
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL if you don't
+ * care about the result of the method invocation.
+ * @user_data: The data to pass to @callback.
+ *
+ * Like g_dbus_proxy_call() but also takes a #GUnixFDList object.
+ *
+ * This method is only available on UNIX.
+ *
+ * Since: 2.30
+ */
+void
+g_dbus_proxy_call_with_unix_fd_list (GDBusProxy *proxy,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusCallFlags flags,
+ gint timeout_msec,
+ GUnixFDList *fd_list,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ return g_dbus_proxy_call_internal (proxy, method_name, parameters, flags, timeout_msec, fd_list, cancellable, callback, user_data);
+}
+
+/**
+ * g_dbus_proxy_call_with_unix_fd_list_finish:
+ * @proxy: A #GDBusProxy.
+ * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL.
+ * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_proxy_call_with_unix_fd_list().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with g_dbus_proxy_call_with_unix_fd_list().
+ *
+ * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
+ * return values. Free with g_variant_unref().
+ *
+ * Since: 2.30
+ */
+GVariant *
+g_dbus_proxy_call_with_unix_fd_list_finish (GDBusProxy *proxy,
+ GUnixFDList **out_fd_list,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_dbus_proxy_call_finish_internal (proxy, out_fd_list, res, error);
+}
+
+/**
+ * g_dbus_proxy_call_with_unix_fd_list_sync:
+ * @proxy: A #GDBusProxy.
+ * @method_name: Name of method to invoke.
+ * @parameters: (allow-none): A #GVariant tuple with parameters for the signal
+ * or %NULL if not passing parameters.
+ * @flags: Flags from the #GDBusCallFlags enumeration.
+ * @timeout_msec: The timeout in milliseconds (with %G_MAXINT meaning
+ * "infinite") or -1 to use the proxy default timeout.
+ * @fd_list: (allow-none): A #GUnixFDList or %NULL.
+ * @out_fd_list: (out): Return location for a #GUnixFDList or %NULL.
+ * @cancellable: A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Like g_dbus_proxy_call_sync() but also takes and returns #GUnixFDList objects.
+ *
+ * This method is only available on UNIX.
+ *
+ * Returns: %NULL if @error is set. Otherwise a #GVariant tuple with
+ * return values. Free with g_variant_unref().
+ *
+ * Since: 2.30
+ */
+GVariant *
+g_dbus_proxy_call_with_unix_fd_list_sync (GDBusProxy *proxy,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusCallFlags flags,
+ gint timeout_msec,
+ GUnixFDList *fd_list,
+ GUnixFDList **out_fd_list,
+ GCancellable *cancellable,
+ GError **error)
+{
+ return g_dbus_proxy_call_sync_internal (proxy, method_name, parameters, flags, timeout_msec, fd_list, out_fd_list, cancellable, error);
+}
+
+#endif /* G_OS_UNIX */
+
+/* ---------------------------------------------------------------------------------------------------- */
+
static GDBusInterfaceInfo *
_g_dbus_proxy_get_info (GDBusInterface *interface)
{
diff --git a/gio/gdbusproxy.h b/gio/gdbusproxy.h
index d9858c1..1e920d3 100644
--- a/gio/gdbusproxy.h
+++ b/gio/gdbusproxy.h
@@ -162,6 +162,29 @@ GVariant *g_dbus_proxy_call_sync (GDBusProxy *pr
GCancellable *cancellable,
GError **error);
+void g_dbus_proxy_call_with_unix_fd_list (GDBusProxy *proxy,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusCallFlags flags,
+ gint timeout_msec,
+ GUnixFDList *fd_list,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GVariant *g_dbus_proxy_call_with_unix_fd_list_finish (GDBusProxy *proxy,
+ GUnixFDList **out_fd_list,
+ GAsyncResult *res,
+ GError **error);
+GVariant *g_dbus_proxy_call_with_unix_fd_list_sync (GDBusProxy *proxy,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusCallFlags flags,
+ gint timeout_msec,
+ GUnixFDList *fd_list,
+ GUnixFDList **out_fd_list,
+ GCancellable *cancellable,
+ GError **error);
+
G_END_DECLS
#endif /* __G_DBUS_PROXY_H__ */
diff --git a/gio/gio.symbols b/gio/gio.symbols
index 00d5328..e5f96e9 100644
--- a/gio/gio.symbols
+++ b/gio/gio.symbols
@@ -1036,6 +1036,13 @@ g_unix_fd_message_new
g_unix_fd_message_steal_fds
g_unix_fd_message_get_fd_list
g_unix_fd_message_new_with_fd_list
+g_dbus_connection_call_with_unix_fd_list
+g_dbus_connection_call_with_unix_fd_list_finish
+g_dbus_connection_call_with_unix_fd_list_sync
+g_dbus_proxy_call_with_unix_fd_list
+g_dbus_proxy_call_with_unix_fd_list_finish
+g_dbus_proxy_call_with_unix_fd_list_sync
+g_dbus_method_invocation_return_value_with_unix_fd_list
#endif
#ifndef G_OS_WIN32
g_unix_fd_list_append
diff --git a/gio/tests/test-codegen.xml b/gio/tests/test-codegen.xml
index 8b8cac2..b78def0 100644
--- a/gio/tests/test-codegen.xml
+++ b/gio/tests/test-codegen.xml
@@ -467,4 +467,12 @@
</interface>
<unknownTag/>
+ <interface name="FDPassing">
+ <method name="HelloFD">
+ <annotation name="org.gtk.GDBus.C.UnixFD" value="1"/>
+ <arg name="greeting" direction="in" type="s"/>
+ <arg name="response" direction="out" type="s"/>
+ </method>
+ </interface>
+
</node>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]