[network-manager-openvpn: 13/16] properties: split libnm-vpn-plugin-openvpn.so in two libraries



commit c7764e0f8b3428bc3061f4ddb7b0456ef8a1c765
Author: Thomas Haller <thaller redhat com>
Date:   Thu Apr 28 21:19:44 2016 +0200

    properties: split libnm-vpn-plugin-openvpn.so in two libraries
    
    Split "libnm-vpn-plugin-openvpn-editor.so" out of "libnm-vpn-plugin-openvpn.so".
    The new library contains the GTK dependent code, making the remaining
    core plugin independent of the GUI.
    
    For the new libnm-based plugin, the get_editor() function will now
    dlopen a second plugin and load the NMVpnEditor instance from there.

 Makefile.am                                    |    4 +-
 configure.ac                                   |    8 ++-
 po/POTFILES.in                                 |    1 +
 properties/Makefile.am                         |   54 ++++++++---
 properties/auth-helpers.c                      |    1 -
 properties/libnm-vpn-plugin-openvpn-editor.ver |    6 +
 properties/nm-openvpn-editor-plugin.c          |   39 +++++++-
 properties/nm-openvpn-editor-plugin.h          |    8 ++
 properties/nm-openvpn-editor.c                 |   18 +++-
 shared/Makefile.am                             |   18 +++-
 shared/nm-vpn-plugin-utils.c                   |  130 ++++++++++++++++++++++++
 shared/nm-vpn-plugin-utils.h                   |   40 +++++++
 12 files changed, 305 insertions(+), 22 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 558cfe9..b6f9cab 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -19,7 +19,7 @@ install-data-hook:
        mkdir -p $(DESTDIR)$(sysconfdir)/NetworkManager/VPN
        sed -e "1s|^|# This file is obsoleted by a file in $(NM_VPN_SERVICE_DIR)\n\n|" \
            -e 's|[ ]LIBEXECDIR[@]|$(libexecdir)|g' \
-           -e 's|[ ]PLUGINDIR[@]|$(libdir)/NetworkManager|g' \
+           -e 's|[ ]PLUGINDIR[@]|@NM_PLUGIN_DIR@|g' \
            <$(srcdir)/nm-openvpn-service.name.in \
            >$(DESTDIR)$(sysconfdir)/NetworkManager/VPN/nm-openvpn-service.name
 
@@ -34,7 +34,7 @@ appdata_in_files = appdata/network-manager-openvpn.metainfo.xml.in
 
 nm-openvpn-service.name: $(srcdir)/nm-openvpn-service.name.in
        sed -e 's|[ ]LIBEXECDIR[@]|$(libexecdir)|g' \
-           -e 's|[ ]PLUGINDIR[@]/|@NM_PLUGIN_DIR@|g' \
+           -e 's|[ ]PLUGINDIR[@]/|@NM_PLUGIN_DIR_NAME_FILE@|g' \
            $^ >$@
 
 DISTCHECK_CONFIGURE_FLAGS = \
diff --git a/configure.ac b/configure.ac
index 340cb66..e33ed18 100644
--- a/configure.ac
+++ b/configure.ac
@@ -95,8 +95,14 @@ AC_SUBST(NM_VPN_SERVICE_DIR)
 
 NM_COMPILER_WARNINGS
 
-test x"$enable_absolute_paths" = x"yes" && NM_PLUGIN_DIR='$(libdir)/NetworkManager/'
+NM_PLUGIN_DIR="$libdir/NetworkManager"
 AC_SUBST(NM_PLUGIN_DIR)
+if test x"$enable_absolute_paths" == x"yes"; then
+       NM_PLUGIN_DIR_NAME_FILE="$NM_PLUGIN_DIR/"
+else
+       NM_PLUGIN_DIR_NAME_FILE=""
+fi
+AC_SUBST(NM_PLUGIN_DIR_NAME_FILE)
 
 dnl
 dnl Tests
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 5dc1db0..45b72a7 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -7,6 +7,7 @@ properties/import-export.c
 properties/nm-openvpn-editor-plugin.c
 properties/nm-openvpn-editor.c
 shared/nm-shared-utils.c
+shared/nm-vpn-plugin-utils.c
 src/nm-openvpn-service.c
 src/nm-openvpn-service-openvpn-helper.c
 [type: gettext/glade]properties/nm-openvpn-dialog.ui
diff --git a/properties/Makefile.am b/properties/Makefile.am
index 2270024..228c854 100644
--- a/properties/Makefile.am
+++ b/properties/Makefile.am
@@ -1,7 +1,9 @@
 SUBDIRS = . tests
 
 plugindir = $(libdir)/NetworkManager
-plugin_LTLIBRARIES = libnm-vpn-plugin-openvpn.la
+plugin_LTLIBRARIES = \
+    libnm-vpn-plugin-openvpn.la \
+    libnm-vpn-plugin-openvpn-editor.la
 if WITH_LIBNM_GLIB
 plugin_LTLIBRARIES += libnm-openvpn-properties.la
 endif
@@ -9,21 +11,21 @@ endif
 plugin_sources = \
         nm-openvpn-editor-plugin.c \
         nm-openvpn-editor-plugin.h \
+        import-export.c \
+        import-export.h
+
+editor_sources = \
         nm-openvpn-editor.c \
         nm-openvpn-editor.h \
         auth-helpers.c \
-        auth-helpers.h \
-        import-export.c \
-        import-export.h
+        auth-helpers.h
 
 uidir = $(datadir)/gnome-vpn-properties/openvpn
 ui_DATA = nm-openvpn-dialog.ui
 
 common_CFLAGS =                                         \
         $(GLIB_CFLAGS)                                  \
-        $(GTK_CFLAGS)                                   \
         -I$(top_srcdir)/shared                          \
-        -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIB \
         -DICONDIR=\""$(datadir)/pixmaps"\"              \
         -DUIDIR=\""$(uidir)"\"                          \
         -DLOCALEDIR=\"$(datadir)/locale\"
@@ -35,13 +37,13 @@ libnm_vpn_plugin_openvpn_la_SOURCES = \
 
 libnm_vpn_plugin_openvpn_la_CFLAGS =                    \
         $(common_CFLAGS)                                \
-        $(LIBNM_CFLAGS)                                 \
-        $(LIBNMA_CFLAGS)
+        -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIB_BASE \
+        -DNM_PLUGIN_DIR=\"$(NM_PLUGIN_DIR)\" \
+        $(LIBNM_CFLAGS)
 
-libnm_vpn_plugin_openvpn_la_LIBADD =                    \
-        $(GTK_LIBS)                                     \
-        $(LIBNM_LIBS)                                   \
-        $(LIBNMA_LIBS)                                  \
+libnm_vpn_plugin_openvpn_la_LIBADD = \
+        $(LIBNM_LIBS) \
+        $(top_builddir)/shared/libnm-vpn-editor-utils-shared.la \
         $(top_builddir)/shared/libnm-vpn-plugin-openvpn-shared.la
 
 libnm_vpn_plugin_openvpn_la_LDFLAGS = \
@@ -50,12 +52,37 @@ libnm_vpn_plugin_openvpn_la_LDFLAGS = \
 
 ###############################################################################
 
+libnm_vpn_plugin_openvpn_editor_la_SOURCES = \
+        $(editor_sources)
+
+libnm_vpn_plugin_openvpn_editor_la_CFLAGS = \
+        $(common_CFLAGS) \
+        $(GTK_CFLAGS) \
+        -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIB_EDITOR \
+        $(LIBNM_CFLAGS) \
+        $(LIBNMA_CFLAGS)
+
+libnm_vpn_plugin_openvpn_editor_la_LIBADD = \
+        $(GTK_LIBS) \
+        $(LIBNM_LIBS) \
+        $(LIBNMA_LIBS) \
+        $(top_builddir)/shared/libnm-vpn-plugin-openvpn-shared.la
+
+libnm_vpn_plugin_openvpn_editor_la_LDFLAGS = \
+        -avoid-version \
+        -Wl,--version-script=$(srcdir)/libnm-vpn-plugin-openvpn-editor.ver
+
+###############################################################################
+
 libnm_openvpn_properties_la_SOURCES = \
-        $(plugin_sources)
+        $(plugin_sources) \
+        $(editor_sources)
 
 libnm_openvpn_properties_la_CFLAGS =                \
         -DNM_OPENVPN_OLD \
         $(common_CFLAGS)                                \
+        $(GTK_CFLAGS) \
+        -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIB \
         $(LIBNM_GLIB_CFLAGS)                            \
         $(LIBNM_GTK_CFLAGS)
 
@@ -95,6 +122,7 @@ CLEANFILES = *.bak *~
 
 EXTRA_DIST = \
         libnm-vpn-plugin-openvpn.ver \
+        libnm-vpn-plugin-openvpn-editor.ver \
         libnm-openvpn-properties.ver \
         $(ui_DATA)
 
diff --git a/properties/auth-helpers.c b/properties/auth-helpers.c
index c56fc0d..746709b 100644
--- a/properties/auth-helpers.c
+++ b/properties/auth-helpers.c
@@ -33,7 +33,6 @@
 #include <unistd.h>
 #include <errno.h>
 
-#include "nm-openvpn-editor.h"
 #include "utils.h"
 
 #define BLOCK_HANDLER_ID "block-handler-id"
diff --git a/properties/libnm-vpn-plugin-openvpn-editor.ver b/properties/libnm-vpn-plugin-openvpn-editor.ver
new file mode 100644
index 0000000..542d577
--- /dev/null
+++ b/properties/libnm-vpn-plugin-openvpn-editor.ver
@@ -0,0 +1,6 @@
+{
+global:
+       nm_vpn_editor_factory_openvpn;
+local:
+       *;
+};
diff --git a/properties/nm-openvpn-editor-plugin.c b/properties/nm-openvpn-editor-plugin.c
index 50c7fb2..90d1d72 100644
--- a/properties/nm-openvpn-editor-plugin.c
+++ b/properties/nm-openvpn-editor-plugin.c
@@ -33,8 +33,12 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "auth-helpers.h"
+#ifdef NM_OPENVPN_OLD
 #include "nm-openvpn-editor.h"
+#else
+#include "nm-vpn-plugin-utils.h"
+#endif
+
 #include "import-export.h"
 
 #define OPENVPN_PLUGIN_NAME    _("OpenVPN")
@@ -122,10 +126,40 @@ get_capabilities (NMVpnEditorPlugin *iface)
                NM_VPN_EDITOR_PLUGIN_CAPABILITY_IPV6);
 }
 
+#ifndef NM_OPENVPN_OLD
+static NMVpnEditor *
+_call_editor_factory (gpointer factory,
+                      NMVpnEditorPlugin *editor_plugin,
+                      NMConnection *connection,
+                      gpointer user_data,
+                      GError **error)
+{
+       return ((NMVpnEditorFactory) factory) (editor_plugin,
+                                              connection,
+                                              error);
+}
+#endif
+
 static NMVpnEditor *
 get_editor (NMVpnEditorPlugin *iface, NMConnection *connection, GError **error)
 {
-       return openvpn_editor_new (connection, error);
+       g_return_val_if_fail (OPENVPN_IS_EDITOR_PLUGIN (iface), NULL);
+       g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+       g_return_val_if_fail (!error || !*error, NULL);
+
+       {
+#ifdef NM_OPENVPN_OLD
+               return openvpn_editor_new (connection, error);
+#else
+               return nm_vpn_plugin_utils_load_editor (NM_PLUGIN_DIR"/libnm-vpn-plugin-openvpn-editor.so",
+                                                       "nm_vpn_editor_factory_openvpn",
+                                                       _call_editor_factory,
+                                                       iface,
+                                                       connection,
+                                                       NULL,
+                                                       error);
+#endif
+       }
 }
 
 /*****************************************************************************/
@@ -158,7 +192,6 @@ openvpn_editor_plugin_init (OpenvpnEditorPlugin *plugin)
 static void
 openvpn_editor_plugin_interface_init (NMVpnEditorPluginInterface *iface_class)
 {
-       /* interface implementation */
        iface_class->get_editor = get_editor;
        iface_class->get_capabilities = get_capabilities;
        iface_class->import_from_file = import;
diff --git a/properties/nm-openvpn-editor-plugin.h b/properties/nm-openvpn-editor-plugin.h
index 2ccdd65..df7808f 100644
--- a/properties/nm-openvpn-editor-plugin.h
+++ b/properties/nm-openvpn-editor-plugin.h
@@ -43,6 +43,14 @@ struct _OpenvpnEditorPluginClass {
 
 GType openvpn_editor_plugin_get_type (void);
 
+typedef NMVpnEditor *(*NMVpnEditorFactory) (NMVpnEditorPlugin *editor_plugin,
+                                            NMConnection *connection,
+                                            GError **error);
+
+NMVpnEditor *
+nm_vpn_editor_factory_openvpn (NMVpnEditorPlugin *editor_plugin,
+                               NMConnection *connection,
+                               GError **error);
 
 #endif /* __NM_OPENVPN_EDITOR_PLUGIN_H__ */
 
diff --git a/properties/nm-openvpn-editor.c b/properties/nm-openvpn-editor.c
index e904d4c..15bcf55 100644
--- a/properties/nm-openvpn-editor.c
+++ b/properties/nm-openvpn-editor.c
@@ -37,7 +37,6 @@
 #include <gtk/gtk.h>
 
 #include "auth-helpers.h"
-#include "import-export.h"
 
 /*****************************************************************************/
 
@@ -588,3 +587,20 @@ openvpn_editor_plugin_widget_class_init (OpenvpnEditorClass *req_class)
        object_class->dispose = dispose;
 }
 
+/*****************************************************************************/
+
+#ifndef NM_OPENVPN_OLD
+
+#include "nm-openvpn-editor-plugin.h"
+
+G_MODULE_EXPORT NMVpnEditor *
+nm_vpn_editor_factory_openvpn (NMVpnEditorPlugin *editor_plugin,
+                               NMConnection *connection,
+                               GError **error)
+{
+       g_return_val_if_fail (!error || !*error, NULL);
+
+       return openvpn_editor_new (connection, error);
+}
+#endif
+
diff --git a/shared/Makefile.am b/shared/Makefile.am
index b427c63..48dba99 100644
--- a/shared/Makefile.am
+++ b/shared/Makefile.am
@@ -1,4 +1,6 @@
-noinst_LTLIBRARIES=libnm-vpn-plugin-openvpn-shared.la
+noinst_LTLIBRARIES = \
+       libnm-vpn-plugin-openvpn-shared.la \
+       libnm-vpn-editor-utils-shared.la
 if WITH_LIBNM_GLIB
 noinst_LTLIBRARIES += libnm-openvpn-shared.la
 endif
@@ -37,6 +39,20 @@ libnm_openvpn_shared_la_LIBADD = \
 
 ###############################################################################
 
+libnm_vpn_editor_utils_shared_la_CPPFLAGS = \
+    $(LIBNM_CFLAGS) \
+    -I$(top_srcdir)/shared
+
+libnm_vpn_editor_utils_shared_la_SOURCES = \
+    nm-vpn-plugin-utils.c \
+    nm-vpn-plugin-utils.h
+
+libnm_vpn_editor_utils_shared_la_LIBADD = \
+    $(LIBNM_LIBS) \
+    -ldl
+
+###############################################################################
+
 EXTRA_DIST = \
      gsystem-local-alloc.h \
      nm-dbus-compat.h \
diff --git a/shared/nm-vpn-plugin-utils.c b/shared/nm-vpn-plugin-utils.c
new file mode 100644
index 0000000..772aa39
--- /dev/null
+++ b/shared/nm-vpn-plugin-utils.c
@@ -0,0 +1,130 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+/*
+ * 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 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, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2016 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include "nm-vpn-plugin-utils.h"
+
+#include <dlfcn.h>
+
+/*****************************************************************************/
+
+NMVpnEditor *
+nm_vpn_plugin_utils_load_editor (const char *module_name,
+                                 const char *factory_name,
+                                 NMVpnPluginUtilsEditorFactory editor_factory,
+                                 NMVpnEditorPlugin *editor_plugin,
+                                 NMConnection *connection,
+                                 gpointer user_data,
+                                 GError **error)
+
+{
+       static struct {
+               gpointer factory;
+               void *dl_module;
+               char *module_name;
+               char *factory_name;
+       } cached = { 0 };
+       NMVpnEditor *editor;
+
+       g_return_val_if_fail (module_name && g_path_is_absolute (module_name), NULL);
+       g_return_val_if_fail (factory_name && factory_name[0], NULL);
+       g_return_val_if_fail (editor_factory, NULL);
+       g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (editor_plugin), NULL);
+       g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+       g_return_val_if_fail (!error || !*error, NULL);
+
+       /* we really expect this function to be called with unchanging @module_name
+        * and @factory_name. And we only want to load the module once, hence it would
+        * be more complicated to accept changing @module_name/@factory_name arguments.
+        *
+        * The reason for only loading once is that due to glib types, we cannot create a
+        * certain type-name more then once, so loading the same module or another version
+        * of the same module will fail horribly as both try to create a GType with the same
+        * name.
+        *
+        * Only support loading once, any future calls will reuse the handle. To simplify
+        * that, we enforce that the @factory_name and @module_name is the same. */
+       if (cached.factory) {
+               g_return_val_if_fail (cached.dl_module, NULL);
+               g_return_val_if_fail (cached.factory_name && nm_streq0 (cached.factory_name, factory_name), 
NULL);
+               g_return_val_if_fail (cached.module_name && nm_streq0 (cached.module_name, module_name), 
NULL);
+       } else {
+               gpointer factory;
+               void *dl_module;
+
+               dl_module = dlopen (module_name, RTLD_LAZY | RTLD_LOCAL);
+               if (!dl_module) {
+                       if (!g_file_test (module_name, G_FILE_TEST_EXISTS)) {
+                               g_set_error (error,
+                                            G_FILE_ERROR,
+                                            G_FILE_ERROR_NOENT,
+                                            _("missing plugin file \"%s\""), module_name);
+                               return NULL;
+                       }
+                       g_set_error (error,
+                                    NM_CONNECTION_ERROR,
+                                    NM_CONNECTION_ERROR_FAILED,
+                                    _("cannot load editor plugin: %s"), dlerror ());
+                       return NULL;
+               }
+
+               factory = dlsym (dl_module, factory_name);
+               if (!factory) {
+                       g_set_error (error,
+                                    NM_CONNECTION_ERROR,
+                                    NM_CONNECTION_ERROR_FAILED,
+                                    _("cannot load factory %s from plugin: %s"),
+                                    factory_name, dlerror ());
+                       dlclose (dl_module);
+                       return NULL;
+               }
+
+               /* we cannot ever unload the module because it creates glib types, which
+                * cannot be unregistered.
+                *
+                * Thus we just leak the dl_module handle indefinitely. */
+               cached.factory = factory;
+               cached.dl_module = dl_module;
+               cached.module_name = g_strdup (module_name);
+               cached.factory_name = g_strdup (factory_name);
+       }
+
+       editor = editor_factory (cached.factory,
+                                editor_plugin,
+                                connection,
+                                user_data,
+                                error);
+       if (!editor) {
+               if (error && !*error ) {
+                       g_set_error_literal (error,
+                                            NM_CONNECTION_ERROR,
+                                            NM_CONNECTION_ERROR_FAILED,
+                                            _("unknown error creating editor instance"));
+                       g_return_val_if_reached (NULL);
+               }
+               return NULL;
+       }
+
+       g_return_val_if_fail (NM_IS_VPN_EDITOR (editor), NULL);
+       return editor;
+}
+
diff --git a/shared/nm-vpn-plugin-utils.h b/shared/nm-vpn-plugin-utils.h
new file mode 100644
index 0000000..3efad44
--- /dev/null
+++ b/shared/nm-vpn-plugin-utils.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+/*
+ * 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 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, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2016 Red Hat, Inc.
+ */
+
+#ifndef __NM_VPN_PLUGIN_UTILS_H__
+#define __NM_VPN_PLUGIN_UTILS_H__
+
+typedef NMVpnEditor *(NMVpnPluginUtilsEditorFactory) (gpointer factory,
+                                                      NMVpnEditorPlugin *editor_plugin,
+                                                      NMConnection *connection,
+                                                      gpointer user_data,
+                                                      GError **error);
+
+NMVpnEditor *nm_vpn_plugin_utils_load_editor (const char *module_name,
+                                              const char *factory_name,
+                                              NMVpnPluginUtilsEditorFactory editor_factory,
+                                              NMVpnEditorPlugin *editor_plugin,
+                                              NMConnection *connection,
+                                              gpointer user_data,
+                                              GError **error);
+
+#endif /* __NM_VPN_PLUGIN_UTILS_H__ */
+


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]