[network-manager-applet/th/vpn-service-info-bgo767197: 1/7] c-e: allow one VPN plugin to create multiple "Add" entires per provided service-type
- From: Thomas Haller <thaller src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [network-manager-applet/th/vpn-service-info-bgo767197: 1/7] c-e: allow one VPN plugin to create multiple "Add" entires per provided service-type
- Date: Mon, 13 Jun 2016 11:57:09 +0000 (UTC)
commit 24a245e32fddfc35f73a0311236a90e2b1a6d977
Author: Thomas Haller <thaller redhat com>
Date: Fri Jun 3 17:31:48 2016 +0200
c-e: allow one VPN plugin to create multiple "Add" entires per provided service-type
One VPN plugin can support multiple "service-types", also known as
"aliases". These service-types look like a D-Bus bus name and are stored
in the connection as vpn.service-type.
Previously already, one VPN plugin could edit connections with different
service-types, using aliases. That is for example used for nm-libreswan,
which supports editing both libreswan and openswan types.
However, in "Connection Add" one plugin could only create one entry
in the list of supported types. Thus, the "vpn.service-type" could
only be set to the main service-type, and one plugin could not create
connection for their aliases.
Extend that, by allowing the VPN to specify that it supports addition
for the aliased service-types.
https://bugzilla.gnome.org/show_bug.cgi?id=767197
shared/Makefile.am | 3 +-
shared/nm-vpn-editor-plugin-call.h | 184 ++++++++++++++++++++++++++++
src/connection-editor/ce-new-connection.ui | 10 +-
src/connection-editor/connection-helpers.c | 100 ++++++++++------
src/connection-editor/vpn-helpers.c | 1 +
5 files changed, 258 insertions(+), 40 deletions(-)
---
diff --git a/shared/Makefile.am b/shared/Makefile.am
index 8ee639d..28b0bf2 100644
--- a/shared/Makefile.am
+++ b/shared/Makefile.am
@@ -4,4 +4,5 @@ EXTRA_DIST = \
nm-default.h \
nm-glib.h \
nm-macros-internal.h \
- nm-test-utils.h
+ nm-test-utils.h \
+ nm-vpn-editor-plugin-call.h
diff --git a/shared/nm-vpn-editor-plugin-call.h b/shared/nm-vpn-editor-plugin-call.h
new file mode 100644
index 0000000..584f378
--- /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__ */
diff --git a/src/connection-editor/ce-new-connection.ui b/src/connection-editor/ce-new-connection.ui
index ec4a3c9..3512dbb 100644
--- a/src/connection-editor/ce-new-connection.ui
+++ b/src/connection-editor/ce-new-connection.ui
@@ -4,14 +4,16 @@
<requires lib="gtk+" version="3.0"/>
<object class="GtkListStore" id="new_connection_combo_model">
<columns>
- <!-- column-name name -->
+ <!-- column-name name, COL_MARKUP -->
<column type="gchararray"/>
- <!-- column-name sensitive -->
+ <!-- column-name sensitive, COL_SENSITIVE -->
<column type="gboolean"/>
- <!-- column-name new_func -->
+ <!-- column-name new_func, COL_NEW_FUNC -->
<column type="gpointer"/>
- <!-- column-name vpn_plugin -->
+ <!-- column-name vpn_plugin, COL_VPN_PLUGIN -->
<column type="GObject"/>
+ <!-- column-name vpn_service_type, COL_VPN_SERVICE_TYPE -->
+ <column type="gchararray"/>
</columns>
</object>
<object class="GtkDialog" id="new_connection_type_dialog">
diff --git a/src/connection-editor/connection-helpers.c b/src/connection-editor/connection-helpers.c
index 9cc789c..997006c 100644
--- a/src/connection-editor/connection-helpers.c
+++ b/src/connection-editor/connection-helpers.c
@@ -35,11 +35,13 @@
#include "page-vlan.h"
#include "page-vpn.h"
#include "vpn-helpers.h"
+#include "nm-vpn-editor-plugin-call.h"
#define COL_MARKUP 0
#define COL_SENSITIVE 1
#define COL_NEW_FUNC 2
#define COL_VPN_PLUGIN 3
+#define COL_VPN_SERVICE_TYPE 4
static gint
sort_types (gconstpointer a, gconstpointer b)
@@ -141,8 +143,10 @@ combo_changed_cb (GtkComboBox *combo, gpointer user_data)
GtkLabel *label = GTK_LABEL (user_data);
GtkTreeModel *model;
GtkTreeIter iter;
- NMVpnEditorPlugin *plugin = NULL;
- char *description, *markup;
+ gs_unref_object NMVpnEditorPlugin *plugin = NULL;
+ gs_free char *service_type = NULL;
+ gs_free char *description = NULL;
+ gs_free char *markup = NULL;
if (!gtk_combo_box_get_active_iter (combo, &iter))
goto error;
@@ -151,19 +155,21 @@ combo_changed_cb (GtkComboBox *combo, gpointer user_data)
if (!model)
goto error;
- gtk_tree_model_get (model, &iter, COL_VPN_PLUGIN, &plugin, -1);
- if (!plugin)
+ gtk_tree_model_get (model, &iter,
+ COL_VPN_PLUGIN, &plugin,
+ COL_VPN_SERVICE_TYPE, &service_type,
+ -1);
+ if (!plugin || !service_type)
goto error;
- g_object_get (G_OBJECT (plugin), NM_VPN_EDITOR_PLUGIN_DESCRIPTION, &description, NULL);
- g_object_unref (plugin);
+ if (!nm_vpn_editor_plugin_get_service_info (plugin, service_type, NULL, NULL, &description, NULL))
+ g_object_get (G_OBJECT (plugin), NM_VPN_EDITOR_PLUGIN_DESCRIPTION, &description, NULL);
+
if (!description)
goto error;
markup = g_markup_printf_escaped ("<i>%s</i>", description);
gtk_label_set_markup (label, markup);
- g_free (markup);
- g_free (description);
return;
error:
@@ -259,24 +265,56 @@ set_up_connection_type_combo (GtkComboBox *combo,
}
for (p = vpn_plugins; p; p = p->next) {
- NMVpnEditorPlugin *plugin = nm_vpn_plugin_info_get_editor_plugin (p->data);
- char *desc;
+ NMVpnPluginInfo *plugin_info = p->data;
+ NMVpnEditorPlugin *plugin;
+ const char *const*aliases;
+ const char *service_type;
+ gboolean is_alias = FALSE;
+
+ plugin = nm_vpn_plugin_info_get_editor_plugin (plugin_info);
+ if (!plugin)
+ continue;
- g_object_get (plugin, NM_VPN_EDITOR_PLUGIN_NAME, &desc, NULL);
+ service_type = nm_vpn_plugin_info_get_service (plugin_info);
+ aliases = nm_vpn_plugin_info_get_aliases (plugin_info);
+
+ for (;;) {
+ gs_free char *pretty_name = NULL;
+ NMVpnEditorPluginServiceFlags flags;
+
+ if (!nm_vpn_editor_plugin_get_service_info (plugin, service_type, NULL, &pretty_name,
NULL, &flags)) {
+ if (!is_alias)
+ goto next;
+ g_object_get (plugin, NM_VPN_EDITOR_PLUGIN_NAME, &pretty_name, NULL);
+ flags = NM_VPN_EDITOR_PLUGIN_SERVICE_FLAGS_CAN_ADD;
+ }
+ if (!pretty_name)
+ goto next;
+ if (!NM_FLAGS_HAS (flags, NM_VPN_EDITOR_PLUGIN_SERVICE_FLAGS_CAN_ADD))
+ goto next;
+
+ if (show_headers)
+ markup = g_markup_printf_escaped (" %s", pretty_name);
+ else
+ markup = g_markup_escape_text (pretty_name, -1);
- if (show_headers)
- markup = g_markup_printf_escaped (" %s", desc);
- else
- markup = g_markup_escape_text (desc, -1);
- gtk_list_store_append (model, &iter);
- gtk_list_store_set (model, &iter,
- COL_MARKUP, markup,
- COL_SENSITIVE, TRUE,
- COL_NEW_FUNC, list[vpn_index].new_connection_func,
- COL_VPN_PLUGIN, plugin,
- -1);
- g_free (markup);
- g_free (desc);
+ gtk_list_store_append (model, &iter);
+ gtk_list_store_set (model, &iter,
+ COL_MARKUP, markup,
+ COL_SENSITIVE, TRUE,
+ COL_NEW_FUNC, list[vpn_index].new_connection_func,
+ COL_VPN_PLUGIN, plugin,
+ COL_VPN_SERVICE_TYPE, service_type,
+ -1);
+ g_free (markup);
+
+next:
+ if (!aliases || !aliases[0])
+ break;
+ is_alias = TRUE;
+ service_type = aliases[0];
+ aliases++;
+ }
if (nm_vpn_editor_plugin_get_capabilities (plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT)
import_supported = TRUE;
@@ -389,8 +427,7 @@ new_connection_dialog_full (GtkWindow *parent_window,
GtkTreeIter iter;
int response;
PageNewConnectionFunc new_func = NULL;
- NMVpnEditorPlugin *plugin = NULL;
- char *vpn_type = NULL;
+ gs_free char *vpn_service_type = NULL;
GError *error = NULL;
/* load GUI */
@@ -425,24 +462,17 @@ new_connection_dialog_full (GtkWindow *parent_window,
gtk_combo_box_get_active_iter (combo, &iter);
gtk_tree_model_get (gtk_combo_box_get_model (combo), &iter,
COL_NEW_FUNC, &new_func,
- COL_VPN_PLUGIN, &plugin,
+ COL_VPN_SERVICE_TYPE, &vpn_service_type,
-1);
-
- if (plugin) {
- g_object_get (G_OBJECT (plugin), NM_VPN_EDITOR_PLUGIN_SERVICE, &vpn_type, NULL);
- g_object_unref (plugin);
- }
}
gtk_widget_destroy (GTK_WIDGET (type_dialog));
g_object_unref (gui);
if (new_func)
- new_connection_of_type (parent_window, vpn_type, client, new_func, result_func, user_data);
+ new_connection_of_type (parent_window, vpn_service_type, client, new_func, result_func,
user_data);
else
result_func (NULL, user_data);
-
- g_free (vpn_type);
}
typedef struct {
diff --git a/src/connection-editor/vpn-helpers.c b/src/connection-editor/vpn-helpers.c
index 0fd3f98..4a875ed 100644
--- a/src/connection-editor/vpn-helpers.c
+++ b/src/connection-editor/vpn-helpers.c
@@ -337,3 +337,4 @@ vpn_supports_ipv6 (NMConnection *connection)
capabilities = nm_vpn_editor_plugin_get_capabilities (plugin);
return (capabilities & NM_VPN_EDITOR_PLUGIN_CAPABILITY_IPV6) != 0;
}
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]