diff options
author | Thomas Haller <thaller@redhat.com> | 2016-06-13 11:47:58 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2016-06-15 10:32:32 +0200 |
commit | 7b3c93829d8682c7443165c100c114744696b976 (patch) | |
tree | 896083d09a02b7a8a6713adae7b8803e771f23a6 | |
parent | 1c42375efb56bccb2ed55153cfd82826f910cac1 (diff) | |
download | NetworkManager-th/vpn-service-info-bgo767197.tar.gz |
libnm/vpn: add nm_vpn_editor_plugin_load_vt()th/vpn-service-info-bgo767197
Let VPN plugins return a virtual function table to extend
the API while bypassing libnm. This allows to add and use
new functionality to VPN plugins without updating libnm.
The actual definitions are in a header-only file
"nm-vpn-editor-plugin-call.h", which can be copied to the
caller/plugin.
-rw-r--r-- | libnm-core/nm-vpn-editor-plugin.c | 47 | ||||
-rw-r--r-- | libnm-core/nm-vpn-editor-plugin.h | 12 | ||||
-rw-r--r-- | libnm/libnm.ver | 1 | ||||
-rw-r--r-- | libnm/nm-vpn-service-plugin.c | 8 | ||||
-rw-r--r-- | po/POTFILES.skip | 1 | ||||
-rw-r--r-- | shared/Makefile.am | 3 | ||||
-rw-r--r-- | shared/nm-vpn-editor-plugin-call.h | 184 |
7 files changed, 255 insertions, 1 deletions
diff --git a/libnm-core/nm-vpn-editor-plugin.c b/libnm-core/nm-vpn-editor-plugin.c index 1a4944b066..bc72ca3911 100644 --- a/libnm-core/nm-vpn-editor-plugin.c +++ b/libnm-core/nm-vpn-editor-plugin.c @@ -180,6 +180,53 @@ nm_vpn_editor_plugin_set_plugin_info (NMVpnEditorPlugin *plugin, NMVpnPluginInfo /*********************************************************************/ +/** + * nm_vpn_editor_plugin_get_vt: + * @plugin: the #NMVpnEditorPlugin + * @vt: (out): buffer to be filled with the VT table of the plugin + * @vt_size: the size of the buffer. Can be 0 to only query the + * size of plugin's VT. + * + * Returns an opaque VT function table for the plugin to extend + * functionality. The actual meaning of NMVpnEditorPluginVT is not + * defined in public API of libnm, instead it must be agreed by + * both the plugin and the caller. See the header-only file + * 'nm-vpn-editor-plugin-call.h' which defines the meaning. + * + * Returns: the actual size of the @plugin's virtual function table. + * + * Since: 1.4 + **/ +gsize +nm_vpn_editor_plugin_get_vt (NMVpnEditorPlugin *plugin, + NMVpnEditorPluginVT *vt, + gsize vt_size) +{ + const NMVpnEditorPluginVT *p_vt = NULL; + gsize p_vt_size = 0; + NMVpnEditorPluginInterface *interface; + + g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), 0); + + if (vt_size) { + g_return_val_if_fail (vt, 0); + memset (vt, 0, vt_size); + } + + interface = NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin); + if (interface->get_vt) { + p_vt = interface->get_vt (plugin, &p_vt_size); + if (!p_vt) + p_vt_size = 0; + g_return_val_if_fail (p_vt_size, 0); + memcpy (vt, p_vt, MIN (vt_size, p_vt_size)); + } + + return p_vt_size; +} + +/*********************************************************************/ + static NMVpnEditorPlugin * _nm_vpn_editor_plugin_load (const char *plugin_name, gboolean do_file_checks, diff --git a/libnm-core/nm-vpn-editor-plugin.h b/libnm-core/nm-vpn-editor-plugin.h index dc18f04b74..fb51f7e621 100644 --- a/libnm-core/nm-vpn-editor-plugin.h +++ b/libnm-core/nm-vpn-editor-plugin.h @@ -82,6 +82,8 @@ typedef enum /*< flags >*/ { /* D-Bus service name of the plugin's VPN service */ #define NM_VPN_EDITOR_PLUGIN_SERVICE "service" +typedef struct _NMVpnEditorPluginVT NMVpnEditorPluginVT; + /** * NMVpnEditorPluginInterface: * @g_iface: the parent interface @@ -99,6 +101,8 @@ typedef enum /*< flags >*/ { * @get_suggested_filename: For a given connection, return a suggested file * name. Returned value will be %NULL or a suggested file name to be freed by * the caller. + * @get_vt: return a virtual function table to implement further functions in + * the plugin, without requiring to update libnm. Used by nm_vpn_editor_plugin_get_vt(). * * Interface for VPN editor plugins. */ @@ -124,6 +128,9 @@ typedef struct { void (*notify_plugin_info_set) (NMVpnEditorPlugin *plugin, struct _NMVpnPluginInfo *plugin_info); + + const NMVpnEditorPluginVT *(*get_vt) (NMVpnEditorPlugin *plugin, + gsize *out_vt_size); } NMVpnEditorPluginInterface; GType nm_vpn_editor_plugin_get_type (void); @@ -134,6 +141,11 @@ NMVpnEditor *nm_vpn_editor_plugin_get_editor (NMVpnEditorPlugin *plugin, NMVpnEditorPluginCapability nm_vpn_editor_plugin_get_capabilities (NMVpnEditorPlugin *plugin); +NM_AVAILABLE_IN_1_4 +gsize nm_vpn_editor_plugin_get_vt (NMVpnEditorPlugin *plugin, + NMVpnEditorPluginVT *vt, + gsize vt_size); + NMConnection *nm_vpn_editor_plugin_import (NMVpnEditorPlugin *plugin, const char *path, GError **error); diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 2dc2103517..41f650f008 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1069,6 +1069,7 @@ global: nm_setting_ip6_config_get_token; nm_setting_ip_config_get_dns_priority; nm_vpn_editor_plugin_get_plugin_info; + nm_vpn_editor_plugin_get_vt; nm_vpn_editor_plugin_load; nm_vpn_editor_plugin_set_plugin_info; nm_vpn_plugin_info_get_aliases; diff --git a/libnm/nm-vpn-service-plugin.c b/libnm/nm-vpn-service-plugin.c index bf4369e4ad..df99eb28d9 100644 --- a/libnm/nm-vpn-service-plugin.c +++ b/libnm/nm-vpn-service-plugin.c @@ -1306,3 +1306,11 @@ nm_vpn_service_plugin_initable_iface_init (GInitableIface *iface) { iface->init = init_sync; } + +/*****************************************************************************/ + +/* this header is intended to be copied to users of nm_vpn_editor_plugin_call(), + * to simplify invocation of generic functions. Include it here, to complile + * the code. */ +#include "nm-vpn-editor-plugin-call.h" + diff --git a/po/POTFILES.skip b/po/POTFILES.skip index 70e222c6a9..2e36b03a17 100644 --- a/po/POTFILES.skip +++ b/po/POTFILES.skip @@ -7,4 +7,5 @@ vpn-daemons/pptp vpn-daemons/vpnc contrib/fedora/rpm/ # https://bugs.launchpad.net/intltool/+bug/1117944 +shared/nm-vpn-editor-plugin-call.h sub/policy/org.freedesktop.NetworkManager.policy.in diff --git a/shared/Makefile.am b/shared/Makefile.am index c6ede00b6a..01818d0cd1 100644 --- a/shared/Makefile.am +++ b/shared/Makefile.am @@ -10,6 +10,7 @@ EXTRA_DIST = \ nm-test-libnm-utils.h \ nm-test-utils.h \ nm-test-utils-impl.c \ - nm-version-macros.h.in + nm-version-macros.h.in \ + nm-vpn-editor-plugin-call.h CLEANFILES=nm-version.h diff --git a/shared/nm-vpn-editor-plugin-call.h b/shared/nm-vpn-editor-plugin-call.h new file mode 100644 index 0000000000..584f3787d5 --- /dev/null +++ b/shared/nm-vpn-editor-plugin-call.h @@ -0,0 +1,184 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2016 Red Hat, Inc. + */ + +#ifndef __NM_VPN_EDITOR_PLUGIN_CALL_H__ +#define __NM_VPN_EDITOR_PLUGIN_CALL_H__ + +/* This header is an internal, header-only file that can be copied to + * other projects to call well-known service functions on VPN plugins. */ + +#include <NetworkManager.h> + +/* we make use of otherinternal header files, you need those too. */ +#include "gsystem-local-alloc.h" +#include "nm-macros-internal.h" + +/*****************************************************************************/ + +/** + * NMVpnEditorPluginServiceFlags: + * @NM_VPN_EDITOR_PLUGIN_SERVICE_FLAGS_NONE: no flags + * @NM_VPN_EDITOR_PLUGIN_SERVICE_FLAGS_CAN_ADD: whether the plugin can + * add a new connection for the given service-type. + **/ +typedef enum { /*< skip >*/ + NM_VPN_EDITOR_PLUGIN_SERVICE_FLAGS_NONE = 0x00, + NM_VPN_EDITOR_PLUGIN_SERVICE_FLAGS_CAN_ADD = 0x01, +} NMVpnEditorPluginServiceFlags; + +struct _NMVpnEditorPluginVT { + gboolean (*fcn_get_service_info) (NMVpnEditorPlugin *plugin, + const char *service_type, + char **out_short_name, + char **out_pretty_name, + char **out_description, + NMVpnEditorPluginServiceFlags *out_flags); + char **(*fcn_get_service_add_details) (NMVpnEditorPlugin *plugin, + const char *service_name); + gboolean (*fcn_get_service_add_detail) (NMVpnEditorPlugin *plugin, + const char *service_type, + const char *add_detail, + char **out_pretty_name, + char **out_description, + char **out_add_detail_key, + char **out_add_detail_val, + guint *out_flags); +}; + +/***************************************************************************** + * Call + * + * The following wrap the calling of generic functions for a VPN plugin. + * They are used by callers (for example nm-connection-editor). + *****************************************************************************/ + +static inline gboolean +nm_vpn_editor_plugin_get_service_info (NMVpnEditorPlugin *plugin, + const char *service_type, + char **out_short_name, + char **out_pretty_name, + char **out_description, + NMVpnEditorPluginServiceFlags *out_flags) +{ + NMVpnEditorPluginVT vt; + gs_free char *short_name_local = NULL; + gs_free char *pretty_name_local = NULL; + gs_free char *description_local = NULL; + guint flags_local = 0; + + g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), FALSE); + g_return_val_if_fail (service_type, FALSE); + + nm_vpn_editor_plugin_get_vt (plugin, &vt, sizeof (vt)); + if ( !vt.fcn_get_service_info + || !vt.fcn_get_service_info (plugin, + service_type, + out_short_name ? &short_name_local : NULL, + out_pretty_name ? &pretty_name_local : NULL, + out_description ? &description_local : NULL, + out_flags ? &flags_local : NULL)) + return FALSE; + NM_SET_OUT (out_short_name, g_steal_pointer (&short_name_local)); + NM_SET_OUT (out_pretty_name, g_steal_pointer (&pretty_name_local)); + NM_SET_OUT (out_description, g_steal_pointer (&description_local)); + NM_SET_OUT (out_flags, flags_local); + return TRUE; +} + +static inline char ** +nm_vpn_editor_plugin_get_service_add_details (NMVpnEditorPlugin *plugin, + const char *service_name) +{ + NMVpnEditorPluginVT vt; + char **details = NULL; + + g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL); + g_return_val_if_fail (service_name, NULL); + + nm_vpn_editor_plugin_get_vt (plugin, &vt, sizeof (vt)); + if (vt.fcn_get_service_add_details) + details = vt.fcn_get_service_add_details (plugin, service_name); + if (!details) + return g_new0 (char *, 1); + return details; +} + +static inline gboolean +nm_vpn_editor_plugin_get_service_add_detail (NMVpnEditorPlugin *plugin, + const char *service_type, + const char *add_detail, + char **out_pretty_name, + char **out_description, + char **out_add_detail_key, + char **out_add_detail_val, + guint *out_flags) +{ + NMVpnEditorPluginVT vt; + gs_free char *pretty_name_local = NULL; + gs_free char *description_local = NULL; + gs_free char *add_detail_key_local = NULL; + gs_free char *add_detail_val_local = NULL; + guint flags_local = 0; + + g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), FALSE); + g_return_val_if_fail (service_type, FALSE); + g_return_val_if_fail (add_detail, FALSE); + + nm_vpn_editor_plugin_get_vt (plugin, &vt, sizeof (vt)); + if ( !vt.fcn_get_service_add_detail + || !vt.fcn_get_service_add_detail (plugin, + service_type, + add_detail, + out_pretty_name ? &pretty_name_local : NULL, + out_description ? &description_local : NULL, + out_add_detail_key ? &add_detail_key_local : NULL, + out_add_detail_val ? &add_detail_val_local : NULL, + out_flags ? &flags_local : NULL)) + return FALSE; + NM_SET_OUT (out_pretty_name, g_steal_pointer (&pretty_name_local)); + NM_SET_OUT (out_description, g_steal_pointer (&description_local)); + NM_SET_OUT (out_add_detail_key, g_steal_pointer (&add_detail_key_local)); + NM_SET_OUT (out_add_detail_val, g_steal_pointer (&add_detail_val_local)); + NM_SET_OUT (out_flags, flags_local); + return TRUE; +} + +/***************************************************************************** + * Implementation + * + * The following glue code can be used to implement calls in a VPN plugin. + *****************************************************************************/ + +#define NM_VPN_EDITOR_PLUGIN_VT_DEFINE(vt_name, get_vt, ...) \ +static const NMVpnEditorPluginVT vt_name = { \ + __VA_ARGS__ \ + }; \ +static const NMVpnEditorPluginVT * \ +get_vt (NMVpnEditorPlugin *plugin, \ + gsize *out_vt_size) \ +{ \ + nm_assert (NM_IS_VPN_EDITOR_PLUGIN (plugin)); \ + nm_assert (out_vt_size); \ + \ + *out_vt_size = sizeof (vt_name); \ + return &vt_name; \ +} + +#endif /* __NM_VPN_EDITOR_PLUGIN_CALL_H__ */ |