From ca607d2effe1f8d9a29a9f6792c487aa872fa1a3 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 1 Apr 2021 21:16:01 +0200 Subject: [PATCH] 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. --- examples/C/glib/vpn-import-libnm.c | 175 ++++++++++++++++++++++------- 1 file changed, 132 insertions(+), 43 deletions(-) diff --git a/examples/C/glib/vpn-import-libnm.c b/examples/C/glib/vpn-import-libnm.c index 6a563bac2d..55ed5175c1 100644 --- a/examples/C/glib/vpn-import-libnm.c +++ b/examples/C/glib/vpn-import-libnm.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * The example shows how to import VPN connection from a file. + * * @author: Jagadeesh Kotra * * Compile with: @@ -9,66 +10,154 @@ #include #include -#include -static void -add_cb(NMClient *client, GAsyncResult *result, GMainLoop *loop) +/*****************************************************************************/ + +static NMConnection * +vpn_connection_import(const char *filename) { - GError *err = NULL; - nm_client_add_connection_finish(client, result, &err); - if (err != NULL) { - g_print("Error: %s\n", err->message); - } else { - g_print("Connection Added.\n"); + NMConnection *conn = NULL; + GSList * plugins; + GSList * iter; + + g_print("Try to import file \"%s\"...\n", filename); + + 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; + } + + 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; } - g_main_loop_quit(loop); + 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 main(int argc, char **argv) { - GMainLoop * loop = g_main_loop_new(NULL, FALSE); - GSList * plugins; - GSList * iter; - NMVpnEditorPlugin *editor; - NMClient * client; - GError * err = NULL; - NMConnection * conn = NULL; + NMRemoteConnection *rconn; + NMConnection * conn; + const char * filename; + gboolean success; if (argc < 2) { g_print("program takes exactly one(1) argument.\n"); - exit(1); + return 1; } - plugins = nm_vpn_plugin_info_list_load(); - g_assert(plugins != NULL); + filename = argv[1]; - for (iter = plugins; iter; iter = iter->next) { - const char *plugin_name = nm_vpn_plugin_info_get_name(iter->data); - g_print("Trying Plugin: %s\n", plugin_name); + conn = vpn_connection_import(filename); + if (!conn) + return 1; - //try to load plugin - editor = nm_vpn_plugin_info_load_editor_plugin(iter->data, NULL); + rconn = connection_add(conn); - conn = nm_vpn_editor_plugin_import(editor, argv[1], &err); - 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; - } - } + success = (rconn != NULL); - g_slist_free_full(plugins, g_object_unref); - g_assert(conn != NULL); + g_clear_object(&conn); + g_clear_object(&rconn); - client = nm_client_new(NULL, NULL); - - nm_client_add_connection_async(client, conn, TRUE, NULL, (GAsyncReadyCallback) add_cb, loop); - g_main_loop_run(loop); - - return 0; + return success ? 0 : 1; }