diff options
author | Thomas Haller <thaller@redhat.com> | 2021-04-01 21:16:01 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2021-04-01 21:16:01 +0200 |
commit | ca607d2effe1f8d9a29a9f6792c487aa872fa1a3 (patch) | |
tree | 6aca847c301c8b63f346173b92c85c4b45a6e24a | |
parent | 24bcb8e3e41219601e8ba7e5f53adb55fbcbc02f (diff) | |
download | NetworkManager-ca607d2effe1f8d9a29a9f6792c487aa872fa1a3.tar.gz |
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.
-rw-r--r-- | examples/C/glib/vpn-import-libnm.c | 171 |
1 files changed, 130 insertions, 41 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 <jagadeesh@stdin.top> * * Compile with: @@ -9,66 +10,154 @@ #include <glib.h> #include <NetworkManager.h> -#include <stdlib.h> + +/*****************************************************************************/ + +static NMConnection * +vpn_connection_import(const char *filename) +{ + 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; + } + + return conn; +} + +/*****************************************************************************/ + +typedef struct { + GMainLoop * loop; + GError * error; + NMRemoteConnection *rconn; +} RequestData; static void -add_cb(NMClient *client, GAsyncResult *result, GMainLoop *loop) +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 *err = NULL; - nm_client_add_connection_finish(client, result, &err); - if (err != NULL) { - g_print("Error: %s\n", err->message); + 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 Added.\n"); + g_print("Connection successfully added: %s\n", nm_object_get_path(NM_OBJECT(rdata.rconn))); } - g_main_loop_quit(loop); + 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); - - //try to load plugin - editor = nm_vpn_plugin_info_load_editor_plugin(iter->data, NULL); - - 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; - } - } + conn = vpn_connection_import(filename); + if (!conn) + return 1; - g_slist_free_full(plugins, g_object_unref); - g_assert(conn != NULL); + rconn = connection_add(conn); - client = nm_client_new(NULL, NULL); + success = (rconn != NULL); - nm_client_add_connection_async(client, conn, TRUE, NULL, (GAsyncReadyCallback) add_cb, loop); - g_main_loop_run(loop); + g_clear_object(&conn); + g_clear_object(&rconn); - return 0; + return success ? 0 : 1; } |