summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2016-06-05 12:40:54 +0200
committerThomas Haller <thaller@redhat.com>2016-06-13 10:51:07 +0200
commit3663bd5348069c1e0513f3d16044cb556a49d1b7 (patch)
tree783cdeac04913e7e4bfe2392d23922f908b3c098
parent1e261d0fa211ee97d5c3f8f2f11bc898d0c1a702 (diff)
downloadNetworkManager-th/vpn-service-info-bgo767197-1.tar.gz
libnm/vpn: add header-only "nm-vpn-editor-plugin-call.h" with VPN call wrappersth/vpn-service-info-bgo767197-1
The calls the the VPN are generic, but still for known names they follow a defined signature and behavior. Add a header-only, internal header-file which adds wrappers and glue code to make/implements the calls more conviniently. This header is intended to be copied to the users (either the VPN plugin or the clients).
-rw-r--r--libnm/nm-vpn-service-plugin.c8
-rw-r--r--po/POTFILES.skip1
-rw-r--r--shared/Makefile.am3
-rw-r--r--shared/nm-vpn-editor-plugin-call.h418
4 files changed, 429 insertions, 1 deletions
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..3517f8f5d6
--- /dev/null
+++ b/shared/nm-vpn-editor-plugin-call.h
@@ -0,0 +1,418 @@
+/* -*- 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;
+
+/*****************************************************************************/
+
+/**
+ * NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_INFO: name of call "get-service-info".
+ * This call has 1 input argument:
+ * service-type (string): analog to NM_VPN_EDITOR_PLUGIN_SERVICE
+ * it specifies for which service-type the information is requested.
+ * This can either be the main service-type or an alias.
+ * This call has 3 output arguments:
+ * short-name (string): for the main service-type, this shall return [VPN Connection].name.
+ * Otherwise, it is a short-name to refer to service-type.
+ * pretty-name (string): for the main service-type, this shall return NM_VPN_EDITOR_PLUGIN_NAME.
+ * It's a localized, pretty name of the service-type.
+ * description (string): for the main service-type, this shall return NM_VPN_EDITOR_PLUGIN_DESCRIPTION
+ * It's a localized, description for the service-type.
+ * service flags (uint): flags for the service-type.
+ */
+#define NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_INFO "get-service-info"
+
+/**
+ * NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_ADD_DETAILS: name of call "get-service-add-details".
+ * For one particular service-type, the UI might want to show multiple "Add new connection"
+ * entires. That is controlled by passing around "add-details".
+ * The "get-service-add-details" returns optionally a list of "add-details" if it wishes
+ * to generate multiple add entries.
+ * This call has 1 input argument:
+ * service-type: string: analog to NM_VPN_EDITOR_PLUGIN_SERVICE or an service-type
+ * alias.
+ * This call has 1 output argument:
+ * add-details: strv: a list of details that can be passed to "get-service-add-detail"
+ * call.
+ */
+#define NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_ADD_DETAILS "get-service-add-details"
+
+/**
+ * NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_ADD_DETAIL: if the plugin supports "add-details"
+ * as indicated by "get-service-add-details", return more information.
+ * This call has 2 input arguments:
+ * service-name: string: analog to NM_VPN_EDITOR_PLUGIN_SERVICE or an service-type
+ * alias. This was passed to "get-service-add-details" call.
+ * add-detail: a detail for which the information is requested.
+ * This call has 1 output argument:
+ * pretty-name: (string), a localized name for what is to be added. Similar to
+ * NM_VPN_EDITOR_PLUGIN_NAME.
+ * description: (string), a localized descirption, similar to NM_VPN_EDITOR_PLUGIN_DESCRIPTION.
+ * add-detail-key: (string), when creating such a connection of type "service-type","add-detail",
+ * the user shall create a NMConnection with setting "service-type". It also sets the VPN
+ * key "add-detail-key" to the value "add-detail", so that the plugin knows which connection
+ * is to be created.
+ * flags: (uint), additional flags, currently unused.
+ */
+#define NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_ADD_DETAIL "get-service-add-detail"
+
+/*****************************************************************************
+ * 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)
+{
+ 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);
+
+ if (!nm_vpn_editor_plugin_call (plugin,
+ NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_INFO,
+ NULL,
+ G_TYPE_STRING, &service_type,
+ G_TYPE_INVALID,
+ G_TYPE_STRING, &short_name_local,
+ G_TYPE_STRING, &pretty_name_local,
+ G_TYPE_STRING, &description_local,
+ G_TYPE_UINT, &flags_local,
+ G_TYPE_INVALID))
+ 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)
+{
+ char **details = NULL;
+
+ g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), FALSE);
+ g_return_val_if_fail (service_name, FALSE);
+
+ if (!nm_vpn_editor_plugin_call (plugin,
+ NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_ADD_DETAILS,
+ NULL,
+ G_TYPE_STRING, service_name,
+ G_TYPE_INVALID,
+ G_TYPE_STRV, &details,
+ G_TYPE_INVALID))
+ g_clear_pointer (&details, g_strfreev);
+ else 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)
+{
+ 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);
+
+ if (!nm_vpn_editor_plugin_call (plugin,
+ NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_ADD_DETAIL,
+ NULL,
+ G_TYPE_STRING, service_type,
+ G_TYPE_STRING, add_detail,
+ G_TYPE_INVALID,
+ G_TYPE_STRING, &pretty_name_local,
+ G_TYPE_STRING, &description_local,
+ G_TYPE_STRING, &add_detail_key_local,
+ G_TYPE_STRING, &add_detail_val_local,
+ G_TYPE_UINT, out_flags ?: &flags_local,
+ G_TYPE_INVALID))
+ 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));
+ return TRUE;
+}
+
+/*****************************************************************************
+ * Implementation
+ *
+ * The following glue code can be used to implement calls in a VPN plugin.
+ * Register your hocks via NM_VPN_EDITOR_PLUGIN_CALL_SET_*() and
+ * NM_VPN_EDITOR_PLUGIN_CALL_SETUP().
+ *****************************************************************************/
+
+static gboolean (*const _nm_vpn_editor_plugin_call_impl_get_service_info) (NMVpnEditorPlugin *plugin,
+ const char *service_type,
+ char **out_short_name,
+ char **out_pretty_name,
+ char **out_description,
+ NMVpnEditorPluginServiceFlags *out_flags,
+ GError **error);
+
+#define NM_VPN_EDITOR_PLUGIN_CALL_SET_GET_SERVICE_INFO(fcn) \
+static gboolean (*const _nm_vpn_editor_plugin_call_impl_get_service_info) (NMVpnEditorPlugin *plugin, \
+ const char *service_type, \
+ char **out_short_name, \
+ char **out_pretty_name, \
+ char **out_description, \
+ NMVpnEditorPluginServiceFlags *out_flags, \
+ GError **error) = (fcn)
+
+static gboolean (*const _nm_vpn_editor_plugin_call_impl_get_service_add_details) (NMVpnEditorPlugin *plugin,
+ const char *service_type,
+ char ***out_add_details,
+ GError **error);
+
+#define NM_VPN_EDITOR_PLUGIN_CALL_SET_GET_SERVICE_ADD_DETAILS(fcn) \
+static gboolean (*const _nm_vpn_editor_plugin_call_impl_get_service_add_details) (NMVpnEditorPlugin *plugin, \
+ const char *service_type, \
+ char ***out_add_details, \
+ GError **error) = (fcn)
+
+static gboolean (*const _nm_vpn_editor_plugin_call_impl_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,
+ GError **error);
+
+#define NM_VPN_EDITOR_PLUGIN_CALL_SET_GET_SERVICE_ADD_DETAIL(fcn) \
+static gboolean (*const _nm_vpn_editor_plugin_call_impl_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, \
+ GError **error) = (fcn)
+
+static inline gboolean
+_nm_vpn_editor_plugin_call_get_signature (NMVpnEditorPlugin *plugin,
+ const char *request,
+ gboolean *free_types,
+ GType **types_in,
+ GType **types_out)
+{
+ if ( _nm_vpn_editor_plugin_call_impl_get_service_info
+ && nm_streq (request, NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_INFO)) {
+ static GType t_in[] = { G_TYPE_STRING, 0 };
+ static GType t_out[] = { G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, 0 };
+
+ *types_in = t_in;
+ *types_out = t_out;
+ return TRUE;
+ }
+ if ( _nm_vpn_editor_plugin_call_impl_get_service_add_details
+ && nm_streq (request, NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_ADD_DETAILS)) {
+ static GType t_in[] = { G_TYPE_STRING, 0 };
+ static GType t_out[] = { 0, 0 };
+
+ if (G_UNLIKELY (t_out[0] == 0))
+ t_out[0] = G_TYPE_STRV;
+
+ *types_in = t_in;
+ *types_out = t_out;
+ return TRUE;
+ }
+ if ( _nm_vpn_editor_plugin_call_impl_get_service_add_detail
+ && nm_streq (request, NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_ADD_DETAIL)) {
+ static GType t_in[] = { G_TYPE_STRING, G_TYPE_STRING, 0 };
+ static GType t_out[] = { G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT, 0 };
+
+ *types_in = t_in;
+ *types_out = t_out;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static inline gboolean
+_nm_vpn_editor_plugin_call_fail_unknown_service_type (GError **error, const char *service_type)
+{
+ if (error && !*error) {
+ g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_CALL_INVALID_ARGUMENT,
+ _("Unknown service-type %s%s%s"), NM_PRINT_FMT_QUOTE_STRING (service_type));
+ }
+ return FALSE;
+}
+
+static inline gboolean
+_nm_vpn_editor_plugin_call (NMVpnEditorPlugin *plugin,
+ const char *request,
+ GError **error,
+ const GValue *const*args_in,
+ GValue *const*args_out)
+{
+ if ( _nm_vpn_editor_plugin_call_impl_get_service_info
+ && nm_streq (request, NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_INFO)) {
+ const char *service_type;
+ gs_free char *short_name = NULL;
+ gs_free char *pretty_name = NULL;
+ gs_free char *description = NULL;
+ NMVpnEditorPluginServiceFlags flags = 0;
+
+ service_type = g_value_get_string (args_in[0]);
+
+ if (!service_type)
+ return _nm_vpn_editor_plugin_call_fail_unknown_service_type (error, service_type);
+
+ if (_nm_vpn_editor_plugin_call_impl_get_service_info (plugin,
+ service_type,
+ &short_name,
+ &pretty_name,
+ &description,
+ &flags,
+ error)) {
+ g_value_take_string (args_out[0], g_steal_pointer (&short_name));
+ g_value_take_string (args_out[1], g_steal_pointer (&pretty_name));
+ g_value_take_string (args_out[2], g_steal_pointer (&description));
+ g_value_set_uint (args_out[3], flags);
+ return TRUE;
+ }
+ return _nm_vpn_editor_plugin_call_fail_unknown_service_type (error, service_type);
+ }
+
+ if ( _nm_vpn_editor_plugin_call_impl_get_service_add_details
+ && nm_streq (request, NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_ADD_DETAILS)) {
+ const char *service_type;
+
+ service_type = g_value_get_string (args_in[0]);
+ if (service_type) {
+ gs_strfreev char **add_details = NULL;
+
+ if (_nm_vpn_editor_plugin_call_impl_get_service_add_details (plugin,
+ service_type,
+ &add_details,
+ error)) {
+ g_value_take_boxed (args_out[0], g_steal_pointer (&add_details));
+ return TRUE;
+ }
+ }
+ return _nm_vpn_editor_plugin_call_fail_unknown_service_type (error, service_type);
+ }
+
+ if ( _nm_vpn_editor_plugin_call_impl_get_service_add_detail
+ && nm_streq (request, NM_VPN_EDITOR_PLUGIN_CALL_GET_SERVICE_ADD_DETAIL)) {
+ const char *service_type;
+ const char *add_detail;
+ gs_free char *pretty_name = NULL;
+ gs_free char *description = NULL;
+ gs_free char *add_detail_key = NULL;
+ gs_free char *add_detail_val = NULL;
+ guint flags = 0;
+
+ service_type = g_value_get_string (args_in[0]);
+ add_detail = g_value_get_string (args_in[1]);
+
+ if (!service_type)
+ return _nm_vpn_editor_plugin_call_fail_unknown_service_type (error, service_type);
+
+ if (!add_detail) {
+ g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_CALL_INVALID_ARGUMENT,
+ _("missing add_detail argument"));
+ return FALSE;
+ }
+ if (_nm_vpn_editor_plugin_call_impl_get_service_add_detail (plugin,
+ service_type,
+ add_detail,
+ &pretty_name,
+ &description,
+ &add_detail_key,
+ &add_detail_val,
+ &flags,
+ error)) {
+ if (!add_detail_val)
+ add_detail_val = g_strdup (add_detail);
+ g_value_take_string (args_out[0], g_steal_pointer (&pretty_name));
+ g_value_take_string (args_out[1], g_steal_pointer (&description));
+ g_value_take_string (args_out[2], g_steal_pointer (&add_detail_key));
+ g_value_take_string (args_out[3], g_steal_pointer (&add_detail_val));
+ g_value_set_uint (args_out[4], flags);
+ return TRUE;
+ }
+ return _nm_vpn_editor_plugin_call_fail_unknown_service_type (error, service_type);
+ }
+
+ g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_CALL_INVALID_ARGUMENT,
+ _("Unknown request %s"), request);
+ return FALSE;
+}
+
+static inline void
+NM_VPN_EDITOR_PLUGIN_CALL_SETUP (NMVpnEditorPluginInterface *iface_class)
+{
+ iface_class->call_get_signature = _nm_vpn_editor_plugin_call_get_signature;
+ iface_class->call = _nm_vpn_editor_plugin_call;
+}
+
+#endif /* __NM_VPN_EDITOR_PLUGIN_CALL_H__ */