example: rework "vpn-import-libnm" example

- add more error handling and free/unref data.

- split code in 3 functions: vpn_connection_import(),
  connection_add() and main(). These steps are mostly
  independent, and having them in separate functions
  makes their separation clearer.

- handle error from nm_client_add_connection_async() to
  exit program with non zero exit code.
This commit is contained in:
Thomas Haller
2021-04-01 21:16:01 +02:00
parent 24bcb8e3e4
commit ca607d2eff

View File

@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* SPDX-License-Identifier: LGPL-2.1-or-later */
/* /*
* The example shows how to import VPN connection from a file. * The example shows how to import VPN connection from a file.
*
* @author: Jagadeesh Kotra <jagadeesh@stdin.top> * @author: Jagadeesh Kotra <jagadeesh@stdin.top>
* *
* Compile with: * Compile with:
@@ -9,66 +10,154 @@
#include <glib.h> #include <glib.h>
#include <NetworkManager.h> #include <NetworkManager.h>
#include <stdlib.h>
static void /*****************************************************************************/
add_cb(NMClient *client, GAsyncResult *result, GMainLoop *loop)
static NMConnection *
vpn_connection_import(const char *filename)
{ {
GError *err = NULL; NMConnection *conn = NULL;
nm_client_add_connection_finish(client, result, &err); GSList * plugins;
if (err != NULL) { GSList * iter;
g_print("Error: %s\n", err->message);
} else { g_print("Try to import file \"%s\"...\n", filename);
g_print("Connection Added.\n");
plugins = nm_vpn_plugin_info_list_load();
for (iter = plugins; iter; iter = iter->next) {
GError * error = NULL;
NMVpnPluginInfo * plugin = iter->data;
NMVpnEditorPlugin *editor;
const char * plugin_name = nm_vpn_plugin_info_get_name(plugin);
g_print("plugin[%s]: trying import...\n", plugin_name);
editor = nm_vpn_plugin_info_load_editor_plugin(plugin, &error);
if (error) {
g_print("plugin[%s]: error loading plugin: %s\n", plugin_name, error->message);
g_clear_error(&error);
continue;
} }
g_main_loop_quit(loop); conn = nm_vpn_editor_plugin_import(editor, filename, &error);
if (error) {
g_print("plugin[%s]: error importing file: %s\n", plugin_name, error->message);
g_clear_error(&error);
continue;
}
if (!nm_connection_normalize(conn, NULL, NULL, &error)) {
g_print("plugin[%s]: imported connection invalid: %s\n", plugin_name, error->message);
g_clear_error(&error);
g_clear_object(&conn);
continue;
}
g_print("plugin[%s]: imported connection \"%s\" (%s)\n",
plugin_name,
nm_connection_get_id(conn),
nm_connection_get_uuid(conn));
break;
}
g_slist_free_full(plugins, g_object_unref);
if (!conn) {
g_print("Failure to import the file with any plugin\n");
return NULL;
}
return conn;
} }
/*****************************************************************************/
typedef struct {
GMainLoop * loop;
GError * error;
NMRemoteConnection *rconn;
} RequestData;
static void
add_cb(GObject *source, GAsyncResult *result, gpointer user_data)
{
RequestData *rdata = user_data;
rdata->rconn = nm_client_add_connection_finish(NM_CLIENT(source), result, &rdata->error);
g_main_loop_quit(rdata->loop);
}
static NMRemoteConnection *
connection_add(NMConnection *conn)
{
GError * error = NULL;
NMClient * client;
RequestData rdata;
g_print("Adding connection \"%s\" (%s)\n",
nm_connection_get_id(conn),
nm_connection_get_uuid(conn));
client = nm_client_new(NULL, &error);
if (!client) {
g_print("Failure to connect with NetworkManager: %s\n", error->message);
return NULL;
}
g_print("Adding connection \"%s\" (%s)\n",
nm_connection_get_id(conn),
nm_connection_get_uuid(conn));
rdata = (RequestData){
.loop = g_main_loop_new(NULL, FALSE),
.rconn = NULL,
.error = NULL,
};
nm_client_add_connection_async(client, conn, TRUE, NULL, add_cb, &rdata);
g_main_loop_run(rdata.loop);
g_clear_pointer(&rdata.loop, g_main_loop_unref);
if (rdata.error != NULL) {
g_print("Error: %s\n", rdata.error->message);
g_clear_error(&rdata.error);
} else {
g_print("Connection successfully added: %s\n", nm_object_get_path(NM_OBJECT(rdata.rconn)));
}
g_clear_object(&client);
return rdata.rconn;
}
/*****************************************************************************/
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
GMainLoop * loop = g_main_loop_new(NULL, FALSE); NMRemoteConnection *rconn;
GSList * plugins; NMConnection * conn;
GSList * iter; const char * filename;
NMVpnEditorPlugin *editor; gboolean success;
NMClient * client;
GError * err = NULL;
NMConnection * conn = NULL;
if (argc < 2) { if (argc < 2) {
g_print("program takes exactly one(1) argument.\n"); g_print("program takes exactly one(1) argument.\n");
exit(1); return 1;
} }
plugins = nm_vpn_plugin_info_list_load(); filename = argv[1];
g_assert(plugins != NULL);
for (iter = plugins; iter; iter = iter->next) { conn = vpn_connection_import(filename);
const char *plugin_name = nm_vpn_plugin_info_get_name(iter->data); if (!conn)
g_print("Trying Plugin: %s\n", plugin_name); return 1;
//try to load plugin rconn = connection_add(conn);
editor = nm_vpn_plugin_info_load_editor_plugin(iter->data, NULL);
conn = nm_vpn_editor_plugin_import(editor, argv[1], &err); success = (rconn != NULL);
if (err != NULL) {
g_print("Error: %s\n", err->message);
g_error_free(err);
err = NULL;
} else {
g_print("%s imported with %s plugin.\n", argv[1], plugin_name);
break;
}
}
g_slist_free_full(plugins, g_object_unref); g_clear_object(&conn);
g_assert(conn != NULL); g_clear_object(&rconn);
client = nm_client_new(NULL, NULL); return success ? 0 : 1;
nm_client_add_connection_async(client, conn, TRUE, NULL, (GAsyncReadyCallback) add_cb, loop);
g_main_loop_run(loop);
return 0;
} }