From e32d58f4d3ad30feb3b06c5dce4549fbb3d14c13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 20 Jan 2021 15:36:29 +0400 Subject: [PATCH 1/8] gio: add G_SOCKET_FAMILY_VSOCK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The VSOCK address family facilitates communication between virtual machines and the host they are running on. It's primarily used on Linux, but can be made available to other systems (for example, see https://github.com/virtio-win/kvm-guest-drivers-windows/issues/534). Signed-off-by: Marc-André Lureau --- docs/reference/glib/glib-sections.txt | 1 + gio/gioenums.h | 8 +++++--- gio/gnetworkaddress.c | 1 + glib/glibconfig.h.in | 1 + meson.build | 24 ++++++++++++++++++++++++ 5 files changed, 32 insertions(+), 3 deletions(-) diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index d20f419afa..fb31280930 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -922,6 +922,7 @@ GLIB_SYSDEF_POLLPRI GLIB_SYSDEF_AF_INET GLIB_SYSDEF_AF_INET6 GLIB_SYSDEF_AF_UNIX +GLIB_SYSDEF_AF_VSOCK GLIB_SYSDEF_MSG_DONTROUTE GLIB_SYSDEF_MSG_OOB GLIB_SYSDEF_MSG_PEEK diff --git a/gio/gioenums.h b/gio/gioenums.h index 2692b746d7..f60740ce30 100644 --- a/gio/gioenums.h +++ b/gio/gioenums.h @@ -812,10 +812,11 @@ typedef enum /*< flags >*/ { * @G_SOCKET_FAMILY_IPV4: the IPv4 family * @G_SOCKET_FAMILY_IPV6: the IPv6 family * @G_SOCKET_FAMILY_UNIX: the UNIX domain family + * @G_SOCKET_FAMILY_VSOCK: the VSOCK domain family. Since: 2.68 * * The protocol family of a #GSocketAddress. (These values are - * identical to the system defines %AF_INET, %AF_INET6 and %AF_UNIX, - * if available.) + * identical to the system defines %AF_INET, %AF_INET6, %AF_UNIX, + * and %AF_VSOCK if available.) * * Since: 2.22 */ @@ -823,7 +824,8 @@ typedef enum { G_SOCKET_FAMILY_INVALID, G_SOCKET_FAMILY_UNIX = GLIB_SYSDEF_AF_UNIX, G_SOCKET_FAMILY_IPV4 = GLIB_SYSDEF_AF_INET, - G_SOCKET_FAMILY_IPV6 = GLIB_SYSDEF_AF_INET6 + G_SOCKET_FAMILY_IPV6 = GLIB_SYSDEF_AF_INET6, + G_SOCKET_FAMILY_VSOCK = GLIB_SYSDEF_AF_VSOCK } GSocketFamily; /** diff --git a/gio/gnetworkaddress.c b/gio/gnetworkaddress.c index ef1940a920..baf1d5e2af 100644 --- a/gio/gnetworkaddress.c +++ b/gio/gnetworkaddress.c @@ -702,6 +702,7 @@ list_split_families (GList *list, break; case G_SOCKET_FAMILY_INVALID: case G_SOCKET_FAMILY_UNIX: + case G_SOCKET_FAMILY_VSOCK: g_assert_not_reached (); } diff --git a/glib/glibconfig.h.in b/glib/glibconfig.h.in index 873cb03142..613f1be17a 100644 --- a/glib/glibconfig.h.in +++ b/glib/glibconfig.h.in @@ -193,6 +193,7 @@ typedef @g_pid_type@ GPid; #define GLIB_SYSDEF_AF_UNIX @g_af_unix@ #define GLIB_SYSDEF_AF_INET @g_af_inet@ #define GLIB_SYSDEF_AF_INET6 @g_af_inet6@ +#define GLIB_SYSDEF_AF_VSOCK @g_af_vsock@ #define GLIB_SYSDEF_MSG_OOB @g_msg_oob@ #define GLIB_SYSDEF_MSG_PEEK @g_msg_peek@ diff --git a/meson.build b/meson.build index d7d64118d7..f66c7f0f18 100644 --- a/meson.build +++ b/meson.build @@ -333,6 +333,9 @@ endif if cc.has_header('linux/netlink.h') glib_conf.set('HAVE_NETLINK', 1) endif +if cc.has_header('linux/vm_sockets.h') + glib_conf.set('HAVE_VSOCK', 1) +endif # Is statx() supported? Android systems don’t reliably support it as of August 2020. statx_code = ''' @@ -1761,6 +1764,27 @@ inet_defines = [ [ 'MSG_PEEK', 'g_msg_peek' ], [ 'MSG_DONTROUTE', 'g_msg_dontroute' ], ] + +if glib_conf.has('HAVE_VSOCK') + vsock_defines = [ + [ 'VMADDR_CID_ANY', '-1U' ], + [ 'VMADDR_PORT_ANY', '-1U' ], + [ 'VMADDR_CID_HYPERVISOR', '0' ], + [ 'VMADDR_CID_LOCAL', '1' ], + [ 'VMADDR_CID_HOST', '2' ], + ] + foreach d : vsock_defines + if not cc.has_header_symbol('linux/vm_sockets.h', d[0], prefix: inet_includes) + glib_conf.set(d[0], d[1]) + endif + endforeach + inet_defines += [ [ 'AF_VSOCK', 'g_af_vsock' ] ] + inet_includes += ''' + #include ''' +else + glibconfig_conf.set('g_af_vsock', '-1') +endif + foreach d : inet_defines val = cc.compute_int(d[0], prefix: inet_includes) glibconfig_conf.set(d[1], val) -- GitLab From 9a754f264db2580bfb9f4f37c752c6af81a68dc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 20 Jan 2021 16:42:31 +0400 Subject: [PATCH 2/8] gio: get VSOCK details from fd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the same code path as AF_UNIX. Signed-off-by: Marc-André Lureau --- gio/gsocket.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gio/gsocket.c b/gio/gsocket.c index 52a198378c..c0252b5781 100644 --- a/gio/gsocket.c +++ b/gio/gsocket.c @@ -540,8 +540,9 @@ g_socket_details_from_fd (GSocket *socket) } break; + case G_SOCKET_FAMILY_VSOCK: case G_SOCKET_FAMILY_UNIX: - socket->priv->family = G_SOCKET_FAMILY_UNIX; + socket->priv->family = family; socket->priv->protocol = G_SOCKET_PROTOCOL_DEFAULT; break; -- GitLab From 4b8ee646ef9d614a4c0ea5597350a8c91eec5777 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 20 Jan 2021 17:03:16 +0400 Subject: [PATCH 3/8] gio: add GVsockConnection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau --- docs/reference/gio/gio-docs.xml | 1 + docs/reference/gio/gio-sections-common.txt | 18 +++++++ gio/gio.h | 1 + gio/gsocketconnection.c | 4 ++ gio/gvsockconnection.c | 55 +++++++++++++++++++ gio/gvsockconnection.h | 63 ++++++++++++++++++++++ gio/meson.build | 2 + 7 files changed, 144 insertions(+) create mode 100644 gio/gvsockconnection.c create mode 100644 gio/gvsockconnection.h diff --git a/docs/reference/gio/gio-docs.xml b/docs/reference/gio/gio-docs.xml index 9cd3d0e39f..e2fe61c8cc 100644 --- a/docs/reference/gio/gio-docs.xml +++ b/docs/reference/gio/gio-docs.xml @@ -139,6 +139,7 @@ + diff --git a/docs/reference/gio/gio-sections-common.txt b/docs/reference/gio/gio-sections-common.txt index 945c26adea..634089a48a 100644 --- a/docs/reference/gio/gio-sections-common.txt +++ b/docs/reference/gio/gio-sections-common.txt @@ -2266,6 +2266,24 @@ GUnixConnectionPrivate g_unix_connection_get_type +
+gvsockconnection +GVsockConnection +GVsockConnection + +GVsockConnectionClass +G_IS_VSOCK_CONNECTION +G_IS_VSOCK_CONNECTION_CLASS +G_TYPE_VSOCK_CONNECTION +G_VSOCK_CONNECTION +G_VSOCK_CONNECTION_CLASS +G_VSOCK_CONNECTION_GET_CLASS + +GVsockConnectionPrivate +g_vsock_connection_get_type +
+ +GUnixConnection
gtcpconnection GTcpConnection diff --git a/gio/gio.h b/gio/gio.h index f5d2dd5a36..3b70e45b95 100644 --- a/gio/gio.h +++ b/gio/gio.h @@ -167,6 +167,7 @@ #include #include #include +#include #include #include diff --git a/gio/gsocketconnection.c b/gio/gsocketconnection.c index 37d5d330cf..36c4d3ee4c 100644 --- a/gio/gsocketconnection.c +++ b/gio/gsocketconnection.c @@ -34,6 +34,7 @@ #include #include "gunixconnection.h" #include "gtcpconnection.h" +#include "gvsockconnection.h" #include "glibintl.h" @@ -615,6 +616,9 @@ g_socket_connection_factory_register_type (GType g_type, static void init_builtin_types (void) { +#ifdef HAVE_VSOCK + g_type_ensure (G_TYPE_VSOCK_CONNECTION); +#endif #ifndef G_OS_WIN32 g_type_ensure (G_TYPE_UNIX_CONNECTION); #endif diff --git a/gio/gvsockconnection.c b/gio/gvsockconnection.c new file mode 100644 index 0000000000..3db53cce09 --- /dev/null +++ b/gio/gvsockconnection.c @@ -0,0 +1,55 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright © 2021 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * See the included COPYING file for more information. + * + * Authors: Marc-André Lureau + */ + +#include "config.h" + +#include "gvsockconnection.h" + +/** + * SECTION:gvsockconnection + * @title: GVsockConnection + * @short_description: A VSOCK domain GSocketConnection + * @include: gio/gvsockconnection.h + * @see_also: #GSocketConnection. + * + * This is the subclass of #GSocketConnection that is created + * for VSOCK domain sockets. + * + * Since: 2.68 + */ + +/** + * GVsockConnection: + * + * #GVsockConnection is an opaque data structure. + **/ + +G_DEFINE_TYPE_WITH_CODE (GVsockConnection, + g_vsock_connection, + G_TYPE_SOCKET_CONNECTION, + g_socket_connection_factory_register_type (g_define_type_id, + G_SOCKET_FAMILY_VSOCK, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT); +); + +static void +g_vsock_connection_init (GVsockConnection *connection) +{ +} + +static void +g_vsock_connection_class_init (GVsockConnectionClass *class) +{ +} diff --git a/gio/gvsockconnection.h b/gio/gvsockconnection.h new file mode 100644 index 0000000000..32dd9fc120 --- /dev/null +++ b/gio/gvsockconnection.h @@ -0,0 +1,63 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright © 2021 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + * + * Authors: Marc-André Lureau + */ + +#ifndef __G_VSOCK_CONNECTION_H__ +#define __G_VSOCK_CONNECTION_H__ + +#include + +G_BEGIN_DECLS + +#define G_TYPE_VSOCK_CONNECTION (g_vsock_connection_get_type ()) +#define G_VSOCK_CONNECTION(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ + G_TYPE_VSOCK_CONNECTION, GVsockConnection)) +#define G_VSOCK_CONNECTION_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), \ + G_TYPE_VSOCK_CONNECTION, GVsockConnectionClass)) +#define G_IS_VSOCK_CONNECTION(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \ + G_TYPE_VSOCK_CONNECTION)) +#define G_IS_VSOCK_CONNECTION_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), \ + G_TYPE_VSOCK_CONNECTION)) +#define G_VSOCK_CONNECTION_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \ + G_TYPE_VSOCK_CONNECTION, GVsockConnectionClass)) + +typedef struct _GVsockConnection GVsockConnection; +typedef struct _GVsockConnectionPrivate GVsockConnectionPrivate; +typedef struct _GVsockConnectionClass GVsockConnectionClass; + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GVsockConnection, g_object_unref) + +struct _GVsockConnectionClass +{ + GSocketConnectionClass parent_class; +}; + +struct _GVsockConnection +{ + GSocketConnection parent_instance; + GVsockConnectionPrivate *priv; +}; + +GLIB_AVAILABLE_IN_2_68 +GType g_vsock_connection_get_type (void); + + +G_END_DECLS + +#endif /* __G_VSOCK_CONNECTION_H__ */ diff --git a/gio/meson.build b/gio/meson.build index 8e039b68c6..b64cdef2ba 100644 --- a/gio/meson.build +++ b/gio/meson.build @@ -580,6 +580,7 @@ gio_sources = files( 'gvfs.c', 'gvolume.c', 'gvolumemonitor.c', + 'gvsockconnection.c', 'gzlibcompressor.c', 'gzlibdecompressor.c', 'glistmodel.c', @@ -714,6 +715,7 @@ gio_headers = files( 'gvfs.h', 'gvolume.h', 'gvolumemonitor.h', + 'gvsockconnection.h', 'gzlibcompressor.h', 'gzlibdecompressor.h', 'glistmodel.h', -- GitLab From f4c2c31bafa51a44d974955930c7fc1ab4af70db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 20 Jan 2021 18:19:57 +0400 Subject: [PATCH 4/8] gio: add GVsockSocketAddress MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau --- docs/reference/gio/gio-docs.xml | 1 + docs/reference/gio/gio-sections-common.txt | 21 ++ gio/gio.h | 1 + gio/giotypes.h | 1 + gio/gsocketaddress.c | 13 + gio/gvsocksocketaddress.c | 300 +++++++++++++++++++++ gio/gvsocksocketaddress.h | 70 +++++ gio/meson.build | 2 + 8 files changed, 409 insertions(+) create mode 100644 gio/gvsocksocketaddress.c create mode 100644 gio/gvsocksocketaddress.h diff --git a/docs/reference/gio/gio-docs.xml b/docs/reference/gio/gio-docs.xml index e2fe61c8cc..ec1e48bb5a 100644 --- a/docs/reference/gio/gio-docs.xml +++ b/docs/reference/gio/gio-docs.xml @@ -122,6 +122,7 @@ + diff --git a/docs/reference/gio/gio-sections-common.txt b/docs/reference/gio/gio-sections-common.txt index 634089a48a..5d46c25e66 100644 --- a/docs/reference/gio/gio-sections-common.txt +++ b/docs/reference/gio/gio-sections-common.txt @@ -1880,6 +1880,27 @@ G_TYPE_NATIVE_SOCKET_ADDRESS_TYPE g_native_socket_address_get_type
+
+gvsocksocketaddress +GVsockSocketAddress +GVsockSocketAddress +g_vsock_socket_address_new +g_vsock_socket_address_get_cid +g_vsock_socket_address_get_port + +GVsockSocketAddressClass +GVsockSocketAddressPrivate +G_IS_VSOCK_SOCKET_ADDRESS +G_IS_VSOCK_SOCKET_ADDRESS_CLASS +G_TYPE_VSOCK_SOCKET_ADDRESS +G_VSOCK_SOCKET_ADDRESS +G_VSOCK_SOCKET_ADDRESS_CLASS +G_VSOCK_SOCKET_ADDRESS_GET_CLASS +G_TYPE_VSOCK_SOCKET_ADDRESS_TYPE + +g_vsock_socket_address_get_type +
+
gresolver GResolver diff --git a/gio/gio.h b/gio/gio.h index 3b70e45b95..f8b745428e 100644 --- a/gio/gio.h +++ b/gio/gio.h @@ -168,6 +168,7 @@ #include #include #include +#include #include #include diff --git a/gio/giotypes.h b/gio/giotypes.h index 995c9cb152..d7f0a67d3d 100644 --- a/gio/giotypes.h +++ b/gio/giotypes.h @@ -105,6 +105,7 @@ typedef struct _GInetAddress GInetAddress; typedef struct _GInetAddressMask GInetAddressMask; typedef struct _GInetSocketAddress GInetSocketAddress; typedef struct _GNativeSocketAddress GNativeSocketAddress; +typedef struct _GVsockSocketAddress GVsockSocketAddress; typedef struct _GInputStream GInputStream; typedef struct _GInitable GInitable; typedef struct _GIOModule GIOModule; diff --git a/gio/gsocketaddress.c b/gio/gsocketaddress.c index 2b7e83ccf9..5fbc5ef367 100644 --- a/gio/gsocketaddress.c +++ b/gio/gsocketaddress.c @@ -27,6 +27,7 @@ #include "ginetaddress.h" #include "ginetsocketaddress.h" #include "gnativesocketaddress.h" +#include "gvsocksocketaddress.h" #include "gnetworkingprivate.h" #include "gproxyaddress.h" #include "gproxyaddressenumerator.h" @@ -39,6 +40,10 @@ #include "gunixsocketaddress.h" #endif +#ifdef HAVE_VSOCK +#include +#endif + /** * SECTION:gsocketaddress @@ -300,6 +305,14 @@ g_socket_address_new_from_native (gpointer native, return g_unix_socket_address_new (addr->sun_path); } #endif +#ifdef HAVE_VSOCK + if (family == AF_VSOCK) + { + struct sockaddr_vm *addr = (struct sockaddr_vm *) native; + + return g_vsock_socket_address_new (addr->svm_cid, addr->svm_port); + } +#endif return g_native_socket_address_new (native, len); } diff --git a/gio/gvsocksocketaddress.c b/gio/gvsocksocketaddress.c new file mode 100644 index 0000000000..78155b892f --- /dev/null +++ b/gio/gvsocksocketaddress.c @@ -0,0 +1,300 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2021 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + * + * Authors: Marc-André Lureau + */ + +#include +#include +#include + +#include "gvsocksocketaddress.h" +#include "gnetworkingprivate.h" +#include "gsocketconnectable.h" +#include "gioerror.h" +#include "glibintl.h" + +#ifdef HAVE_VSOCK +#include +#endif + +/** + * SECTION:gvsocksocketaddress + * @short_description: VSOCK GSocketAddress + * @include: gio/gio.h + * + * An VSOCK socket address; that is, the combination of a Context Identifier + * (CID) and a port number. + */ + +/** + * GVsockSocketAddress: + * + * A VSOCK socket address, corresponding to a struct sockaddr_vm. + * + * Since: 2.68 + */ + +struct _GVsockSocketAddressPrivate +{ + guint cid; + guint port; +}; + +static void g_vsock_socket_address_connectable_iface_init (GSocketConnectableIface *iface); +static gchar *g_vsock_socket_address_connectable_to_string (GSocketConnectable *connectable); + +G_DEFINE_TYPE_WITH_CODE (GVsockSocketAddress, g_vsock_socket_address, G_TYPE_SOCKET_ADDRESS, + G_ADD_PRIVATE (GVsockSocketAddress) + G_IMPLEMENT_INTERFACE (G_TYPE_SOCKET_CONNECTABLE, + g_vsock_socket_address_connectable_iface_init)) + +enum { + PROP_0, + PROP_CID, + PROP_PORT, +}; + +static void +g_vsock_socket_address_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GVsockSocketAddress *address = G_VSOCK_SOCKET_ADDRESS (object); + + switch (prop_id) + { + case PROP_CID: + g_value_set_uint (value, address->priv->cid); + break; + + case PROP_PORT: + g_value_set_uint (value, address->priv->port); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +g_vsock_socket_address_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GVsockSocketAddress *address = G_VSOCK_SOCKET_ADDRESS (object); + + switch (prop_id) + { + case PROP_CID: + address->priv->cid = g_value_get_uint (value); + break; + + case PROP_PORT: + address->priv->port = g_value_get_uint (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static GSocketFamily +g_vsock_socket_address_get_family (GSocketAddress *address) +{ + g_return_val_if_fail (G_IS_VSOCK_SOCKET_ADDRESS (address), 0); + + return G_SOCKET_FAMILY_VSOCK; +} + +static gssize +g_vsock_socket_address_get_native_size (GSocketAddress *address) +{ +#ifdef HAVE_VSOCK + g_return_val_if_fail (G_IS_VSOCK_SOCKET_ADDRESS (address), 0); + + return sizeof (struct sockaddr_vm); +#else + g_warning_once ("VSOCK is not supported on this platform yet."); + return -1; +#endif +} + +static gboolean +g_vsock_socket_address_to_native (GSocketAddress *address, + gpointer dest, + gsize destlen, + GError **error) +{ +#ifdef HAVE_VSOCK + GVsockSocketAddress *addr; + struct sockaddr_vm *sock = (struct sockaddr_vm *) dest; + + g_return_val_if_fail (G_IS_VSOCK_SOCKET_ADDRESS (address), FALSE); + + addr = G_VSOCK_SOCKET_ADDRESS (address); + if (destlen < sizeof (*sock)) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE, + _("Not enough space for socket address")); + return FALSE; + } + + memset (sock, 0, sizeof (*sock)); + sock->svm_family = AF_VSOCK; + sock->svm_cid = addr->priv->cid; + sock->svm_port = addr->priv->port; + return TRUE; +#else + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("VSOCK is not support for this platform yet.")); + return FALSE; +#endif +} + +static void +g_vsock_socket_address_class_init (GVsockSocketAddressClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GSocketAddressClass *gsocketaddress_class = G_SOCKET_ADDRESS_CLASS (klass); + + gobject_class->set_property = g_vsock_socket_address_set_property; + gobject_class->get_property = g_vsock_socket_address_get_property; + + gsocketaddress_class->get_family = g_vsock_socket_address_get_family; + gsocketaddress_class->to_native = g_vsock_socket_address_to_native; + gsocketaddress_class->get_native_size = g_vsock_socket_address_get_native_size; + + /** + * GVsockSocketAddress:cid: + * + * The `svm_cid` field, for VSOCK addresses. + * + * Since: 2.68 + */ + g_object_class_install_property (gobject_class, PROP_CID, + g_param_spec_uint ("cid", + P_("CID"), + P_("The Context Identifier (CID)"), + 0, + G_MAXUINT, + 0, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * GVsockSocketAddress:port: + * + * The `svm_port` field, for VSOCK addresses. + * + * Since: 2.68 + */ + g_object_class_install_property (gobject_class, PROP_PORT, + g_param_spec_uint ("port", + P_("Port"), + P_("The port"), + 0, + G_MAXUINT, + 0, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); +} + +static void +g_vsock_socket_address_connectable_iface_init (GSocketConnectableIface *iface) +{ + GSocketConnectableIface *parent_iface = g_type_interface_peek_parent (iface); + + iface->enumerate = parent_iface->enumerate; + iface->proxy_enumerate = parent_iface->proxy_enumerate; + iface->to_string = g_vsock_socket_address_connectable_to_string; +} + +static gchar * +g_vsock_socket_address_connectable_to_string (GSocketConnectable *connectable) +{ + GVsockSocketAddress *sa = G_VSOCK_SOCKET_ADDRESS (connectable); + + return g_strdup_printf ("vsock:cid=%u,port=%u", sa->priv->cid, sa->priv->port); +} + +static void +g_vsock_socket_address_init (GVsockSocketAddress *address) +{ + address->priv = g_vsock_socket_address_get_instance_private (address); +} + +/** + * g_vsock_socket_address_new: + * @cid: a Context Identifier (CID) + * @port: a port number + * + * Creates a new #GVsockSocketAddress for @cid and @port. + * + * Returns: a new #GVsockSocketAddress + * + * Since: 2.68 + */ +GSocketAddress * +g_vsock_socket_address_new (guint cid, + guint port) +{ + return g_object_new (G_TYPE_VSOCK_SOCKET_ADDRESS, + "cid", cid, + "port", port, + NULL); +} + +/** + * g_vsock_socket_address_get_cid: + * @address: a #GVsockSocketAddress + * + * Gets @address's Context Identifier (CID). + * + * Returns: the Context Identifier (CID) for @address + * + * Since: 2.68 + */ +guint +g_vsock_socket_address_get_cid (GVsockSocketAddress *address) +{ + g_return_val_if_fail (G_IS_VSOCK_SOCKET_ADDRESS (address), 0); + + return address->priv->cid; +} + +/** + * g_vsock_socket_address_get_port: + * @address: a #GVsockSocketAddress + * + * Gets @address's port. + * + * Returns: the port for @address + * + * Since: 2.68 + */ +guint +g_vsock_socket_address_get_port (GVsockSocketAddress *address) +{ + g_return_val_if_fail (G_IS_VSOCK_SOCKET_ADDRESS (address), 0); + + return address->priv->port; +} diff --git a/gio/gvsocksocketaddress.h b/gio/gvsocksocketaddress.h new file mode 100644 index 0000000000..8e76d70686 --- /dev/null +++ b/gio/gvsocksocketaddress.h @@ -0,0 +1,70 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2021 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, see . + * + * Authors: Marc-André Lureau + */ + +#ifndef __G_VSOCK_SOCKET_ADDRESS_H__ +#define __G_VSOCK_SOCKET_ADDRESS_H__ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define G_TYPE_VSOCK_SOCKET_ADDRESS (g_vsock_socket_address_get_type ()) +#define G_VSOCK_SOCKET_ADDRESS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_VSOCK_SOCKET_ADDRESS, GVsockSocketAddress)) +#define G_VSOCK_SOCKET_ADDRESS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_VSOCK_SOCKET_ADDRESS, GVsockSocketAddressClass)) +#define G_IS_VSOCK_SOCKET_ADDRESS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_VSOCK_SOCKET_ADDRESS)) +#define G_IS_VSOCK_SOCKET_ADDRESS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_VSOCK_SOCKET_ADDRESS)) +#define G_VSOCK_SOCKET_ADDRESS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_VSOCK_SOCKET_ADDRESS, GVsockSocketAddressClass)) + +typedef struct _GVsockSocketAddressClass GVsockSocketAddressClass; +typedef struct _GVsockSocketAddressPrivate GVsockSocketAddressPrivate; + +struct _GVsockSocketAddress +{ + GSocketAddress parent_instance; + + /*< private >*/ + GVsockSocketAddressPrivate *priv; +}; + +struct _GVsockSocketAddressClass +{ + GSocketAddressClass parent_class; +}; + +GLIB_AVAILABLE_IN_2_68 +GType g_vsock_socket_address_get_type (void) G_GNUC_CONST; + +GLIB_AVAILABLE_IN_2_68 +GSocketAddress *g_vsock_socket_address_new (guint cid, + guint port); + +GLIB_AVAILABLE_IN_2_68 +guint g_vsock_socket_address_get_cid (GVsockSocketAddress *address); + +GLIB_AVAILABLE_IN_2_68 +guint g_vsock_socket_address_get_port (GVsockSocketAddress *address); + +G_END_DECLS + +#endif /* __G_VSOCK_SOCKET_ADDRESS_H__ */ diff --git a/gio/meson.build b/gio/meson.build index b64cdef2ba..b4cca8d1ab 100644 --- a/gio/meson.build +++ b/gio/meson.build @@ -581,6 +581,7 @@ gio_sources = files( 'gvolume.c', 'gvolumemonitor.c', 'gvsockconnection.c', + 'gvsocksocketaddress.c', 'gzlibcompressor.c', 'gzlibdecompressor.c', 'glistmodel.c', @@ -716,6 +717,7 @@ gio_headers = files( 'gvolume.h', 'gvolumemonitor.h', 'gvsockconnection.h', + 'gvsocksocketaddress.h', 'gzlibcompressor.h', 'gzlibdecompressor.h', 'glistmodel.h', -- GitLab From 635cf4b173126cd8772822dd1780c10f7ff6f9aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 20 Jan 2021 18:31:30 +0400 Subject: [PATCH 5/8] gio/tests: add a few VSOCK socket tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau --- gio/tests/socket.c | 74 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/gio/tests/socket.c b/gio/tests/socket.c index 683866ede3..7a272c8d3c 100644 --- a/gio/tests/socket.c +++ b/gio/tests/socket.c @@ -16,6 +16,7 @@ * Public License along with this library; if not, see . */ +#include "config.h" #include #include @@ -27,8 +28,10 @@ #include #include #endif - -#include "gnetworkingprivate.h" +#include +#ifdef HAVE_VSOCK +#include +#endif static gboolean ipv6_supported; @@ -1306,6 +1309,9 @@ static void test_sockaddr (void) { struct sockaddr_in6 sin6, gsin6; +#ifdef HAVE_VSOCK + struct sockaddr_vm svm; +#endif GSocketAddress *saddr; GInetSocketAddress *isaddr; GInetAddress *iaddr; @@ -1339,8 +1345,68 @@ test_sockaddr (void) g_assert_cmpint (sin6.sin6_flowinfo, ==, gsin6.sin6_flowinfo); g_object_unref (saddr); + +#ifdef HAVE_VSOCK + memset (&svm, 0, sizeof (svm)); + svm.svm_family = AF_VSOCK; + svm.svm_port = 42; + svm.svm_cid = 1729; + + saddr = g_socket_address_new_from_native (&svm, sizeof (svm)); + g_assert (G_IS_VSOCK_SOCKET_ADDRESS (saddr)); + g_assert_cmpint (g_socket_address_get_family (saddr), ==, AF_VSOCK); + g_object_unref (saddr); +#endif +} + +#ifdef HAVE_VSOCK +static void +test_vsock_from_fd (void) +{ + gint fd; + GError *error; + GSocket *s; + + fd = socket (AF_VSOCK, SOCK_STREAM, 0); + g_assert_cmpint (fd, !=, -1); + + error = NULL; + s = g_socket_new_from_fd (fd, &error); + g_assert_no_error (error); + g_assert_cmpint (g_socket_get_family (s), ==, G_SOCKET_FAMILY_VSOCK); + g_assert_cmpint (g_socket_get_socket_type (s), ==, G_SOCKET_TYPE_STREAM); + g_assert_cmpint (g_socket_get_protocol (s), ==, G_SOCKET_PROTOCOL_DEFAULT); + g_object_unref (s); } +static void +test_vsock_connection (void) +{ + gint fd; + GError *error; + GSocket *s; + GSocketConnection *c; + GSocketAddress *addr; + + fd = socket (AF_VSOCK, SOCK_STREAM, 0); + g_assert_cmpint (fd, !=, -1); + + error = NULL; + s = g_socket_new_from_fd (fd, &error); + g_assert_no_error (error); + c = g_socket_connection_factory_create_connection (s); + g_assert (G_IS_VSOCK_CONNECTION (c)); + + addr = g_socket_connection_get_local_address (c, &error); + g_assert_no_error (error); + g_assert (G_IS_VSOCK_SOCKET_ADDRESS (addr)); + + g_object_unref (addr); + g_object_unref (c); + g_object_unref (s); +} +#endif + #ifdef G_OS_UNIX static void test_unix_from_fd (void) @@ -2154,6 +2220,10 @@ main (int argc, g_test_add_func ("/socket/unix-connection", test_unix_connection); g_test_add_func ("/socket/unix-connection-ancillary-data", test_unix_connection_ancillary_data); g_test_add_func ("/socket/source-postmortem", test_source_postmortem); +#endif +#ifdef HAVE_VSOCK + g_test_add_func ("/socket/vsock-from-fd", test_vsock_from_fd); + g_test_add_func ("/socket/vsock-connection", test_vsock_connection); #endif g_test_add_func ("/socket/reuse/tcp", test_reuse_tcp); g_test_add_func ("/socket/reuse/udp", test_reuse_udp); -- GitLab From 341ef82f903679849195f321c800a78d13888831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 21 Jan 2021 19:34:27 +0400 Subject: [PATCH 6/8] gio: add support for vsock: DBus transport MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau --- gio/gdbusaddress.c | 121 +++++++++++++++++++++++++++++++++++++++++++++ gio/gdbusserver.c | 65 ++++++++++++++++++++++++ 2 files changed, 186 insertions(+) diff --git a/gio/gdbusaddress.c b/gio/gdbusaddress.c index d26c4d25f1..a28b46e97b 100644 --- a/gio/gdbusaddress.c +++ b/gio/gdbusaddress.c @@ -46,6 +46,10 @@ #include #include #endif +#ifdef HAVE_VSOCK +#include +#include +#endif #ifdef G_OS_WIN32 #include @@ -191,6 +195,80 @@ is_valid_unix (const gchar *address_entry, return ret; } +#ifdef HAVE_VSOCK +static gboolean +is_valid_vsock (const gchar *address_entry, + GHashTable *key_value_pairs, + GError **error) +{ + gboolean ret; + GList *keys; + GList *l; + const gchar *cid; + const gchar *port; + gchar *endp; + + ret = FALSE; + cid = NULL; + port = NULL; + + keys = g_hash_table_get_keys (key_value_pairs); + for (l = keys; l != NULL; l = l->next) + { + const gchar *key = l->data; + if (g_strcmp0 (key, "cid") == 0) + cid = g_hash_table_lookup (key_value_pairs, key); + else if (g_strcmp0 (key, "port") == 0) + port = g_hash_table_lookup (key_value_pairs, key); + else if (g_strcmp0 (key, "guid") != 0) + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + _("Unsupported key “%s” in address entry “%s”"), + key, + address_entry); + goto out; + } + } + + if (port != NULL) + { + strtoul (port, &endp, 10); + if ((*port == '\0' || *endp != '\0')) + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + _("Error in address “%s” — the “%s” attribute is malformed"), + address_entry, "port"); + goto out; + } + } + + if (cid != NULL) + { + strtoul (port, &endp, 10); + if ((*port == '\0' || *endp != '\0')) + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + _("Error in address “%s” — the “%s” attribute is malformed"), + address_entry, "cid"); + goto out; + } + } + + ret = TRUE; + + out: + g_list_free (keys); + + return ret; +} +#endif + static gboolean is_valid_nonce_tcp (const gchar *address_entry, GHashTable *key_value_pairs, @@ -413,6 +491,10 @@ g_dbus_is_supported_address (const gchar *string, supported = is_valid_nonce_tcp (a[n], key_value_pairs, error); else if (g_strcmp0 (a[n], "autolaunch:") == 0) supported = TRUE; +#ifdef HAVE_VSOCK + else if (g_strcmp0 (transport_name, "vsock") == 0) + supported = is_valid_vsock (a[n], key_value_pairs, error); +#endif else g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, _("Unknown or unsupported transport “%s” for address “%s”"), @@ -605,6 +687,45 @@ g_dbus_address_connect (const gchar *address_entry, g_assert_not_reached (); } } +#endif +#ifdef HAVE_VSOCK + else if (g_strcmp0 (transport_name, "vsock") == 0) + { + const gchar *s; + struct sockaddr_vm svm; + gchar *endp; + + memset (&svm, 0, sizeof (svm)); + svm.svm_family = AF_VSOCK; + + s = g_hash_table_lookup (key_value_pairs, "cid"); + if (s != NULL) + svm.svm_cid = strtoul (s, &endp, 10); + if (s == NULL || (*s == '\0' || *endp != '\0')) + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + _("Error in address “%s” — the cid attribute is missing or malformed"), + address_entry); + goto out; + } + + s = g_hash_table_lookup (key_value_pairs, "port"); + if (s != NULL) + svm.svm_port = strtoul (s, &endp, 10); + if (s == NULL || (*s == '\0' || *endp != '\0')) + { + g_set_error (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + _("Error in address “%s” — the port attribute is missing or malformed"), + address_entry); + goto out; + } + + connectable = G_SOCKET_CONNECTABLE (g_socket_address_new_from_native (&svm, sizeof (svm))); + } #endif else if (g_strcmp0 (transport_name, "tcp") == 0 || g_strcmp0 (transport_name, "nonce-tcp") == 0) { diff --git a/gio/gdbusserver.c b/gio/gdbusserver.c index 9009734d52..7e37ae03db 100644 --- a/gio/gdbusserver.c +++ b/gio/gdbusserver.c @@ -54,6 +54,10 @@ #ifdef G_OS_UNIX #include "gunixsocketaddress.h" #endif +#ifdef HAVE_VSOCK +#include +#include +#endif #include "glibintl.h" @@ -813,6 +817,63 @@ try_unix (GDBusServer *server, } #endif +#ifdef HAVE_VSOCK +/* note that address_entry has already been validated */ +static gboolean +try_vsock (GDBusServer *server, + const gchar *address_entry, + GHashTable *key_value_pairs, + GError **error) +{ + GSocketAddress *socket_address; + GSocketAddress *effective_address; + gboolean ret; + struct sockaddr_vm svm; + const gchar *cid; + const gchar *port; + + ret = FALSE; + + cid = g_hash_table_lookup (key_value_pairs, "cid"); + port = g_hash_table_lookup (key_value_pairs, "port"); + + memset (&svm, 0, sizeof (svm)); + svm.svm_family = AF_VSOCK; + svm.svm_cid = VMADDR_CID_LOCAL; + if (cid != NULL) + svm.svm_cid = strtoul (cid, NULL, 10); + svm.svm_port = VMADDR_PORT_ANY; + if (port != NULL) + svm.svm_port = strtoul (port, NULL, 10); + + socket_address = g_socket_address_new_from_native (&svm, sizeof (svm)); + if (!g_socket_listener_add_address (server->listener, + socket_address, + G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, + NULL, /* GObject *source_object */ + &effective_address, + error)) + { + g_object_unref (socket_address); + goto out; + } + + if (svm.svm_port == VMADDR_PORT_ANY) + svm.svm_port = g_vsock_socket_address_get_port (G_VSOCK_SOCKET_ADDRESS (effective_address)); + + g_object_unref (effective_address); + g_object_unref (socket_address); + + server->client_address = g_strdup_printf ("vsock:cid=%u,port=%u", svm.svm_cid, svm.svm_port); + server->is_using_listener = TRUE; + ret = TRUE; + + out: + return ret; +} +#endif + /* ---------------------------------------------------------------------------------------------------- */ /* note that address_entry has already been validated => @@ -1131,6 +1192,10 @@ initable_init (GInitable *initable, #ifdef G_OS_UNIX else if (g_strcmp0 (transport_name, "unix") == 0) ret = try_unix (server, address_entry, key_value_pairs, &this_error); +#endif +#ifdef HAVE_VSOCK + else if (g_strcmp0 (transport_name, "vsock") == 0) + ret = try_vsock (server, address_entry, key_value_pairs, &this_error); #endif else if (g_strcmp0 (transport_name, "tcp") == 0) ret = try_tcp (server, address_entry, key_value_pairs, FALSE, &this_error); -- GitLab From 7028fd93f90234cd718ed5c4c358a493b2b46224 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 21 Jan 2021 20:22:44 +0400 Subject: [PATCH 7/8] gio: add G_IO_ERROR_ADDRESS_NOT_AVAILABLE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau --- gio/gioenums.h | 4 +++- gio/gioerror.c | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/gio/gioenums.h b/gio/gioenums.h index f60740ce30..8efaef32d4 100644 --- a/gio/gioenums.h +++ b/gio/gioenums.h @@ -507,6 +507,7 @@ typedef enum { * value, which has this more logical name. Since 2.44. * @G_IO_ERROR_NOT_CONNECTED: Transport endpoint is not connected. Since 2.44 * @G_IO_ERROR_MESSAGE_TOO_LARGE: Message too large. Since 2.48. + * @G_IO_ERROR_ADDRESS_NOT_AVAILABLE: Cannot assign requested address. Since 2.68. * * Error codes returned by GIO functions. * @@ -575,7 +576,8 @@ typedef enum { G_IO_ERROR_BROKEN_PIPE, G_IO_ERROR_CONNECTION_CLOSED = G_IO_ERROR_BROKEN_PIPE, G_IO_ERROR_NOT_CONNECTED, - G_IO_ERROR_MESSAGE_TOO_LARGE + G_IO_ERROR_MESSAGE_TOO_LARGE, + G_IO_ERROR_ADDRESS_NOT_AVAILABLE } GIOErrorEnum; diff --git a/gio/gioerror.c b/gio/gioerror.c index 477906c0c6..120c234ff3 100644 --- a/gio/gioerror.c +++ b/gio/gioerror.c @@ -278,6 +278,12 @@ g_io_error_from_errno (gint err_no) break; #endif +#ifdef EADDRNOTAVAIL + case EADDRNOTAVAIL: + return G_IO_ERROR_ADDRESS_NOT_AVAILABLE; + break; +#endif + default: return G_IO_ERROR_FAILED; break; @@ -366,6 +372,11 @@ g_io_error_from_win32_error (gint error_code) case WSAEMSGSIZE: return G_IO_ERROR_MESSAGE_TOO_LARGE; +#ifdef WSAEADDRNOTAVAIL + case WSAEADDRNOTAVAIL: + return G_IO_ERROR_ADDRESS_NOT_AVAILABLE; +#endif + default: return G_IO_ERROR_FAILED; } -- GitLab From aa5374b2456cf4c9e4cd84418cedaa166e3abd75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 21 Jan 2021 19:34:51 +0400 Subject: [PATCH 8/8] gio: test DBus vsock: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau --- gio/tests/gdbus-peer.c | 95 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/gio/tests/gdbus-peer.c b/gio/tests/gdbus-peer.c index 23a22981a0..ac8538d940 100644 --- a/gio/tests/gdbus-peer.c +++ b/gio/tests/gdbus-peer.c @@ -1736,6 +1736,98 @@ test_tcp_anonymous (void) g_free (test_guid); } +#ifdef HAVE_VSOCK +static gpointer +vsock_service_thread_func (gpointer user_data) +{ + gboolean *seen_connection = user_data; + GMainContext *service_context; + GError *error; + + service_context = g_main_context_new (); + g_main_context_push_thread_default (service_context); + + error = NULL; + server = g_dbus_server_new_sync ("vsock:", + G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS, + test_guid, + NULL, /* GDBusObserver* */ + NULL, /* GCancellable* */ + &error); + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_ADDRESS_NOT_AVAILABLE)) + { + g_test_skip ("VSOCK not enabled or not avaialble"); + goto run_loop; + } + g_assert_no_error (error); + + g_signal_connect (server, + "new-connection", + G_CALLBACK (tcp_anonymous_on_new_connection), + seen_connection); + + g_dbus_server_start (server); + +run_loop: + run_service_loop (service_context); + + g_main_context_pop_thread_default (service_context); + + teardown_service_loop (); + g_main_context_unref (service_context); + + return NULL; +} + +static void +test_vsock (void) +{ + gboolean seen_connection; + GThread *service_thread; + GDBusConnection *connection; + GError *error; + + test_guid = g_dbus_generate_guid (); + loop = g_main_loop_new (NULL, FALSE); + + seen_connection = FALSE; + service_thread = g_thread_new ("vsock-service", + vsock_service_thread_func, + &seen_connection); + await_service_loop (); + if (server == NULL) + goto end; + + error = NULL; + connection = g_dbus_connection_new_for_address_sync (g_dbus_server_get_client_address (server), + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, /* GDBusAuthObserver* */ + NULL, /* GCancellable */ + &error); + g_assert_no_error (error); + g_assert (connection != NULL); + + while (!seen_connection) + g_thread_yield (); + + g_object_unref (connection); + +end: + g_main_loop_quit (service_loop); + if (server) + { + g_dbus_server_stop (server); + g_object_unref (server); + server = NULL; + } + + g_thread_join (service_thread); + + g_main_loop_unref (loop); + g_free (test_guid); +} +#endif + /* ---------------------------------------------------------------------------------------------------- */ static GDBusServer *codegen_server = NULL; @@ -2017,6 +2109,9 @@ main (int argc, g_test_add_func ("/gdbus/tcp-anonymous", test_tcp_anonymous); g_test_add_func ("/gdbus/credentials", test_credentials); g_test_add_func ("/gdbus/codegen-peer-to-peer", codegen_test_peer); +#ifdef HAVE_VSOCK + g_test_add_func ("/gdbus/vsock", test_vsock); +#endif ret = g_test_run (); -- GitLab