diff --git a/clients/cli/connections.c b/clients/cli/connections.c index 718b6c0023..e4de756a85 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -228,16 +228,9 @@ static NmcOutputField nmc_fields_con_active_details_groups[] = { #define CON_SHOW_DETAIL_GROUP_PROFILE "profile" #define CON_SHOW_DETAIL_GROUP_ACTIVE "active" -typedef struct { - NmCli *nmc; - int argc; - char **argv; -} ArgsInfo; - /* glib main loop variable - defined in nmcli.c */ extern GMainLoop *loop; -static ArgsInfo args_info; static guint progress_id = 0; /* ID of event source for displaying progress */ /* for readline TAB completion in editor */ @@ -1285,7 +1278,7 @@ do_connections_show (NmCli *nmc, gboolean active_only, int argc, char **argv) nmc->should_wait = FALSE; nmc->get_client (nmc); - if (!nm_client_get_manager_running (nmc->client)) { + if (!nm_client_get_nm_running (nmc->client)) { g_string_printf (nmc->return_text, _("Error: NetworkManager is not running.")); nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING; goto finish; @@ -2009,7 +2002,7 @@ do_connection_up (NmCli *nmc, int argc, char **argv) /* create NMClient */ nmc->get_client (nmc); - if (!nm_client_get_manager_running (nmc->client)) { + if (!nm_client_get_nm_running (nmc->client)) { g_string_printf (nmc->return_text, _("Error: NetworkManager is not running.")); nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING; goto error; @@ -2069,7 +2062,7 @@ do_connection_down (NmCli *nmc, int argc, char **argv) /* create NMClient */ nmc->get_client (nmc); - if (!nm_client_get_manager_running (nmc->client)) { + if (!nm_client_get_nm_running (nmc->client)) { g_string_printf (nmc->return_text, _("Error: NetworkManager is not running.")); nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING; goto error; @@ -8046,7 +8039,7 @@ do_connection_modify (NmCli *nmc, /* create NMClient */ nmc->get_client (nmc); - if (!nm_client_get_manager_running (nmc->client)) { + if (!nm_client_get_nm_running (nmc->client)) { g_string_printf (nmc->return_text, _("Error: NetworkManager is not running.")); nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING; goto finish; @@ -8254,7 +8247,7 @@ do_connection_delete (NmCli *nmc, int argc, char **argv) /* create NMClient */ nmc->get_client (nmc); - if (!nm_client_get_manager_running (nmc->client)) { + if (!nm_client_get_nm_running (nmc->client)) { g_string_printf (nmc->return_text, _("Error: NetworkManager is not running.")); nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING; goto finish; @@ -8347,7 +8340,7 @@ do_connection_reload (NmCli *nmc, int argc, char **argv) nmc->return_value = NMC_RESULT_SUCCESS; nmc->should_wait = FALSE; - if (!nm_client_get_manager_running (nmc->client)) { + if (!nm_client_get_nm_running (nmc->client)) { g_string_printf (nmc->return_text, _("Error: NetworkManager is not running.")); nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING; return nmc->return_value; @@ -8375,7 +8368,7 @@ do_connection_load (NmCli *nmc, int argc, char **argv) nmc->return_value = NMC_RESULT_SUCCESS; nmc->should_wait = FALSE; - if (!nm_client_get_manager_running (nmc->client)) { + if (!nm_client_get_nm_running (nmc->client)) { g_string_printf (nmc->return_text, _("Error: NetworkManager is not running.")); nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING; return nmc->return_value; @@ -8607,21 +8600,6 @@ opt_error: return nmc->return_value; } -/* callback called when connections are obtained from the settings service */ -static void -get_connections_cb (NMRemoteSettings *settings, gpointer user_data) -{ - ArgsInfo *args = (ArgsInfo *) user_data; - - /* Get the connection list */ - args->nmc->system_connections = nm_remote_settings_list_connections (settings); - - parse_cmd (args->nmc, args->argc, args->argv); - - if (!args->nmc->should_wait) - quit (); -} - /* Entry point function for connections-related commands: 'nmcli connection' */ NMCResultCode do_connections (NmCli *nmc, int argc, char **argv) @@ -8651,10 +8629,6 @@ do_connections (NmCli *nmc, int argc, char **argv) nmc->should_wait = TRUE; - args_info.nmc = nmc; - args_info.argc = argc; - args_info.argv = argv; - /* get system settings */ if (!(nmc->system_settings = nm_remote_settings_new (NULL, &error))) { g_string_printf (nmc->return_text, _("Error: Could not get system settings: %s."), error->message); @@ -8665,7 +8639,7 @@ do_connections (NmCli *nmc, int argc, char **argv) } /* find out whether settings service is running */ - g_object_get (nmc->system_settings, NM_REMOTE_SETTINGS_SERVICE_RUNNING, &nmc->system_settings_running, NULL); + g_object_get (nmc->system_settings, NM_REMOTE_SETTINGS_NM_RUNNING, &nmc->system_settings_running, NULL); if (!nmc->system_settings_running) { g_string_printf (nmc->return_text, _("Error: Can't obtain connections: settings service is not running.")); @@ -8674,13 +8648,13 @@ do_connections (NmCli *nmc, int argc, char **argv) return nmc->return_value; } - /* connect to signal "connections-read" - emitted when connections are fetched and ready */ - g_signal_connect (nmc->system_settings, NM_REMOTE_SETTINGS_CONNECTIONS_READ, - G_CALLBACK (get_connections_cb), &args_info); + /* Get the connection list */ + nmc->system_connections = nm_remote_settings_list_connections (nmc->system_settings); - /* The rest will be done in get_connection_cb() callback. - * We need to wait for signals that connections are read. - */ + parse_cmd (nmc, argc, argv); + + if (!nmc->should_wait) + quit (); return NMC_RESULT_SUCCESS; } } diff --git a/clients/cli/devices.c b/clients/cli/devices.c index c548038b79..9db9d59a98 100644 --- a/clients/cli/devices.c +++ b/clients/cli/devices.c @@ -1183,7 +1183,7 @@ do_devices_status (NmCli *nmc, int argc, char **argv) nmc->get_client (nmc); - if (!nm_client_get_manager_running (nmc->client)) { + if (!nm_client_get_nm_running (nmc->client)) { g_string_printf (nmc->return_text, _("Error: NetworkManager is not running.")); nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING; goto error; @@ -1231,7 +1231,7 @@ do_devices_show (NmCli *nmc, int argc, char **argv) nmc->get_client (nmc); - if (!nm_client_get_manager_running (nmc->client)) { + if (!nm_client_get_nm_running (nmc->client)) { g_string_printf (nmc->return_text, _("Error: NetworkManager is not running.")); nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING; goto error; @@ -1394,7 +1394,7 @@ do_device_connect (NmCli *nmc, int argc, char **argv) } nmc->get_client (nmc); - if (!nm_client_get_manager_running (nmc->client)) { + if (!nm_client_get_nm_running (nmc->client)) { g_string_printf (nmc->return_text, _("Error: NetworkManager is not running.")); nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING; goto error; @@ -1528,7 +1528,7 @@ do_device_disconnect (NmCli *nmc, int argc, char **argv) } nmc->get_client (nmc); - if (!nm_client_get_manager_running (nmc->client)) { + if (!nm_client_get_nm_running (nmc->client)) { g_string_printf (nmc->return_text, _("Error: NetworkManager is not running.")); nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING; goto error; @@ -1622,7 +1622,7 @@ do_device_delete (NmCli *nmc, int argc, char **argv) } nmc->get_client (nmc); - if (!nm_client_get_manager_running (nmc->client)) { + if (!nm_client_get_nm_running (nmc->client)) { g_string_printf (nmc->return_text, _("Error: NetworkManager is not running.")); nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING; goto error; @@ -1765,7 +1765,7 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv) nmc->get_client (nmc); - if (!nm_client_get_manager_running (nmc->client)) { + if (!nm_client_get_nm_running (nmc->client)) { g_string_printf (nmc->return_text, _("Error: NetworkManager is not running.")); nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING; goto error; @@ -2209,7 +2209,7 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv) nmc->get_client (nmc); - if (!nm_client_get_manager_running (nmc->client)) { + if (!nm_client_get_nm_running (nmc->client)) { g_string_printf (nmc->return_text, _("Error: NetworkManager is not running.")); nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING; goto error; @@ -2508,7 +2508,7 @@ do_device_wimax_list (NmCli *nmc, int argc, char **argv) nmc->get_client (nmc); - if (!nm_client_get_manager_running (nmc->client)) { + if (!nm_client_get_nm_running (nmc->client)) { g_string_printf (nmc->return_text, _("Error: NetworkManager is not running.")); nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING; goto error; diff --git a/clients/cli/network-manager.c b/clients/cli/network-manager.c index cace83256f..a963a04bfc 100644 --- a/clients/cli/network-manager.c +++ b/clients/cli/network-manager.c @@ -335,7 +335,7 @@ show_nm_status (NmCli *nmc, const char *pretty_header_name, const char *print_fl nmc->get_client (nmc); /* create NMClient */ - nm_running = nm_client_get_manager_running (nmc->client); + nm_running = nm_client_get_nm_running (nmc->client); if (nm_running) { if (!nmc_versions_match (nmc)) return FALSE; @@ -478,7 +478,7 @@ show_nm_permissions (NmCli *nmc) nmc->get_client (nmc); /* create NMClient */ - if (!nm_client_get_manager_running (nmc->client)) { + if (!nm_client_get_nm_running (nmc->client)) { g_string_printf (nmc->return_text, _("Error: NetworkManager is not running.")); nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING; return FALSE; diff --git a/clients/nm-online.c b/clients/nm-online.c index af40022b31..d4397042bb 100644 --- a/clients/nm-online.c +++ b/clients/nm-online.c @@ -62,7 +62,7 @@ client_properties_changed (GObject *object, NMState state; gboolean wait_startup = GPOINTER_TO_UINT (g_object_get_data (object, WAIT_STARTUP_TAG)); - if (!nm_client_get_manager_running (client)) + if (!nm_client_get_nm_running (client)) return; if (wait_startup) { @@ -203,7 +203,7 @@ main (int argc, char *argv[]) g_object_set_data (G_OBJECT (client), WAIT_STARTUP_TAG, GUINT_TO_POINTER (wait_startup)); state = nm_client_get_state (client); - if (!nm_client_get_manager_running (client)) { + if (!nm_client_get_nm_running (client)) { if (exit_no_nm) { g_object_unref (client); return 1; diff --git a/clients/tui/nmt-edit-connection-list.c b/clients/tui/nmt-edit-connection-list.c index 2c2c084646..508f204c39 100644 --- a/clients/tui/nmt-edit-connection-list.c +++ b/clients/tui/nmt-edit-connection-list.c @@ -155,7 +155,7 @@ sort_by_timestamp (gconstpointer a, static void nmt_edit_connection_list_rebuild (NmtEditConnectionList *list); static void -rebuild_on_connection_updated (NMRemoteConnection *connection, +rebuild_on_connection_changed (NMRemoteConnection *connection, gpointer list) { nmt_edit_connection_list_rebuild (list); @@ -171,7 +171,7 @@ free_connections (NmtEditConnectionList *list) for (iter = priv->connections; iter; iter = iter->next) { conn = iter->data; - g_signal_handlers_disconnect_by_func (conn, G_CALLBACK (rebuild_on_connection_updated), list); + g_signal_handlers_disconnect_by_func (conn, G_CALLBACK (rebuild_on_connection_changed), list); g_object_unref (conn); } g_slist_free (priv->connections); @@ -202,10 +202,8 @@ nmt_edit_connection_list_rebuild (NmtEditConnectionList *list) continue; } - g_signal_connect (conn, NM_REMOTE_CONNECTION_UPDATED, - G_CALLBACK (rebuild_on_connection_updated), list); - g_signal_connect (conn, NM_REMOTE_CONNECTION_REMOVED, - G_CALLBACK (rebuild_on_connection_updated), list); + g_signal_connect (conn, NM_CONNECTION_CHANGED, + G_CALLBACK (rebuild_on_connection_changed), list); g_object_ref (iter->data); } priv->connections = g_slist_sort (priv->connections, sort_by_timestamp); @@ -279,9 +277,9 @@ nmt_edit_connection_list_rebuild (NmtEditConnectionList *list) } static void -rebuild_on_new_connection (NMRemoteSettings *settings, - NMRemoteConnection *connection, - gpointer list) +rebuild_on_connections_changed (GObject *object, + GParamSpec *pspec, + gpointer list) { nmt_edit_connection_list_rebuild (list); } @@ -295,8 +293,8 @@ nmt_edit_connection_list_constructed (GObject *object) if (priv->extra) nmt_newt_button_box_add_widget_end (priv->buttons, priv->extra); - g_signal_connect (nm_settings, NM_REMOTE_SETTINGS_NEW_CONNECTION, - G_CALLBACK (rebuild_on_new_connection), list); + g_signal_connect (nm_settings, "notify::" NM_REMOTE_SETTINGS_CONNECTIONS, + G_CALLBACK (rebuild_on_connections_changed), list); nmt_edit_connection_list_rebuild (list); diff --git a/clients/tui/nmtui-edit.c b/clients/tui/nmtui-edit.c index a564ff3685..1757ff4961 100644 --- a/clients/tui/nmtui-edit.c +++ b/clients/tui/nmtui-edit.c @@ -426,6 +426,7 @@ nmt_edit_connection (NMConnection *connection) typedef struct { NmtSyncOp op; gboolean got_callback, got_signal; + NMRemoteConnection *connection; } ConnectionDeleteData; static void @@ -446,14 +447,17 @@ connection_deleted_callback (NMRemoteConnection *connection, } static void -connection_removed_signal (NMRemoteConnection *connection, +connection_removed_signal (NMRemoteSettings *settings, + NMRemoteConnection *connection, gpointer user_data) { ConnectionDeleteData *data = user_data; - data->got_signal = TRUE; - if (data->got_callback && data->got_signal) - nmt_sync_op_complete_boolean (&data->op, TRUE, NULL); + if (connection == data->connection) { + data->got_signal = TRUE; + if (data->got_callback && data->got_signal) + nmt_sync_op_complete_boolean (&data->op, TRUE, NULL); + } } void @@ -473,8 +477,8 @@ nmt_remove_connection (NMRemoteConnection *connection) data.got_callback = data.got_signal = FALSE; nmt_sync_op_init (&data.op); - g_object_ref (connection); - g_signal_connect (connection, NM_REMOTE_CONNECTION_REMOVED, + data.connection = connection; + g_signal_connect (nm_settings, NM_REMOTE_SETTINGS_CONNECTION_REMOVED, G_CALLBACK (connection_removed_signal), &data); nm_remote_connection_delete (connection, connection_deleted_callback, &data); @@ -484,8 +488,7 @@ nmt_remove_connection (NMRemoteConnection *connection) g_error_free (error); } - g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_removed_signal), &data); - g_object_unref (connection); + g_signal_handlers_disconnect_by_func (nm_settings, G_CALLBACK (connection_removed_signal), &data); } NmtNewtForm * diff --git a/clients/tui/nmtui.c b/clients/tui/nmtui.c index 795f663d93..ee63ccf280 100644 --- a/clients/tui/nmtui.c +++ b/clients/tui/nmtui.c @@ -140,15 +140,6 @@ nmtui_quit (void) g_main_loop_quit (loop); } -static void -connections_read (NMRemoteSettings *settings, - gpointer user_data) -{ - gboolean *got_connections = user_data; - - *got_connections = TRUE; -} - static void usage (void) { @@ -217,7 +208,6 @@ GOptionEntry entries[] = { int main (int argc, char **argv) { - gboolean got_connections = FALSE; GOptionContext *opts; GError *error = NULL; NmtuiStartupData startup_data; @@ -249,7 +239,7 @@ main (int argc, char **argv) g_error_free (error); exit (1); } - if (!nm_client_get_manager_running (nm_client)) { + if (!nm_client_get_nm_running (nm_client)) { g_printerr ("%s\n", _("NetworkManager is not running.")); exit (1); } @@ -260,11 +250,6 @@ main (int argc, char **argv) g_error_free (error); exit (1); } - g_signal_connect (nm_settings, NM_REMOTE_SETTINGS_CONNECTIONS_READ, - G_CALLBACK (connections_read), &got_connections); - /* coverity[loop_condition] */ - while (!got_connections) - g_main_context_iteration (NULL, TRUE); if (sleep_on_startup) sleep (5); diff --git a/examples/C/glib/list-connections-libnm.c b/examples/C/glib/list-connections-libnm.c index 4dd178dbf6..1827835948 100644 --- a/examples/C/glib/list-connections-libnm.c +++ b/examples/C/glib/list-connections-libnm.c @@ -27,38 +27,9 @@ #include #include #include -#include #include - -/* Global variables */ -GMainLoop *loop = NULL; /* Main loop variable - needed for waiting for signal */ -int result = EXIT_SUCCESS; - -static void -signal_handler (int signo) -{ - if (signo == SIGINT || signo == SIGTERM) { - g_message ("Caught signal %d, shutting down...", signo); - g_main_loop_quit (loop); - } -} - -static void -setup_signals (void) -{ - struct sigaction action; - sigset_t mask; - - sigemptyset (&mask); - action.sa_handler = signal_handler; - action.sa_mask = mask; - action.sa_flags = 0; - sigaction (SIGTERM, &action, NULL); - sigaction (SIGINT, &action, NULL); -} - /* Print details of connection */ static void show_connection (gpointer data, gpointer user_data) @@ -89,14 +60,35 @@ show_connection (gpointer data, gpointer user_data) } } -/* This callback is called when connections from the settings service are ready. - * Now the connections can be listed. - */ -static void -get_connections_cb (NMRemoteSettings *settings, gpointer user_data) +int +main (int argc, char *argv[]) { + NMRemoteSettings *settings; + gboolean settings_running; + GError *error = NULL; GSList *connections; +#if !GLIB_CHECK_VERSION (2, 35, 0) + /* Initialize GType system */ + g_type_init (); +#endif + + /* Get system settings */ + if (!(settings = nm_remote_settings_new (NULL, &error))) { + g_message ("Error: Could not get system settings: %s.", error->message); + g_error_free (error); + return EXIT_FAILURE; + } + + /* Find out whether setting service is running */ + g_object_get (settings, NM_REMOTE_SETTINGS_NM_RUNNING, &settings_running, NULL); + + if (!settings_running) { + g_message ("Error: Can't obtain connections: settings service is not running."); + return EXIT_FAILURE; + } + + /* Now the connections can be listed. */ connections = nm_remote_settings_list_connections (settings); printf ("Connections:\n===================\n"); @@ -106,68 +98,5 @@ get_connections_cb (NMRemoteSettings *settings, gpointer user_data) g_slist_free (connections); g_object_unref (settings); - /* We are done, exit main loop */ - g_main_loop_quit (loop); -} - -/* Get system settings and then connect to connections-read signal */ -static gboolean -list_connections (gpointer data) -{ - NMRemoteSettings *settings; - gboolean settings_running; - GError *error = NULL; - - /* Get system settings */ - if (!(settings = nm_remote_settings_new (NULL, &error))) { - g_message ("Error: Could not get system settings: %s.", error->message); - g_error_free (error); - result = EXIT_FAILURE; - g_main_loop_quit (loop); - return FALSE; - } - - /* Find out whether setting service is running */ - g_object_get (settings, NM_REMOTE_SETTINGS_SERVICE_RUNNING, &settings_running, NULL); - - if (!settings_running) { - g_message ("Error: Can't obtain connections: settings service is not running."); - result = EXIT_FAILURE; - g_main_loop_quit (loop); - return FALSE; - } - - /* Connect to signal "connections-read" - emitted when connections are fetched and ready */ - g_signal_connect (settings, NM_REMOTE_SETTINGS_CONNECTIONS_READ, - G_CALLBACK (get_connections_cb), NULL); - - return FALSE; -} - -int main (int argc, char *argv[]) -{ - DBusGConnection *bus; - -#if !GLIB_CHECK_VERSION (2, 35, 0) - /* Initialize GType system */ - g_type_init (); -#endif - - /* Get system bus */ - bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL); - - /* Run list_connections from main loop, because we need to wait for "connections-read" - * signal to have connections ready. The execution will be finished in get_connections_cb() - * callback on the signal. - */ - g_idle_add (list_connections, bus); - - loop = g_main_loop_new (NULL, FALSE); /* Create main loop */ - setup_signals (); /* Setup UNIX signals */ - g_main_loop_run (loop); /* Run main loop */ - - g_main_loop_unref (loop); - dbus_g_connection_unref (bus); - - return result; + return EXIT_SUCCESS; } diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index 09ab1ad988..d666a8e837 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -679,5 +679,49 @@ nmtst_ip6_config_clone (NMIP6Config *config) #endif +#ifdef NM_CONNECTION_H + +inline static NMConnection * +nmtst_create_minimal_connection (const char *id, const char *uuid, const char *type, NMSettingConnection **out_s_con) +{ + NMConnection *con; + NMSetting *s_base = NULL; + NMSettingConnection *s_con; + + g_assert (id); + + if (uuid) + g_assert (nm_utils_is_uuid (uuid)); + else + uuid = nm_utils_uuid_generate (); + + if (type) { + GType type_g = nm_connection_lookup_setting_type (type); + + g_assert (type_g != G_TYPE_INVALID); + + s_base = g_object_new (type_g, NULL); + g_assert (NM_IS_SETTING (s_base)); + } + + con = nm_connection_new (); + s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ()); + + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, id, + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_TYPE, type, + NULL); + nm_connection_add_setting (con, NM_SETTING (s_con)); + + if (s_base) + nm_connection_add_setting (con, s_base); + + if (out_s_con) + *out_s_con = s_con; + return con; +} + +#endif #endif /* __NM_TEST_UTILS_H__ */ diff --git a/libnm-glib/nm-client.c b/libnm-glib/nm-client.c index 711da7f4a0..329f1e1ad1 100644 --- a/libnm-glib/nm-client.c +++ b/libnm-glib/nm-client.c @@ -1704,50 +1704,6 @@ nm_client_new_finish (GAsyncResult *result, GError **error) return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple)); } -/* - * Validate D-Bus object path. - * The function is copied and adjusted version of - * g_variant_serialiser_is_object_path() from glib. - * FIXME: The function can be replaced by g_variant_is_object_path() - * when we start using GLib >= 2.24 - */ -static gboolean -_nm_client_is_object_path (const char *string) -{ - gsize i; - - if (!g_utf8_validate (string, -1, NULL)) - return FALSE; - - /* The path must begin with an ASCII '/' (integer 47) character */ - if (string[0] != '/') - return FALSE; - - for (i = 1; string[i]; i++) { - /* Each element must only contain the ASCII characters - * "[A-Z][a-z][0-9]_" - */ - if (g_ascii_isalnum (string[i]) || string[i] == '_') - ; - /* must consist of elements separated by slash characters. */ - else if (string[i] == '/') { - /* No element may be the empty string. */ - /* Multiple '/' characters cannot occur in sequence. */ - if (string[i - 1] == '/') - return FALSE; - } else - return FALSE; - } - - /* A trailing '/' character is not allowed unless the path is the - * root path (a single '/' character). - */ - if (i > 1 && string[i - 1] == '/') - return FALSE; - - return TRUE; -} - /* * constructor() shouldn't be overriden in most cases, rather constructed() * method is preferred and more useful. @@ -1785,8 +1741,8 @@ constructor (GType type, if (dbus_path == NULL) { g_value_set_static_string (construct_params[i].value, NM_DBUS_PATH); } else { - if (!_nm_client_is_object_path (dbus_path)) { - g_warning ("Passsed D-Bus object path '%s' is invalid; using default '%s' instead", + if (!g_variant_is_object_path (dbus_path)) { + g_warning ("Passed D-Bus object path '%s' is invalid; using default '%s' instead", dbus_path, NM_DBUS_PATH); g_value_set_static_string (construct_params[i].value, NM_DBUS_PATH); } diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 5203f9fe01..816979ffc7 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -48,7 +48,7 @@ global: nm_client_get_device_by_path; nm_client_get_devices; nm_client_get_logging; - nm_client_get_manager_running; + nm_client_get_nm_running; nm_client_get_permission_result; nm_client_get_primary_connection; nm_client_get_startup; @@ -355,6 +355,7 @@ global: nm_remote_connection_get_secrets; nm_remote_connection_get_type; nm_remote_connection_get_unsaved; + nm_remote_connection_get_visible; nm_remote_connection_save; nm_remote_settings_add_connection; nm_remote_settings_add_connection_unsaved; diff --git a/libnm/nm-client.c b/libnm/nm-client.c index 97558fea42..1ba44f7842 100644 --- a/libnm/nm-client.c +++ b/libnm/nm-client.c @@ -51,8 +51,6 @@ G_DEFINE_TYPE_WITH_CODE (NMClient, nm_client, NM_TYPE_OBJECT, typedef struct { DBusGProxy *client_proxy; - DBusGProxy *bus_proxy; - gboolean manager_running; char *version; NMState state; gboolean startup; @@ -86,7 +84,7 @@ enum { PROP_VERSION, PROP_STATE, PROP_STARTUP, - PROP_MANAGER_RUNNING, + PROP_NM_RUNNING, PROP_NETWORKING_ENABLED, PROP_WIRELESS_ENABLED, PROP_WIRELESS_HARDWARE_ENABLED, @@ -113,11 +111,9 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; -static void proxy_name_owner_changed (DBusGProxy *proxy, - const char *name, - const char *old_owner, - const char *new_owner, - gpointer user_data); +static void nm_running_changed_cb (GObject *object, + GParamSpec *pspec, + gpointer user_data); /**********************************************************************/ @@ -211,24 +207,6 @@ init_dbus (NMObject *object) G_CALLBACK (client_recheck_permissions), object, NULL); - - if (_nm_object_is_connection_private (NM_OBJECT (object))) - priv->manager_running = TRUE; - else { - priv->bus_proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)), - DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS); - g_assert (priv->bus_proxy); - - dbus_g_proxy_add_signal (priv->bus_proxy, "NameOwnerChanged", - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->bus_proxy, - "NameOwnerChanged", - G_CALLBACK (proxy_name_owner_changed), - object, NULL); - } } #define NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK "org.freedesktop.NetworkManager.enable-disable-network" @@ -660,7 +638,7 @@ nm_client_activate_connection (NMClient *client, priv = NM_CLIENT_GET_PRIVATE (client); priv->pending_activations = g_slist_prepend (priv->pending_activations, info); - if (priv->manager_running == FALSE) { + if (!nm_client_get_nm_running (client)) { info->idle_id = g_idle_add (activate_nm_not_running, info); return; } @@ -747,7 +725,7 @@ nm_client_add_and_activate_connection (NMClient *client, priv = NM_CLIENT_GET_PRIVATE (client); priv->pending_activations = g_slist_prepend (priv->pending_activations, info); - if (priv->manager_running) { + if (nm_client_get_nm_running (client)) { dbus_g_proxy_begin_call (priv->client_proxy, "AddAndActivateConnection", add_activate_cb, info, NULL, DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, hash, @@ -791,7 +769,7 @@ nm_client_deactivate_connection (NMClient *client, NMActiveConnection *active) g_return_if_fail (NM_IS_ACTIVE_CONNECTION (active)); priv = NM_CLIENT_GET_PRIVATE (client); - if (!priv->manager_running) + if (!nm_client_get_nm_running (client)) return; path = nm_object_get_path (NM_OBJECT (active)); @@ -822,7 +800,7 @@ nm_client_get_active_connections (NMClient *client) g_return_val_if_fail (NM_IS_CLIENT (client), NULL); priv = NM_CLIENT_GET_PRIVATE (client); - if (!priv->manager_running) + if (!nm_client_get_nm_running (client)) return NULL; return handle_ptr_array_return (priv->active_connections); @@ -858,7 +836,7 @@ nm_client_wireless_set_enabled (NMClient *client, gboolean enabled) g_return_if_fail (NM_IS_CLIENT (client)); - if (!NM_CLIENT_GET_PRIVATE (client)->manager_running) + if (!nm_client_get_nm_running (client)) return; g_value_init (&value, G_TYPE_BOOLEAN); @@ -916,7 +894,7 @@ nm_client_wwan_set_enabled (NMClient *client, gboolean enabled) g_return_if_fail (NM_IS_CLIENT (client)); - if (!NM_CLIENT_GET_PRIVATE (client)->manager_running) + if (!nm_client_get_nm_running (client)) return; g_value_init (&value, G_TYPE_BOOLEAN); @@ -974,7 +952,7 @@ nm_client_wimax_set_enabled (NMClient *client, gboolean enabled) g_return_if_fail (NM_IS_CLIENT (client)); - if (!NM_CLIENT_GET_PRIVATE (client)->manager_running) + if (!nm_client_get_nm_running (client)) return; g_value_init (&value, G_TYPE_BOOLEAN); @@ -1013,13 +991,12 @@ nm_client_wimax_hardware_get_enabled (NMClient *client) const char * nm_client_get_version (NMClient *client) { - NMClientPrivate *priv; - g_return_val_if_fail (NM_IS_CLIENT (client), NULL); - priv = NM_CLIENT_GET_PRIVATE (client); + if (!nm_client_get_nm_running (client)) + return NULL; - return priv->manager_running ? priv->version : NULL; + return NM_CLIENT_GET_PRIVATE (client)->version; } /** @@ -1087,7 +1064,7 @@ nm_client_networking_set_enabled (NMClient *client, gboolean enable) g_return_if_fail (NM_IS_CLIENT (client)); - if (!NM_CLIENT_GET_PRIVATE (client)->manager_running) + if (!nm_client_get_nm_running (client)) return; if (!dbus_g_proxy_call (NM_CLIENT_GET_PRIVATE (client)->client_proxy, "Enable", &err, @@ -1100,7 +1077,7 @@ nm_client_networking_set_enabled (NMClient *client, gboolean enable) } /** - * nm_client_get_manager_running: + * nm_client_get_nm_running: * @client: a #NMClient * * Determines whether the daemon is running. @@ -1108,11 +1085,11 @@ nm_client_networking_set_enabled (NMClient *client, gboolean enable) * Returns: %TRUE if the daemon is running **/ gboolean -nm_client_get_manager_running (NMClient *client) +nm_client_get_nm_running (NMClient *client) { g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); - return NM_CLIENT_GET_PRIVATE (client)->manager_running; + return _nm_object_get_nm_running (NM_OBJECT (client)); } /** @@ -1160,7 +1137,7 @@ nm_client_get_logging (NMClient *client, char **level, char **domains, GError ** g_return_val_if_fail (error == NULL || *error == NULL, FALSE); priv = NM_CLIENT_GET_PRIVATE (client); - if (!priv->manager_running) { + if (!nm_client_get_nm_running (client)) { g_set_error_literal (error, NM_CLIENT_ERROR, NM_CLIENT_ERROR_MANAGER_NOT_RUNNING, @@ -1199,7 +1176,7 @@ nm_client_set_logging (NMClient *client, const char *level, const char *domains, g_return_val_if_fail (error == NULL || *error == NULL, FALSE); priv = NM_CLIENT_GET_PRIVATE (client); - if (!priv->manager_running) { + if (!nm_client_get_nm_running (client)) { g_set_error_literal (error, NM_CLIENT_ERROR, NM_CLIENT_ERROR_MANAGER_NOT_RUNNING, @@ -1323,38 +1300,21 @@ updated_properties (GObject *object, GAsyncResult *result, gpointer user_data) g_error_free (error); } - _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_MANAGER_RUNNING); + _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_NM_RUNNING); } static void -proxy_name_owner_changed (DBusGProxy *proxy, - const char *name, - const char *old_owner, - const char *new_owner, - gpointer user_data) +nm_running_changed_cb (GObject *object, + GParamSpec *pspec, + gpointer user_data) { - NMClient *client = NM_CLIENT (user_data); + NMClient *client = NM_CLIENT (object); NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client); - gboolean old_good = (old_owner && strlen (old_owner)); - gboolean new_good = (new_owner && strlen (new_owner)); - gboolean new_running = FALSE; - if (!name || strcmp (name, NM_DBUS_SERVICE)) - return; - - if (!old_good && new_good) - new_running = TRUE; - else if (old_good && !new_good) - new_running = FALSE; - - if (new_running == priv->manager_running) - return; - - priv->manager_running = new_running; - if (!priv->manager_running) { + if (!nm_client_get_nm_running (client)) { priv->state = NM_STATE_UNKNOWN; priv->startup = FALSE; - _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_MANAGER_RUNNING); + _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_NM_RUNNING); _nm_object_suppress_property_updates (NM_OBJECT (client), TRUE); poke_wireless_devices_with_rf_status (client); free_devices (client, TRUE); @@ -1669,50 +1629,6 @@ nm_client_new_finish (GAsyncResult *result, GError **error) return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple)); } -/* - * Validate D-Bus object path. - * The function is copied and adjusted version of - * g_variant_serialiser_is_object_path() from glib. - * FIXME: The function can be replaced by g_variant_is_object_path() - * when we start using GLib >= 2.24 - */ -static gboolean -_nm_client_is_object_path (const char *string) -{ - gsize i; - - if (!g_utf8_validate (string, -1, NULL)) - return FALSE; - - /* The path must begin with an ASCII '/' (integer 47) character */ - if (string[0] != '/') - return FALSE; - - for (i = 1; string[i]; i++) { - /* Each element must only contain the ASCII characters - * "[A-Z][a-z][0-9]_" - */ - if (g_ascii_isalnum (string[i]) || string[i] == '_') - ; - /* must consist of elements separated by slash characters. */ - else if (string[i] == '/') { - /* No element may be the empty string. */ - /* Multiple '/' characters cannot occur in sequence. */ - if (string[i - 1] == '/') - return FALSE; - } else - return FALSE; - } - - /* A trailing '/' character is not allowed unless the path is the - * root path (a single '/' character). - */ - if (i > 1 && string[i - 1] == '/') - return FALSE; - - return TRUE; -} - /* * constructor() shouldn't be overriden in most cases, rather constructed() * method is preferred and more useful. @@ -1749,8 +1665,8 @@ constructor (GType type, if (dbus_path == NULL) { g_value_set_static_string (construct_params[i].value, NM_DBUS_PATH); } else { - if (!_nm_client_is_object_path (dbus_path)) { - g_warning ("Passsed D-Bus object path '%s' is invalid; using default '%s' instead", + if (!g_variant_is_object_path (dbus_path)) { + g_warning ("Passed D-Bus object path '%s' is invalid; using default '%s' instead", dbus_path, NM_DBUS_PATH); g_value_set_static_string (construct_params[i].value, NM_DBUS_PATH); } @@ -1769,6 +1685,9 @@ constructed (GObject *object) { G_OBJECT_CLASS (nm_client_parent_class)->constructed (object); + g_signal_connect (object, "notify::" NM_OBJECT_NM_RUNNING, + G_CALLBACK (nm_running_changed_cb), NULL); + g_signal_connect (object, "notify::" NM_CLIENT_WIRELESS_ENABLED, G_CALLBACK (wireless_enabled_cb), NULL); @@ -1783,7 +1702,6 @@ static gboolean init_sync (GInitable *initable, GCancellable *cancellable, GError **error) { NMClient *client = NM_CLIENT (initable); - NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client); if (!nm_utils_init (error)) return FALSE; @@ -1791,17 +1709,8 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error) if (!nm_client_parent_initable_iface->init (initable, cancellable, error)) return FALSE; - if (!_nm_object_is_connection_private (NM_OBJECT (client))) { - if (!dbus_g_proxy_call (priv->bus_proxy, - "NameHasOwner", error, - G_TYPE_STRING, NM_DBUS_SERVICE, - G_TYPE_INVALID, - G_TYPE_BOOLEAN, &priv->manager_running, - G_TYPE_INVALID)) - return FALSE; - } - - if (priv->manager_running && !get_permissions_sync (client, error)) + if ( nm_client_get_nm_running (client) + && !get_permissions_sync (client, error)) return FALSE; return TRUE; @@ -1810,16 +1719,11 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error) typedef struct { NMClient *client; GSimpleAsyncResult *result; - gboolean properties_pending; - gboolean permissions_pending; } NMClientInitData; static void init_async_complete (NMClientInitData *init_data) { - if (init_data->properties_pending || init_data->permissions_pending) - return; - g_simple_async_result_complete (init_data->result); g_object_unref (init_data->result); g_slice_free (NMClientInitData, init_data); @@ -1836,63 +1740,33 @@ init_async_got_permissions (DBusGProxy *proxy, DBusGProxyCall *call, gpointer us DBUS_TYPE_G_MAP_OF_STRING, &permissions, G_TYPE_INVALID); update_permissions (init_data->client, error ? NULL : permissions); - g_clear_error (&error); - - init_data->permissions_pending = FALSE; - init_async_complete (init_data); -} - -static void -init_async_got_properties (GObject *source, GAsyncResult *result, gpointer user_data) -{ - NMClientInitData *init_data = user_data; - GError *error = NULL; - - if (!nm_client_parent_async_initable_iface->init_finish (G_ASYNC_INITABLE (source), result, &error)) + if (error) g_simple_async_result_take_error (init_data->result, error); - init_data->properties_pending = FALSE; init_async_complete (init_data); } static void -finish_init (NMClientInitData *init_data) +init_async_parent_inited (GObject *source, GAsyncResult *result, gpointer user_data) { + NMClientInitData *init_data = user_data; NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (init_data->client); + GError *error = NULL; - nm_client_parent_async_initable_iface->init_async (G_ASYNC_INITABLE (init_data->client), - G_PRIORITY_DEFAULT, NULL, /* FIXME cancellable */ - init_async_got_properties, init_data); - init_data->properties_pending = TRUE; + if (!nm_client_parent_async_initable_iface->init_finish (G_ASYNC_INITABLE (source), result, &error)) { + g_simple_async_result_take_error (init_data->result, error); + init_async_complete (init_data); + return; + } + + if (!nm_client_get_nm_running (init_data->client)) { + init_async_complete (init_data); + return; + } dbus_g_proxy_begin_call (priv->client_proxy, "GetPermissions", init_async_got_permissions, init_data, NULL, G_TYPE_INVALID); - init_data->permissions_pending = TRUE; -} - -static void -init_async_got_manager_running (DBusGProxy *proxy, DBusGProxyCall *call, - gpointer user_data) -{ - NMClientInitData *init_data = user_data; - NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (init_data->client); - GError *error = NULL; - - if (!dbus_g_proxy_end_call (proxy, call, &error, - G_TYPE_BOOLEAN, &priv->manager_running, - G_TYPE_INVALID)) { - g_simple_async_result_take_error (init_data->result, error); - init_async_complete (init_data); - return; - } - - if (!priv->manager_running) { - init_async_complete (init_data); - return; - } - - finish_init (init_data); } static void @@ -1901,7 +1775,6 @@ init_async (GAsyncInitable *initable, int io_priority, gpointer user_data) { NMClientInitData *init_data; - NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (initable); GError *error = NULL; if (!nm_utils_init (&error)) { @@ -1916,16 +1789,8 @@ init_async (GAsyncInitable *initable, int io_priority, user_data, init_async); g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE); - if (_nm_object_is_connection_private (NM_OBJECT (init_data->client))) - finish_init (init_data); - else { - /* Check if NM is running */ - dbus_g_proxy_begin_call (priv->bus_proxy, "NameHasOwner", - init_async_got_manager_running, - init_data, NULL, - G_TYPE_STRING, NM_DBUS_SERVICE, - G_TYPE_INVALID); - } + nm_client_parent_async_initable_iface->init_async (initable, io_priority, cancellable, + init_async_parent_inited, init_data); } static gboolean @@ -1951,7 +1816,6 @@ dispose (GObject *object) } g_clear_object (&priv->client_proxy); - g_clear_object (&priv->bus_proxy); free_devices (client, FALSE); free_active_connections (client, FALSE); @@ -2038,8 +1902,8 @@ get_property (GObject *object, case PROP_STARTUP: g_value_set_boolean (value, nm_client_get_startup (self)); break; - case PROP_MANAGER_RUNNING: - g_value_set_boolean (value, priv->manager_running); + case PROP_NM_RUNNING: + g_value_set_boolean (value, nm_client_get_nm_running (self)); break; case PROP_NETWORKING_ENABLED: g_value_set_boolean (value, nm_client_networking_get_enabled (self)); @@ -2140,13 +2004,13 @@ nm_client_class_init (NMClientClass *client_class) G_PARAM_STATIC_STRINGS)); /** - * NMClient:manager-running: + * NMClient:nm-running: * * Whether the daemon is running. **/ g_object_class_install_property - (object_class, PROP_MANAGER_RUNNING, - g_param_spec_boolean (NM_CLIENT_MANAGER_RUNNING, "", "", + (object_class, PROP_NM_RUNNING, + g_param_spec_boolean (NM_CLIENT_NM_RUNNING, "", "", FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); diff --git a/libnm/nm-client.h b/libnm/nm-client.h index 8fc676b8f2..52d59d4bd4 100644 --- a/libnm/nm-client.h +++ b/libnm/nm-client.h @@ -48,7 +48,7 @@ G_BEGIN_DECLS #define NM_CLIENT_VERSION "version" #define NM_CLIENT_STATE "state" #define NM_CLIENT_STARTUP "startup" -#define NM_CLIENT_MANAGER_RUNNING "manager-running" +#define NM_CLIENT_NM_RUNNING "nm-running" #define NM_CLIENT_NETWORKING_ENABLED "networking-enabled" #define NM_CLIENT_WIRELESS_ENABLED "wireless-enabled" #define NM_CLIENT_WIRELESS_HARDWARE_ENABLED "wireless-hardware-enabled" @@ -222,7 +222,7 @@ gboolean nm_client_wimax_hardware_get_enabled (NMClient *client); const char *nm_client_get_version (NMClient *client); NMState nm_client_get_state (NMClient *client); gboolean nm_client_get_startup (NMClient *client); -gboolean nm_client_get_manager_running (NMClient *client); +gboolean nm_client_get_nm_running (NMClient *client); const GPtrArray *nm_client_get_active_connections (NMClient *client); NMClientPermissionResult nm_client_get_permission_result (NMClient *client, diff --git a/libnm/nm-object-private.h b/libnm/nm-object-private.h index 6474dc7516..f9925cf73a 100644 --- a/libnm/nm-object-private.h +++ b/libnm/nm-object-private.h @@ -87,4 +87,7 @@ typedef void (*NMObjectTypeAsyncFunc) (DBusGConnection *, const char *, NMObject void _nm_object_register_type_func (GType base_type, NMObjectTypeFunc type_func, NMObjectTypeAsyncFunc type_async_func); +#define NM_OBJECT_NM_RUNNING "nm-running-internal" +gboolean _nm_object_get_nm_running (NMObject *self); + #endif /* NM_OBJECT_PRIVATE_H */ diff --git a/libnm/nm-object.c b/libnm/nm-object.c index f44bf6bab5..d0e88994b2 100644 --- a/libnm/nm-object.c +++ b/libnm/nm-object.c @@ -84,6 +84,7 @@ enum { PROP_0, PROP_DBUS_CONNECTION, PROP_DBUS_PATH, + PROP_NM_RUNNING, LAST_PROP }; @@ -122,15 +123,15 @@ proxy_name_owner_changed (DBusGProxy *proxy, { NMObject *self = NM_OBJECT (user_data); NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); + gboolean now_running; - if (g_strcmp0 (name, NM_DBUS_SERVICE) == 0) { - gboolean old_good = (old_owner && old_owner[0]); - gboolean new_good = (new_owner && new_owner[0]); + if (g_strcmp0 (name, NM_DBUS_SERVICE) != 0) + return; - if (!old_good && new_good) - priv->nm_running = TRUE; - else if (old_good && !new_good) - priv->nm_running = FALSE; + now_running = (new_owner && new_owner[0]); + if (now_running != priv->nm_running) { + priv->nm_running = now_running; + g_object_notify (G_OBJECT (self), NM_OBJECT_NM_RUNNING); } } @@ -232,8 +233,8 @@ init_async_got_properties (GObject *object, GAsyncResult *result, gpointer user_ } static void -init_async_got_manager_running (DBusGProxy *proxy, DBusGProxyCall *call, - gpointer user_data) +init_async_got_nm_running (DBusGProxy *proxy, DBusGProxyCall *call, + gpointer user_data) { GSimpleAsyncResult *simple = user_data; NMObject *self; @@ -289,7 +290,7 @@ init_async (GAsyncInitable *initable, int io_priority, else { /* Check if NM is running */ dbus_g_proxy_begin_call (priv->bus_proxy, "NameHasOwner", - init_async_got_manager_running, + init_async_got_nm_running, simple, NULL, G_TYPE_STRING, NM_DBUS_SERVICE, G_TYPE_INVALID); @@ -379,6 +380,9 @@ get_property (GObject *object, guint prop_id, case PROP_DBUS_PATH: g_value_set_string (value, priv->path); break; + case PROP_NM_RUNNING: + g_value_set_boolean (value, priv->nm_running); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -428,6 +432,18 @@ nm_object_class_init (NMObjectClass *nm_object_class) G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + /** + * NMObject:manager-running: (skip) + * + * Internal use only. + */ + g_object_class_install_property + (object_class, PROP_NM_RUNNING, + g_param_spec_boolean (NM_OBJECT_NM_RUNNING, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + /* signals */ /** @@ -1431,3 +1447,9 @@ _nm_object_is_connection_private (NMObject *self) { return _nm_dbus_is_connection_private (NM_OBJECT_GET_PRIVATE (self)->connection); } + +gboolean +_nm_object_get_nm_running (NMObject *self) +{ + return NM_OBJECT_GET_PRIVATE (self)->nm_running; +} diff --git a/libnm/nm-remote-connection.c b/libnm/nm-remote-connection.c index 9806995a7f..71dd8c62d0 100644 --- a/libnm/nm-remote-connection.c +++ b/libnm/nm-remote-connection.c @@ -50,19 +50,11 @@ enum { PROP_DBUS_CONNECTION, PROP_DBUS_PATH, PROP_UNSAVED, + PROP_VISIBLE, LAST_PROP }; -enum { - UPDATED, - REMOVED, - VISIBLE, - - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL] = { 0 }; - typedef struct RemoteCall RemoteCall; typedef void (*RemoteCallFetchResultCb) (RemoteCall *call, DBusGProxyCall *proxy_call, GError *error); @@ -413,6 +405,30 @@ nm_remote_connection_get_unsaved (NMRemoteConnection *connection) return NM_REMOTE_CONNECTION_GET_PRIVATE (connection)->unsaved; } +/** + * nm_remote_connection_get_visible: + * @connection: the #NMRemoteConnection + * + * Checks if the connection is visible to the current user. If the + * connection is not visible then it is essentially useless; it will + * not contain any settings, and operations such as + * nm_remote_connection_save() and nm_remote_connection_delete() will + * always fail. (#NMRemoteSettings will not normally return + * non-visible connections to callers, but it is possible for a + * connection's visibility to change after you already have a + * reference to it.) + * + * Returns: %TRUE if the remote connection is visible to the current + * user, %FALSE if not. + **/ +gboolean +nm_remote_connection_get_visible (NMRemoteConnection *connection) +{ + g_return_val_if_fail (NM_IS_REMOTE_CONNECTION (connection), FALSE); + + return NM_REMOTE_CONNECTION_GET_PRIVATE (connection)->visible; +} + /****************************************************************/ static void @@ -420,17 +436,13 @@ replace_settings (NMRemoteConnection *self, GHashTable *new_settings) { GError *error = NULL; - if (nm_connection_replace_settings (NM_CONNECTION (self), new_settings, &error)) - g_signal_emit (self, signals[UPDATED], 0, new_settings); - else { + if (!nm_connection_replace_settings (NM_CONNECTION (self), new_settings, &error)) { g_warning ("%s: error updating connection %s settings: (%d) %s", __func__, nm_connection_get_path (NM_CONNECTION (self)), error ? error->code : -1, (error && error->message) ? error->message : "(unknown)"); g_clear_error (&error); - - g_signal_emit (self, signals[REMOVED], 0); } } @@ -443,6 +455,7 @@ updated_get_settings_cb (DBusGProxy *proxy, NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self); GHashTable *new_settings; GError *error = NULL; + gboolean visible; dbus_g_proxy_end_call (proxy, call, &error, DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, &new_settings, @@ -452,26 +465,22 @@ updated_get_settings_cb (DBusGProxy *proxy, g_error_free (error); - /* Connection is no longer visible to this user. Let the settings - * service handle this via 'visible'. The settings service will emit - * the "removed" signal for us since it handles the lifetime of this - * object. - */ + /* Connection is no longer visible to this user. */ hash = g_hash_table_new (g_str_hash, g_str_equal); nm_connection_replace_settings (NM_CONNECTION (self), hash, NULL); g_hash_table_destroy (hash); - priv->visible = FALSE; - g_signal_emit (self, signals[VISIBLE], 0, FALSE); + visible = FALSE; } else { replace_settings (self, new_settings); g_hash_table_destroy (new_settings); - /* Settings service will handle announcing the connection to clients */ - if (priv->visible == FALSE) { - priv->visible = TRUE; - g_signal_emit (self, signals[VISIBLE], 0, TRUE); - } + visible = TRUE; + } + + if (visible != priv->visible) { + priv->visible = visible; + g_object_notify (G_OBJECT (self), NM_REMOTE_CONNECTION_VISIBLE); } } @@ -489,12 +498,6 @@ updated_cb (DBusGProxy *proxy, gpointer user_data) } } -static void -removed_cb (DBusGProxy *proxy, gpointer user_data) -{ - g_signal_emit (G_OBJECT (user_data), signals[REMOVED], 0); -} - static void properties_changed_cb (DBusGProxy *proxy, GHashTable *properties, @@ -533,9 +536,6 @@ init_common (NMRemoteConnection *self) dbus_g_proxy_add_signal (priv->proxy, "Updated", G_TYPE_INVALID); dbus_g_proxy_connect_signal (priv->proxy, "Updated", G_CALLBACK (updated_cb), self, NULL); - dbus_g_proxy_add_signal (priv->proxy, "Removed", G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "Removed", G_CALLBACK (removed_cb), self, NULL); - g_signal_connect (priv->proxy, "destroy", G_CALLBACK (proxy_destroy_cb), self); /* Monitor properties */ @@ -734,6 +734,9 @@ get_property (GObject *object, guint prop_id, case PROP_UNSAVED: g_value_set_boolean (value, NM_REMOTE_CONNECTION_GET_PRIVATE (object)->unsaved); break; + case PROP_VISIBLE: + g_value_set_boolean (value, NM_REMOTE_CONNECTION_GET_PRIVATE (object)->visible); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -847,47 +850,23 @@ nm_remote_connection_class_init (NMRemoteConnectionClass *remote_class) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - /* Signals */ /** - * NMRemoteConnection::updated: - * @connection: a #NMConnection + * NMRemoteConnection:visible: * - * This signal is emitted when a connection changes, and it is - * still visible to the user. - */ - signals[UPDATED] = - g_signal_new (NM_REMOTE_CONNECTION_UPDATED, - G_TYPE_FROM_CLASS (remote_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMRemoteConnectionClass, updated), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - /** - * NMRemoteConnection::removed: - * @connection: a #NMConnection - * - * This signal is emitted when a connection is either deleted or becomes - * invisible to the current user. - */ - signals[REMOVED] = - g_signal_new (NM_REMOTE_CONNECTION_REMOVED, - G_TYPE_FROM_CLASS (remote_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMRemoteConnectionClass, removed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - /* Private signal */ - signals[VISIBLE] = - g_signal_new ("visible", - G_TYPE_FROM_CLASS (remote_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__BOOLEAN, - G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + * %TRUE if the remote connection is visible to the current user, %FALSE if + * not. If the connection is not visible then it is essentially useless; it + * will not contain any settings, and operations such as + * nm_remote_connection_save() and nm_remote_connection_delete() will always + * fail. (#NMRemoteSettings will not normally return non-visible connections + * to callers, but it is possible for a connection's visibility to change + * after you already have a reference to it.) + **/ + g_object_class_install_property + (object_class, PROP_VISIBLE, + g_param_spec_boolean (NM_REMOTE_CONNECTION_VISIBLE, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); } static void diff --git a/libnm/nm-remote-connection.h b/libnm/nm-remote-connection.h index 23964a51b2..58ffe03bc4 100644 --- a/libnm/nm-remote-connection.h +++ b/libnm/nm-remote-connection.h @@ -57,10 +57,7 @@ GQuark nm_remote_connection_error_quark (void); /* Properties */ #define NM_REMOTE_CONNECTION_BUS "bus" #define NM_REMOTE_CONNECTION_UNSAVED "unsaved" - -/* Signals */ -#define NM_REMOTE_CONNECTION_UPDATED "updated" -#define NM_REMOTE_CONNECTION_REMOVED "removed" +#define NM_REMOTE_CONNECTION_VISIBLE "visible" typedef struct { NMConnection parent; @@ -69,12 +66,6 @@ typedef struct { typedef struct { NMConnectionClass parent_class; - /* Signals */ - void (*updated) (NMRemoteConnection *connection, - GHashTable *new_settings); - - void (*removed) (NMRemoteConnection *connection); - /*< private >*/ gpointer padding[8]; } NMRemoteConnectionClass; @@ -138,6 +129,8 @@ void nm_remote_connection_get_secrets (NMRemoteConnection *connection, gboolean nm_remote_connection_get_unsaved (NMRemoteConnection *connection); +gboolean nm_remote_connection_get_visible (NMRemoteConnection *connection); + G_END_DECLS #endif /* __NM_REMOTE_CONNECTION__ */ diff --git a/libnm/nm-remote-settings.c b/libnm/nm-remote-settings.c index 185981a9c7..be512c665d 100644 --- a/libnm/nm-remote-settings.c +++ b/libnm/nm-remote-settings.c @@ -30,6 +30,7 @@ #include "nm-dbus-helpers-private.h" #include "nm-glib-compat.h" #include "nm-object-private.h" +#include "nm-types.h" /** * SECTION:nm-remote-settings @@ -118,42 +119,26 @@ * ]| */ -static void nm_remote_settings_initable_iface_init (GInitableIface *iface); -static void nm_remote_settings_async_initable_iface_init (GAsyncInitableIface *iface); - -G_DEFINE_TYPE_WITH_CODE (NMRemoteSettings, nm_remote_settings, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_remote_settings_initable_iface_init); - G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_remote_settings_async_initable_iface_init); - ) +G_DEFINE_TYPE (NMRemoteSettings, nm_remote_settings, NM_TYPE_OBJECT) #define NM_REMOTE_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsPrivate)) typedef struct { - DBusGConnection *bus; - gboolean private_bus; - DBusGProxy *proxy; - GHashTable *connections; - GHashTable *pending; /* Connections we don't have settings for yet */ - gboolean service_running; - guint32 init_left; + GPtrArray *all_connections; + GPtrArray *visible_connections; /* AddConnectionInfo objects that are waiting for the connection to become initialized */ GSList *add_list; - DBusGProxy *props_proxy; char *hostname; gboolean can_modify; - - DBusGProxy *dbus_proxy; - - DBusGProxyCall *listcon_call; } NMRemoteSettingsPrivate; enum { PROP_0, - PROP_BUS, - PROP_SERVICE_RUNNING, + PROP_NM_RUNNING, + PROP_CONNECTIONS, PROP_HOSTNAME, PROP_CAN_MODIFY, @@ -162,8 +147,8 @@ enum { /* Signals */ enum { - NEW_CONNECTION, - CONNECTIONS_READ, + CONNECTION_ADDED, + CONNECTION_REMOVED, LAST_SIGNAL }; @@ -194,11 +179,11 @@ typedef struct { NMRemoteSettings *self; NMRemoteSettingsAddConnectionFunc callback; gpointer callback_data; - NMRemoteConnection *connection; + char *path; } AddConnectionInfo; static AddConnectionInfo * -add_connection_info_find (NMRemoteSettings *self, NMRemoteConnection *connection) +add_connection_info_find (NMRemoteSettings *self, const char *path) { NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); GSList *iter; @@ -206,7 +191,7 @@ add_connection_info_find (NMRemoteSettings *self, NMRemoteConnection *connection for (iter = priv->add_list; iter; iter = g_slist_next (iter)) { AddConnectionInfo *info = iter->data; - if (info->connection == connection) + if (!g_strcmp0 (info->path, path)) return info; } @@ -220,20 +205,47 @@ add_connection_info_dispose (NMRemoteSettings *self, AddConnectionInfo *info) priv->add_list = g_slist_remove (priv->add_list, info); + g_free (info->path); g_free (info); } static void add_connection_info_complete (NMRemoteSettings *self, AddConnectionInfo *info, + NMRemoteConnection *connection, GError *error) { g_return_if_fail (info != NULL); - info->callback (info->self, error ? NULL : info->connection, error, info->callback_data); + info->callback (info->self, connection, error, info->callback_data); add_connection_info_dispose (self, info); } +typedef const char * (*ConnectionStringGetter) (NMConnection *); + +static NMRemoteConnection * +get_connection_by_string (NMRemoteSettings *settings, + const char *string, + ConnectionStringGetter get_comparison_string) +{ + NMRemoteSettingsPrivate *priv; + NMConnection *candidate; + int i; + + if (!_nm_object_get_nm_running (NM_OBJECT (settings))) + return NULL; + + priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); + + for (i = 0; i < priv->visible_connections->len; i++) { + candidate = priv->visible_connections->pdata[i]; + if (!g_strcmp0 (string, get_comparison_string (candidate))) + return NM_REMOTE_CONNECTION (candidate); + } + + return NULL; +} + /** * nm_remote_settings_get_connection_by_id: * @settings: the %NMRemoteSettings @@ -247,26 +259,10 @@ add_connection_info_complete (NMRemoteSettings *self, NMRemoteConnection * nm_remote_settings_get_connection_by_id (NMRemoteSettings *settings, const char *id) { - NMRemoteSettingsPrivate *priv; - g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL); g_return_val_if_fail (id != NULL, NULL); - priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); - - if (priv->service_running) { - GHashTableIter iter; - NMConnection *candidate; - - g_hash_table_iter_init (&iter, priv->connections); - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &candidate)) { - - if (!strcmp (id, nm_connection_get_id (candidate))) - return NM_REMOTE_CONNECTION (candidate); - } - } - - return NULL; + return get_connection_by_string (settings, id, nm_connection_get_id); } /** @@ -282,14 +278,10 @@ nm_remote_settings_get_connection_by_id (NMRemoteSettings *settings, const char NMRemoteConnection * nm_remote_settings_get_connection_by_path (NMRemoteSettings *settings, const char *path) { - NMRemoteSettingsPrivate *priv; - g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL); g_return_val_if_fail (path != NULL, NULL); - priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); - - return priv->service_running ? g_hash_table_lookup (priv->connections, path) : NULL; + return get_connection_by_string (settings, path, nm_connection_get_path); } /** @@ -305,260 +297,101 @@ nm_remote_settings_get_connection_by_path (NMRemoteSettings *settings, const cha NMRemoteConnection * nm_remote_settings_get_connection_by_uuid (NMRemoteSettings *settings, const char *uuid) { - NMRemoteSettingsPrivate *priv; - GHashTableIter iter; - NMRemoteConnection *candidate; - g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL); g_return_val_if_fail (uuid != NULL, NULL); - priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); - - if (priv->service_running) { - g_hash_table_iter_init (&iter, priv->connections); - while (g_hash_table_iter_next (&iter, NULL, (gpointer) &candidate)) { - if (g_strcmp0 (uuid, nm_connection_get_uuid (NM_CONNECTION (candidate))) == 0) - return candidate; - } - } - - return NULL; + return get_connection_by_string (settings, uuid, nm_connection_get_uuid); } static void -connection_removed_cb (NMRemoteConnection *remote, gpointer user_data) +connection_visible_changed (GObject *object, + GParamSpec *pspec, + gpointer user_data) { + NMRemoteConnection *connection = NM_REMOTE_CONNECTION (object); NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data); + + if (nm_remote_connection_get_visible (connection)) + g_signal_emit (self, signals[CONNECTION_ADDED], 0, connection); + else + g_signal_emit (self, signals[CONNECTION_REMOVED], 0, connection); +} + +static void +cleanup_connection (NMRemoteSettings *self, + NMRemoteConnection *remote) +{ + g_signal_handlers_disconnect_by_func (remote, G_CALLBACK (connection_visible_changed), self); +} + +static void +connection_removed (NMRemoteSettings *self, + NMRemoteConnection *remote) +{ + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); + gboolean still_exists = FALSE; + int i; + + /* Check if the connection was actually removed or if it just turned invisible. */ + if (priv->all_connections) { + for (i = 0; i < priv->all_connections->len; i++) { + if (remote == priv->all_connections->pdata[i]) { + still_exists = TRUE; + break; + } + } + } + + if (!still_exists) + cleanup_connection (self, remote); + + /* Allow the signal to propagate if and only if @remote was in visible_connections */ + if (!g_ptr_array_remove (priv->visible_connections, remote)) + g_signal_stop_emission (self, signals[CONNECTION_REMOVED], 0); +} + +static void +connection_added (NMRemoteSettings *self, + NMRemoteConnection *remote) +{ NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); AddConnectionInfo *addinfo; - GError *add_error; const char *path; - /* Might have been removed while it was waiting to be initialized */ - addinfo = add_connection_info_find (self, remote); + if (!g_signal_handler_find (remote, G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, NULL, + G_CALLBACK (connection_visible_changed), self)) { + g_signal_connect (remote, + "notify::" NM_REMOTE_CONNECTION_VISIBLE, + G_CALLBACK (connection_visible_changed), + self); + } + + if (nm_remote_connection_get_visible (remote)) + g_ptr_array_add (priv->visible_connections, remote); + else + g_signal_stop_emission (self, signals[CONNECTION_ADDED], 0); + + path = nm_connection_get_path (NM_CONNECTION (remote)); + addinfo = add_connection_info_find (self, path); + if (addinfo) + add_connection_info_complete (self, addinfo, remote, NULL); +} + +static void +object_creation_failed (NMObject *object, GError *error, char *failed_path) +{ + NMRemoteSettings *self = NM_REMOTE_SETTINGS (object); + AddConnectionInfo *addinfo; + GError *add_error; + + addinfo = add_connection_info_find (self, failed_path); if (addinfo) { add_error = g_error_new_literal (NM_REMOTE_SETTINGS_ERROR, NM_REMOTE_SETTINGS_ERROR_CONNECTION_REMOVED, "Connection removed before it was initialized"); - add_connection_info_complete (self, addinfo, add_error); + add_connection_info_complete (self, addinfo, NULL, add_error); g_error_free (add_error); } - - path = nm_connection_get_path (NM_CONNECTION (remote)); - g_hash_table_remove (priv->connections, path); - g_hash_table_remove (priv->pending, path); -} - -static void connection_visible_cb (NMRemoteConnection *remote, - gboolean visible, - gpointer user_data); - -/* Takes a reference to the connection when adding to 'to' */ -static void -move_connection (NMRemoteSettings *self, - NMRemoteConnection *remote, - GHashTable *from, - GHashTable *to) -{ - const char *path = nm_connection_get_path (NM_CONNECTION (remote)); - - g_hash_table_insert (to, g_strdup (path), g_object_ref (remote)); - if (from) - g_hash_table_remove (from, path); - - /* Setup connection signals since removing from 'from' clears them, but - * also the first time the connection is added to a hash if 'from' is NULL. - */ - if (!g_signal_handler_find (remote, G_SIGNAL_MATCH_FUNC, - 0, 0, NULL, connection_removed_cb, NULL)) { - g_signal_connect (remote, - NM_REMOTE_CONNECTION_REMOVED, - G_CALLBACK (connection_removed_cb), - self); - } - - if (!g_signal_handler_find (remote, G_SIGNAL_MATCH_FUNC, - 0, 0, NULL, connection_visible_cb, NULL)) { - g_signal_connect (remote, - "visible", - G_CALLBACK (connection_visible_cb), - self); - } -} - -static void -connection_visible_cb (NMRemoteConnection *remote, - gboolean visible, - gpointer user_data) -{ - NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data); - NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); - const char *path; - - path = nm_connection_get_path (NM_CONNECTION (remote)); - g_assert (path); - - /* When a connection becomes invisible, we put it back in the pending - * hash until it becomes visible again. When it does, we move it back to - * the normal connections hash. - */ - if (visible) { - /* Connection visible to this user again */ - if (g_hash_table_lookup (priv->pending, path)) { - /* Move connection from pending to visible hash; emit for clients */ - move_connection (self, remote, priv->pending, priv->connections); - g_signal_emit (self, signals[NEW_CONNECTION], 0, remote); - } - } else { - /* Connection now invisible to this user */ - if (g_hash_table_lookup (priv->connections, path)) { - /* Move connection to pending hash and wait for it to become visible again */ - move_connection (self, remote, priv->connections, priv->pending); - - /* Signal to clients that the connection is gone; but we have to - * block our connection removed handler so we don't destroy - * the connection when the signal is emitted. - */ - g_signal_handlers_block_by_func (remote, connection_removed_cb, self); - g_signal_emit_by_name (remote, NM_REMOTE_CONNECTION_REMOVED); - g_signal_handlers_unblock_by_func (remote, connection_removed_cb, self); - } - } -} - -static void -connection_inited (GObject *source, GAsyncResult *result, gpointer user_data) -{ - NMRemoteConnection *remote = NM_REMOTE_CONNECTION (source); - NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data); - NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); - AddConnectionInfo *addinfo; - const char *path; - GError *error = NULL, *local; - - path = nm_connection_get_path (NM_CONNECTION (remote)); - addinfo = add_connection_info_find (self, remote); - - if (g_async_initable_init_finish (G_ASYNC_INITABLE (remote), result, &error)) { - /* Connection is initialized and visible; expose it to clients */ - move_connection (self, remote, priv->pending, priv->connections); - - /* If there's a pending AddConnection request, complete that here before - * signaling new-connection. - */ - if (addinfo) - add_connection_info_complete (self, addinfo, NULL); - - /* Finally, let users know of the new connection now that it has all - * its settings and is valid. - */ - g_signal_emit (self, signals[NEW_CONNECTION], 0, remote); - } else { - if (addinfo) { - local = g_error_new (NM_REMOTE_SETTINGS_ERROR, - NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE, - "Connection not visible or not available: %s", - error ? error->message : "(unknown)"); - add_connection_info_complete (self, addinfo, local); - g_error_free (local); - } - - /* PermissionDenied means the connection isn't visible to this user, so - * keep it in priv->pending to be notified later of visibility changes. - * Otherwise forget it. - */ - if (!dbus_g_error_has_name (error, "org.freedesktop.NetworkManager.Settings.PermissionDenied")) - g_hash_table_remove (priv->pending, path); - - g_error_free (error); - } - - /* Let listeners know that all connections have been found */ - priv->init_left--; - if (priv->init_left == 0) - g_signal_emit (self, signals[CONNECTIONS_READ], 0); -} - -static NMRemoteConnection * -new_connection_cb (DBusGProxy *proxy, const char *path, gpointer user_data) -{ - NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data); - NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); - NMRemoteConnection *connection = NULL; - - /* Make double-sure we don't already have it */ - connection = g_hash_table_lookup (priv->pending, path); - if (connection) - return connection; - connection = g_hash_table_lookup (priv->connections, path); - if (connection) - return connection; - - /* Create a new connection object for it */ - connection = g_object_new (NM_TYPE_REMOTE_CONNECTION, - NM_REMOTE_CONNECTION_BUS, priv->bus, - NM_CONNECTION_PATH, path, - NULL); - g_async_initable_init_async (G_ASYNC_INITABLE (connection), - G_PRIORITY_DEFAULT, NULL, - connection_inited, self); - - /* Add the connection to the pending table to wait for it to retrieve - * it's settings asynchronously over D-Bus. The connection isn't - * really valid until it has all its settings, so hide it until it does. - */ - move_connection (self, connection, NULL, priv->pending); - g_object_unref (connection); /* move_connection() takes a ref */ - - return connection; -} - -static void -fetch_connections_done (DBusGProxy *proxy, - DBusGProxyCall *call, - gpointer user_data) -{ - NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data); - NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); - GPtrArray *connections; - GError *error = NULL; - int i; - - g_warn_if_fail (priv->listcon_call == call); - priv->listcon_call = NULL; - - if (!dbus_g_proxy_end_call (proxy, call, &error, - DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, &connections, - G_TYPE_INVALID)) { - if ( !g_error_matches (error, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN) - && !g_error_matches (error, DBUS_GERROR, DBUS_GERROR_NAME_HAS_NO_OWNER) - && priv->service_running) { - g_warning ("%s: error fetching connections: (%d) %s.", - __func__, - error->code, - error->message ? error->message : "(unknown)"); - } - g_clear_error (&error); - - /* We tried to read connections and failed */ - g_signal_emit (self, signals[CONNECTIONS_READ], 0); - return; - } - - /* Let listeners know we are done getting connections */ - if (connections->len == 0) - g_signal_emit (self, signals[CONNECTIONS_READ], 0); - else { - priv->init_left = connections->len; - for (i = 0; i < connections->len; i++) { - char *path = g_ptr_array_index (connections, i); - - new_connection_cb (proxy, path, user_data); - g_free (path); - } - } - - g_ptr_array_free (connections, TRUE); } /** @@ -577,17 +410,16 @@ nm_remote_settings_list_connections (NMRemoteSettings *settings) { NMRemoteSettingsPrivate *priv; GSList *list = NULL; - GHashTableIter iter; - gpointer value; + int i; g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL); priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); - if (priv->service_running) { - g_hash_table_iter_init (&iter, priv->connections); - while (g_hash_table_iter_next (&iter, NULL, &value)) - list = g_slist_prepend (list, NM_REMOTE_CONNECTION (value)); + if (_nm_object_get_nm_running (NM_OBJECT (settings))) { + for (i = 0; i < priv->visible_connections->len; i++) + list = g_slist_prepend (list, priv->visible_connections->pdata[i]); + list = g_slist_reverse (list); } return list; @@ -601,12 +433,10 @@ add_connection_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data char *path = NULL; if (dbus_g_proxy_end_call (proxy, call, &error, DBUS_TYPE_G_OBJECT_PATH, &path, G_TYPE_INVALID)) { - info->connection = new_connection_cb (proxy, path, info->self); - g_assert (info->connection); + info->path = path; /* Wait until this connection is fully initialized before calling the callback */ - g_free (path); } else - add_connection_info_complete (info->self, info, error); + add_connection_info_complete (info->self, info, NULL, error); g_clear_error (&error); } @@ -647,7 +477,7 @@ nm_remote_settings_add_connection (NMRemoteSettings *settings, priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); - if (!priv->service_running) + if (!_nm_object_get_nm_running (NM_OBJECT (settings))) return FALSE; info = g_malloc0 (sizeof (AddConnectionInfo)); @@ -700,7 +530,7 @@ nm_remote_settings_add_connection_unsaved (NMRemoteSettings *settings, priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); - if (!priv->service_running) + if (!_nm_object_get_nm_running (NM_OBJECT (settings))) return FALSE; info = g_malloc0 (sizeof (AddConnectionInfo)); @@ -760,7 +590,7 @@ nm_remote_settings_load_connections (NMRemoteSettings *settings, priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); - if (!priv->service_running) { + if (!_nm_object_get_nm_running (NM_OBJECT (settings))) { g_set_error_literal (error, NM_REMOTE_SETTINGS_ERROR, NM_REMOTE_SETTINGS_ERROR_SERVICE_UNAVAILABLE, "NetworkManager is not running."); @@ -807,7 +637,7 @@ nm_remote_settings_reload_connections (NMRemoteSettings *settings, priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); - if (!priv->service_running) { + if (!_nm_object_get_nm_running (NM_OBJECT (settings))) { g_set_error_literal (error, NM_REMOTE_SETTINGS_ERROR, NM_REMOTE_SETTINGS_ERROR_SERVICE_UNAVAILABLE, "NetworkManager is not running."); @@ -822,29 +652,6 @@ nm_remote_settings_reload_connections (NMRemoteSettings *settings, return success; } -static void -clear_one_hash (GHashTable *table) -{ - GHashTableIter iter; - gpointer value; - GSList *list = NULL, *list_iter; - - /* Build up the list of connections; we can't emit "removed" during hash - * table iteration because emission of the "removed" signal may trigger code - * that explicitly removes the connection from the hash table somewhere - * else. - */ - g_hash_table_iter_init (&iter, table); - while (g_hash_table_iter_next (&iter, NULL, &value)) - list = g_slist_prepend (list, NM_REMOTE_CONNECTION (value)); - - for (list_iter = list; list_iter; list_iter = g_slist_next (list_iter)) - g_signal_emit_by_name (NM_REMOTE_CONNECTION (list_iter->data), NM_REMOTE_CONNECTION_REMOVED); - g_slist_free (list); - - g_hash_table_remove_all (table); -} - typedef struct { NMRemoteSettings *settings; NMRemoteSettingsSaveHostnameFunc callback; @@ -894,7 +701,7 @@ nm_remote_settings_save_hostname (NMRemoteSettings *settings, priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); - if (!priv->service_running) + if (!_nm_object_get_nm_running (NM_OBJECT (settings))) return FALSE; info = g_malloc0 (sizeof (SaveHostnameInfo)); @@ -912,91 +719,64 @@ nm_remote_settings_save_hostname (NMRemoteSettings *settings, } static void -properties_changed_cb (DBusGProxy *proxy, - GHashTable *properties, - gpointer user_data) +updated_properties (GObject *object, GAsyncResult *result, gpointer user_data) { NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data); - NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); - GHashTableIter iter; - gpointer key, tmp; + GError *error = NULL; - g_hash_table_iter_init (&iter, properties); - while (g_hash_table_iter_next (&iter, &key, &tmp)) { - GValue *value = tmp; - - if (!strcmp ((const char *) key, "Hostname")) { - g_free (priv->hostname); - priv->hostname = g_value_dup_string (value); - g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_HOSTNAME); - } - - if (!strcmp ((const char *) key, "CanModify")) { - priv->can_modify = g_value_get_boolean (value); - g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_CAN_MODIFY); - } + if (!_nm_object_reload_properties_finish (NM_OBJECT (object), result, &error)) { + g_warning ("%s: error reading NMRemoteSettings properties: %s", __func__, error->message); + g_error_free (error); } + + g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_NM_RUNNING); } static void -nm_appeared_got_properties (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) -{ - NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data); - NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); - GHashTable *props = NULL; - - if (dbus_g_proxy_end_call (proxy, call, NULL, - DBUS_TYPE_G_MAP_OF_VARIANT, &props, - G_TYPE_INVALID)) { - properties_changed_cb (priv->props_proxy, props, self); - g_hash_table_destroy (props); - } -} - -static void -name_owner_changed (DBusGProxy *proxy, - const char *name, - const char *old_owner, - const char *new_owner, +nm_running_changed (GObject *object, + GParamSpec *pspec, gpointer user_data) { - NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data); + NMRemoteSettings *self = NM_REMOTE_SETTINGS (object); NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); - const char *sname = NM_DBUS_SERVICE; - if (!strcmp (name, sname)) { - if (new_owner && strlen (new_owner) > 0) { - priv->service_running = TRUE; + g_object_freeze_notify (object); - priv->listcon_call = dbus_g_proxy_begin_call (priv->proxy, "ListConnections", - fetch_connections_done, self, NULL, - G_TYPE_INVALID); + if (!_nm_object_get_nm_running (NM_OBJECT (self))) { + if (priv->all_connections) { + GPtrArray *connections; + int i; - dbus_g_proxy_begin_call (priv->props_proxy, "GetAll", - nm_appeared_got_properties, self, NULL, - G_TYPE_STRING, NM_DBUS_INTERFACE_SETTINGS, - G_TYPE_INVALID); - } else { - priv->service_running = FALSE; + connections = priv->all_connections; + priv->all_connections = NULL; - clear_one_hash (priv->pending); - clear_one_hash (priv->connections); + for (i = 0; i < connections->len; i++) { + g_signal_emit (self, signals[CONNECTION_REMOVED], 0, connections->pdata[i]); + g_object_unref (connections->pdata[i]); + } + g_ptr_array_unref (connections); + } - /* Clear properties */ + /* Clear properties */ + if (priv->hostname) { g_free (priv->hostname); priv->hostname = NULL; g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_HOSTNAME); + } + if (priv->can_modify) { priv->can_modify = FALSE; g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_CAN_MODIFY); - - if (priv->listcon_call) { - dbus_g_proxy_cancel_call (priv->proxy, priv->listcon_call); - priv->listcon_call = NULL; - } } - g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_SERVICE_RUNNING); + + _nm_object_suppress_property_updates (NM_OBJECT (self), TRUE); + g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_NM_RUNNING); + } else { + _nm_object_suppress_property_updates (NM_OBJECT (self), FALSE); + _nm_object_reload_properties_async (NM_OBJECT (self), updated_properties, self); } + + g_object_thaw_notify (object); } /****************************************************************/ @@ -1022,20 +802,6 @@ nm_remote_settings_new (GCancellable *cancellable, NULL); } -static void -remote_settings_inited (GObject *source, GAsyncResult *result, gpointer user_data) -{ - GSimpleAsyncResult *simple = user_data; - GError *error = NULL; - - if (!g_async_initable_new_finish (G_ASYNC_INITABLE (source), result, &error)) - g_simple_async_result_take_error (simple, error); - else - g_simple_async_result_set_op_res_gpointer (simple, source, g_object_unref); - g_simple_async_result_complete (simple); - g_object_unref (simple); -} - /** * nm_remote_settings_new_async: * @cancellable: a #GCancellable, or %NULL @@ -1049,14 +815,11 @@ remote_settings_inited (GObject *source, GAsyncResult *result, gpointer user_dat **/ void nm_remote_settings_new_async (GCancellable *cancellable, - GAsyncReadyCallback callback, gpointer user_data) + GAsyncReadyCallback callback, + gpointer user_data) { - GSimpleAsyncResult *simple; - - simple = g_simple_async_result_new (NULL, callback, user_data, nm_remote_settings_new_async); - g_async_initable_new_async (NM_TYPE_REMOTE_SETTINGS, G_PRIORITY_DEFAULT, cancellable, - remote_settings_inited, simple, + callback, user_data, NULL); } @@ -1072,27 +835,14 @@ nm_remote_settings_new_async (GCancellable *cancellable, NMRemoteSettings * nm_remote_settings_new_finish (GAsyncResult *result, GError **error) { - GSimpleAsyncResult *simple; + GObject *source; + NMRemoteSettings *settings; - g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, nm_remote_settings_new_async), NULL); + source = g_async_result_get_source_object (result); + settings = (NMRemoteSettings *) g_async_initable_new_finish (G_ASYNC_INITABLE (source), result, error); + g_object_unref (source); - simple = G_SIMPLE_ASYNC_RESULT (result); - if (g_simple_async_result_propagate_error (simple, error)) - return NULL; - else - return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple)); -} - -static void -forget_connection (gpointer user_data) -{ - NMRemoteConnection *remote = NM_REMOTE_CONNECTION (user_data); - - g_signal_handlers_disconnect_matched (remote, G_SIGNAL_MATCH_FUNC, - 0, 0, NULL, connection_removed_cb, NULL); - g_signal_handlers_disconnect_matched (remote, G_SIGNAL_MATCH_FUNC, - 0, 0, NULL, connection_visible_cb, NULL); - g_object_unref (remote); + return settings; } static void @@ -1100,235 +850,61 @@ nm_remote_settings_init (NMRemoteSettings *self) { NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); - priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, forget_connection); - priv->pending = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, forget_connection); + priv->visible_connections = g_ptr_array_new (); } static void -init_common (NMRemoteSettings *self) +init_dbus (NMObject *object) { - NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_REMOTE_SETTINGS_CONNECTIONS, &priv->all_connections, NULL, NM_TYPE_REMOTE_CONNECTION, "connection" }, + { NM_REMOTE_SETTINGS_HOSTNAME, &priv->hostname }, + { NM_REMOTE_SETTINGS_CAN_MODIFY, &priv->can_modify }, + { NULL }, + }; - if (priv->private_bus == FALSE) { - /* D-Bus proxy for clearing connections on NameOwnerChanged */ - priv->dbus_proxy = dbus_g_proxy_new_for_name (priv->bus, - DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS); - g_assert (priv->dbus_proxy); + NM_OBJECT_CLASS (nm_remote_settings_parent_class)->init_dbus (object); - dbus_g_object_register_marshaller (g_cclosure_marshal_generic, - G_TYPE_NONE, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_INVALID); - dbus_g_proxy_add_signal (priv->dbus_proxy, "NameOwnerChanged", - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->dbus_proxy, - "NameOwnerChanged", - G_CALLBACK (name_owner_changed), - self, NULL); - } + priv->proxy = _nm_object_new_proxy (object, + NM_DBUS_PATH_SETTINGS, + NM_DBUS_INTERFACE_SETTINGS); + _nm_object_register_properties (object, + priv->proxy, + property_info); - priv->proxy = _nm_dbus_new_proxy_for_connection (priv->bus, - NM_DBUS_PATH_SETTINGS, - NM_DBUS_INTERFACE_SETTINGS); - g_assert (priv->proxy); - dbus_g_proxy_set_default_timeout (priv->proxy, G_MAXINT); - - dbus_g_proxy_add_signal (priv->proxy, "NewConnection", - DBUS_TYPE_G_OBJECT_PATH, - G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "NewConnection", - G_CALLBACK (new_connection_cb), - self, - NULL); - - /* D-Bus properties proxy */ - priv->props_proxy = _nm_dbus_new_proxy_for_connection (priv->bus, - NM_DBUS_PATH_SETTINGS, - "org.freedesktop.DBus.Properties"); - g_assert (priv->props_proxy); - - /* Monitor properties */ - dbus_g_object_register_marshaller (g_cclosure_marshal_generic, - G_TYPE_NONE, - DBUS_TYPE_G_MAP_OF_VARIANT, - G_TYPE_INVALID); - dbus_g_proxy_add_signal (priv->proxy, "PropertiesChanged", - DBUS_TYPE_G_MAP_OF_VARIANT, - G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "PropertiesChanged", - G_CALLBACK (properties_changed_cb), - self, - NULL); + g_signal_connect (object, "notify::" NM_OBJECT_NM_RUNNING, + G_CALLBACK (nm_running_changed), NULL); } -static gboolean -init_sync (GInitable *initable, GCancellable *cancellable, GError **error) +static GObject * +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) { - NMRemoteSettings *settings = NM_REMOTE_SETTINGS (initable); - NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); - GHashTable *props; + guint i; + const char *dbus_path; - init_common (settings); - - if (priv->private_bus == FALSE) { - if (!dbus_g_proxy_call (priv->dbus_proxy, "NameHasOwner", error, - G_TYPE_STRING, NM_DBUS_SERVICE, - G_TYPE_INVALID, - G_TYPE_BOOLEAN, &priv->service_running, - G_TYPE_INVALID)) { - priv->service_running = FALSE; - return FALSE; + /* Fill in the right D-Bus path if none was specified */ + for (i = 0; i < n_construct_params; i++) { + if (strcmp (construct_params[i].pspec->name, NM_OBJECT_DBUS_PATH) == 0) { + dbus_path = g_value_get_string (construct_params[i].value); + if (dbus_path == NULL) { + g_value_set_static_string (construct_params[i].value, NM_DBUS_PATH_SETTINGS); + } else { + if (!g_variant_is_object_path (dbus_path)) { + g_warning ("Passed D-Bus object path '%s' is invalid; using default '%s' instead", + dbus_path, NM_DBUS_PATH); + g_value_set_static_string (construct_params[i].value, NM_DBUS_PATH_SETTINGS); + } + } + break; } - - /* If NM isn't running we'll grab properties from name_owner_changed() - * when it starts. - */ - if (!priv->service_running) - return TRUE; - } else - priv->service_running = TRUE; - - priv->listcon_call = dbus_g_proxy_begin_call (priv->proxy, "ListConnections", - fetch_connections_done, NM_REMOTE_SETTINGS (initable), NULL, - G_TYPE_INVALID); - - /* Get properties */ - if (!dbus_g_proxy_call (priv->props_proxy, "GetAll", error, - G_TYPE_STRING, NM_DBUS_INTERFACE_SETTINGS, - G_TYPE_INVALID, - DBUS_TYPE_G_MAP_OF_VARIANT, &props, - G_TYPE_INVALID)) - return FALSE; - properties_changed_cb (priv->props_proxy, props, settings); - g_hash_table_destroy (props); - - return TRUE; -} - -typedef struct { - NMRemoteSettings *settings; - GSimpleAsyncResult *result; -} NMRemoteSettingsInitData; - -static void -init_async_complete (NMRemoteSettingsInitData *init_data) -{ - g_simple_async_result_complete (init_data->result); - g_object_unref (init_data->result); - g_slice_free (NMRemoteSettingsInitData, init_data); -} - -static void -init_read_connections (NMRemoteSettings *settings, gpointer user_data) -{ - NMRemoteSettingsInitData *init_data = user_data; - - g_signal_handlers_disconnect_by_func (settings, G_CALLBACK (init_read_connections), user_data); - - init_async_complete (init_data); -} - -static void -init_async_got_properties (DBusGProxy *proxy, DBusGProxyCall *call, - gpointer user_data) -{ - NMRemoteSettingsInitData *init_data = user_data; - NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (init_data->settings); - GHashTable *props; - GError *error = NULL; - - if (dbus_g_proxy_end_call (proxy, call, &error, - DBUS_TYPE_G_MAP_OF_VARIANT, &props, - G_TYPE_INVALID)) { - properties_changed_cb (priv->props_proxy, props, init_data->settings); - g_hash_table_destroy (props); - g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE); - } else - g_simple_async_result_take_error (init_data->result, error); - - /* Read connections and wait for the result */ - priv->listcon_call = dbus_g_proxy_begin_call (priv->proxy, "ListConnections", - fetch_connections_done, init_data->settings, NULL, - G_TYPE_INVALID); - g_signal_connect (init_data->settings, "connections-read", - G_CALLBACK (init_read_connections), init_data); -} - -static void -init_get_properties (NMRemoteSettingsInitData *init_data) -{ - NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (init_data->settings); - - dbus_g_proxy_begin_call (priv->props_proxy, "GetAll", - init_async_got_properties, init_data, NULL, - G_TYPE_STRING, NM_DBUS_INTERFACE_SETTINGS, - G_TYPE_INVALID); -} - -static void -init_async_got_manager_running (DBusGProxy *proxy, DBusGProxyCall *call, - gpointer user_data) -{ - NMRemoteSettingsInitData *init_data = user_data; - NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (init_data->settings); - GError *error = NULL; - - if (!dbus_g_proxy_end_call (proxy, call, &error, - G_TYPE_BOOLEAN, &priv->service_running, - G_TYPE_INVALID)) { - g_simple_async_result_take_error (init_data->result, error); - init_async_complete (init_data); - return; } - if (!priv->service_running) { - g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE); - init_async_complete (init_data); - return; - } - - init_get_properties (init_data); -} - -static void -init_async (GAsyncInitable *initable, int io_priority, - GCancellable *cancellable, GAsyncReadyCallback callback, - gpointer user_data) -{ - NMRemoteSettingsInitData *init_data; - NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (initable); - - init_data = g_slice_new0 (NMRemoteSettingsInitData); - init_data->settings = NM_REMOTE_SETTINGS (initable); - init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback, - user_data, init_async); - - init_common (init_data->settings); - - if (priv->private_bus) - init_get_properties (init_data); - else { - /* Check if NM is running */ - dbus_g_proxy_begin_call (priv->dbus_proxy, "NameHasOwner", - init_async_got_manager_running, - init_data, NULL, - G_TYPE_STRING, NM_DBUS_SERVICE, - G_TYPE_INVALID); - } -} - -static gboolean -init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error) -{ - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); - - if (g_simple_async_result_propagate_error (simple, error)) - return FALSE; - else - return TRUE; + return G_OBJECT_CLASS (nm_remote_settings_parent_class)->constructor (type, + n_construct_params, + construct_params); } static void @@ -1340,52 +916,22 @@ dispose (GObject *object) while (g_slist_length (priv->add_list)) add_connection_info_dispose (self, (AddConnectionInfo *) priv->add_list->data); - if (priv->connections) { - g_hash_table_destroy (priv->connections); - priv->connections = NULL; + if (priv->all_connections) { + int i; + + for (i = 0; i < priv->all_connections->len; i++) { + cleanup_connection (self, priv->all_connections->pdata[i]); + g_object_unref (priv->all_connections->pdata[i]); + } + g_clear_pointer (&priv->all_connections, g_ptr_array_unref); } - - if (priv->pending) { - g_hash_table_destroy (priv->pending); - priv->pending = NULL; - } - - g_free (priv->hostname); - priv->hostname = NULL; - - g_clear_object (&priv->dbus_proxy); + g_clear_pointer (&priv->visible_connections, g_ptr_array_unref); + g_clear_pointer (&priv->hostname, g_free); g_clear_object (&priv->proxy); - g_clear_object (&priv->props_proxy); - - if (priv->bus) { - dbus_g_connection_unref (priv->bus); - priv->bus = NULL; - } G_OBJECT_CLASS (nm_remote_settings_parent_class)->dispose (object); } -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_BUS: - /* Construct only */ - priv->bus = g_value_dup_boxed (value); - if (!priv->bus) { - priv->bus = _nm_dbus_new_connection (NULL); - priv->private_bus = _nm_dbus_is_connection_private (priv->bus); - } - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) @@ -1393,11 +939,11 @@ get_property (GObject *object, guint prop_id, NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object); switch (prop_id) { - case PROP_BUS: - g_value_set_boxed (value, priv->bus); + case PROP_NM_RUNNING: + g_value_set_boolean (value, _nm_object_get_nm_running (NM_OBJECT (object))); break; - case PROP_SERVICE_RUNNING: - g_value_set_boolean (value, priv->service_running); + case PROP_CONNECTIONS: + g_value_set_boxed (value, priv->visible_connections); break; case PROP_HOSTNAME: g_value_set_string (value, priv->hostname); @@ -1415,42 +961,52 @@ static void nm_remote_settings_class_init (NMRemoteSettingsClass *class) { GObjectClass *object_class = G_OBJECT_CLASS (class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (class); g_type_class_add_private (class, sizeof (NMRemoteSettingsPrivate)); /* Virtual methods */ - object_class->set_property = set_property; + object_class->constructor = constructor; object_class->get_property = get_property; object_class->dispose = dispose; + nm_object_class->init_dbus = init_dbus; + nm_object_class->object_creation_failed = object_creation_failed; + + class->connection_added = connection_added; + class->connection_removed = connection_removed; + /* Properties */ /** - * NMRemoteSettings:bus: + * NMRemoteSettings:nm-running: * - * The #DBusGConnection that the #NMRemoteSettings is connected to. Defaults - * to the system bus if not specified. + * Whether the NetworkManager settings service is running. */ g_object_class_install_property - (object_class, PROP_BUS, - g_param_spec_boxed (NM_REMOTE_SETTINGS_BUS, "", "", - DBUS_TYPE_G_CONNECTION, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - /** - * NMRemoteSettings:service-running: - * - * Whether the settings service is running. - */ - g_object_class_install_property - (object_class, PROP_SERVICE_RUNNING, - g_param_spec_boolean (NM_REMOTE_SETTINGS_SERVICE_RUNNING, "", "", + (object_class, PROP_NM_RUNNING, + g_param_spec_boolean (NM_REMOTE_SETTINGS_NM_RUNNING, "", "", FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + /** + * NMRemoteSettings:connections: + * + * The list of configured connections that are available to the user. (Note + * that this differs from the underlying D-Bus property, which may also + * contain the object paths of connections that the user does not have + * permission to read the details of.) + * + * Type: GPtrArray + */ + g_object_class_install_property + (object_class, PROP_CONNECTIONS, + g_param_spec_boxed (NM_REMOTE_SETTINGS_CONNECTIONS, "", "", + NM_TYPE_OBJECT_ARRAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + /** * NMRemoteSettings:hostname: * @@ -1477,32 +1033,35 @@ nm_remote_settings_class_init (NMRemoteSettingsClass *class) G_PARAM_STATIC_STRINGS)); /* Signals */ - signals[NEW_CONNECTION] = - g_signal_new (NM_REMOTE_SETTINGS_NEW_CONNECTION, + /** + * NMRemoteSettings::connection-added: + * @settings: the settings object that received the signal + * @connection: the new connection + * + * Notifies that a #NMConnection has been added. + **/ + signals[CONNECTION_ADDED] = + g_signal_new (NM_REMOTE_SETTINGS_CONNECTION_ADDED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMRemoteSettingsClass, new_connection), + G_STRUCT_OFFSET (NMRemoteSettingsClass, connection_added), NULL, NULL, NULL, - G_TYPE_NONE, 1, G_TYPE_OBJECT); + G_TYPE_NONE, 1, + NM_TYPE_REMOTE_CONNECTION); - signals[CONNECTIONS_READ] = - g_signal_new (NM_REMOTE_SETTINGS_CONNECTIONS_READ, + /** + * NMRemoteSettings::connection-removed: + * @settings: the settings object that received the signal + * @connection: the removed connection + * + * Notifies that a #NMConnection has been removed. + **/ + signals[CONNECTION_REMOVED] = + g_signal_new (NM_REMOTE_SETTINGS_CONNECTION_REMOVED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMRemoteSettingsClass, connections_read), + G_STRUCT_OFFSET (NMRemoteSettingsClass, connection_removed), NULL, NULL, NULL, - G_TYPE_NONE, 0); -} - -static void -nm_remote_settings_initable_iface_init (GInitableIface *iface) -{ - iface->init = init_sync; -} - -static void -nm_remote_settings_async_initable_iface_init (GAsyncInitableIface *iface) -{ - iface->init_async = init_async; - iface->init_finish = init_finish; + G_TYPE_NONE, 1, + NM_TYPE_REMOTE_CONNECTION); } diff --git a/libnm/nm-remote-settings.h b/libnm/nm-remote-settings.h index aebd2c0c83..7ba7527fb2 100644 --- a/libnm/nm-remote-settings.h +++ b/libnm/nm-remote-settings.h @@ -27,6 +27,7 @@ #endif #include +#include #include #include @@ -62,13 +63,13 @@ typedef enum { GQuark nm_remote_settings_error_quark (void); -#define NM_REMOTE_SETTINGS_BUS "bus" -#define NM_REMOTE_SETTINGS_SERVICE_RUNNING "service-running" +#define NM_REMOTE_SETTINGS_NM_RUNNING "nm-running" +#define NM_REMOTE_SETTINGS_CONNECTIONS "connections" #define NM_REMOTE_SETTINGS_HOSTNAME "hostname" #define NM_REMOTE_SETTINGS_CAN_MODIFY "can-modify" -#define NM_REMOTE_SETTINGS_NEW_CONNECTION "new-connection" -#define NM_REMOTE_SETTINGS_CONNECTIONS_READ "connections-read" +#define NM_REMOTE_SETTINGS_CONNECTION_ADDED "connection-added" +#define NM_REMOTE_SETTINGS_CONNECTION_REMOVED "connection-removed" typedef struct _NMRemoteSettings NMRemoteSettings; typedef struct _NMRemoteSettingsClass NMRemoteSettingsClass; @@ -90,17 +91,17 @@ typedef void (*NMRemoteSettingsSaveHostnameFunc) (NMRemoteSettings *settings, struct _NMRemoteSettings { - GObject parent; + NMObject parent; }; struct _NMRemoteSettingsClass { - GObjectClass parent; + NMObjectClass parent; /* Signals */ - void (*new_connection) (NMRemoteSettings *settings, - NMRemoteConnection *connection); - - void (*connections_read) (NMRemoteSettings *settings); + void (*connection_added) (NMRemoteSettings *settings, + NMRemoteConnection *connection); + void (*connection_removed) (NMRemoteSettings *settings, + NMRemoteConnection *connection); /*< private >*/ gpointer padding[8]; diff --git a/libnm/tests/test-nm-client.c b/libnm/tests/test-nm-client.c index 1fa5101db9..3f1e95496c 100644 --- a/libnm/tests/test-nm-client.c +++ b/libnm/tests/test-nm-client.c @@ -808,9 +808,9 @@ test_devices_array (void) } static void -manager_running_changed (GObject *client, - GParamSpec *pspec, - gpointer user_data) +nm_running_changed (GObject *client, + GParamSpec *pspec, + gpointer user_data) { int *running_changed = user_data; @@ -819,7 +819,7 @@ manager_running_changed (GObject *client, } static void -test_client_manager_running (void) +test_client_nm_running (void) { NMClient *client1, *client2; guint quit_id; @@ -828,7 +828,7 @@ test_client_manager_running (void) client1 = test_client_new (); - g_assert (!nm_client_get_manager_running (client1)); + g_assert (!nm_client_get_nm_running (client1)); g_assert_cmpstr (nm_client_get_version (client1), ==, NULL); g_assert (!nm_client_networking_get_enabled (client1)); @@ -848,26 +848,26 @@ test_client_manager_running (void) /* client2 should know that NM is running, but the previously-created * client1 hasn't gotten the news yet. */ - g_assert (!nm_client_get_manager_running (client1)); - g_assert (nm_client_get_manager_running (client2)); + g_assert (!nm_client_get_nm_running (client1)); + g_assert (nm_client_get_nm_running (client2)); - g_signal_connect (client1, "notify::" NM_CLIENT_MANAGER_RUNNING, - G_CALLBACK (manager_running_changed), &running_changed); + g_signal_connect (client1, "notify::" NM_CLIENT_NM_RUNNING, + G_CALLBACK (nm_running_changed), &running_changed); quit_id = g_timeout_add_seconds (5, loop_quit, loop); g_main_loop_run (loop); g_assert_cmpint (running_changed, ==, 1); - g_assert (nm_client_get_manager_running (client1)); + g_assert (nm_client_get_nm_running (client1)); g_source_remove (quit_id); /* And kill it */ g_clear_pointer (&sinfo, nm_test_service_cleanup); - g_assert (nm_client_get_manager_running (client1)); + g_assert (nm_client_get_nm_running (client1)); quit_id = g_timeout_add_seconds (5, loop_quit, loop); g_main_loop_run (loop); g_assert_cmpint (running_changed, ==, 2); - g_assert (!nm_client_get_manager_running (client1)); + g_assert (!nm_client_get_nm_running (client1)); g_source_remove (quit_id); g_object_unref (client1); @@ -891,7 +891,7 @@ main (int argc, char **argv) g_test_add_func ("/libnm/wifi-ap-added-removed", test_wifi_ap_added_removed); g_test_add_func ("/libnm/wimax-nsp-added-removed", test_wimax_nsp_added_removed); g_test_add_func ("/libnm/devices-array", test_devices_array); - g_test_add_func ("/libnm/client-manager-running", test_client_manager_running); + g_test_add_func ("/libnm/client-nm-running", test_client_nm_running); return g_test_run (); } diff --git a/libnm/tests/test-remote-settings-client.c b/libnm/tests/test-remote-settings-client.c index 0f99a6ff43..d0ba50428d 100644 --- a/libnm/tests/test-remote-settings-client.c +++ b/libnm/tests/test-remote-settings-client.c @@ -34,6 +34,8 @@ #include "nm-remote-settings.h" #include "common.h" +#include "nm-test-utils.h" + static NMTestServiceInfo *sinfo; static NMRemoteSettings *settings = NULL; DBusGConnection *bus = NULL; @@ -47,8 +49,7 @@ add_cb (NMRemoteSettings *s, GError *error, gpointer user_data) { - if (error) - g_warning ("Add error: %s", error->message); + g_assert_no_error (error); *((gboolean *) user_data) = TRUE; remote = connection; @@ -61,27 +62,11 @@ static void test_add_connection (void) { NMConnection *connection; - NMSettingConnection *s_con; - NMSettingWired *s_wired; - char *uuid; gboolean success; time_t start, now; gboolean done = FALSE; - connection = nm_connection_new (); - - s_con = (NMSettingConnection *) nm_setting_connection_new (); - uuid = nm_utils_uuid_generate (); - g_object_set (G_OBJECT (s_con), - NM_SETTING_CONNECTION_ID, TEST_CON_ID, - NM_SETTING_CONNECTION_UUID, uuid, - NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, - NULL); - g_free (uuid); - nm_connection_add_setting (connection, NM_SETTING (s_con)); - - s_wired = (NMSettingWired *) nm_setting_wired_new (); - nm_connection_add_setting (connection, NM_SETTING (s_wired)); + connection = nmtst_create_minimal_connection (TEST_CON_ID, NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); success = nm_remote_settings_add_connection (settings, connection, @@ -101,6 +86,7 @@ test_add_connection (void) g_assert (nm_connection_compare (connection, NM_CONNECTION (remote), NM_SETTING_COMPARE_FLAG_EXACT) == TRUE); + g_object_unref (connection); } /*******************************************************************/ @@ -119,9 +105,17 @@ set_visible_cb (DBusGProxy *proxy, } static void -invis_removed_cb (NMRemoteConnection *connection, gboolean *done) +visible_changed_cb (GObject *object, GParamSpec *pspec, gboolean *done) { - *done = TRUE; + if (!nm_remote_connection_get_visible (NM_REMOTE_CONNECTION (object))) + *done = TRUE; +} + +static void +connection_removed_cb (NMRemoteSettings *s, NMRemoteConnection *connection, gboolean *done) +{ + if (connection == remote) + *done = TRUE; } static void @@ -140,13 +134,15 @@ test_make_invisible (void) time_t start, now; GSList *list, *iter; DBusGProxy *proxy; - gboolean done = FALSE, has_settings = FALSE; + gboolean visible_changed = FALSE, connection_removed = FALSE; + gboolean has_settings = FALSE; char *path; g_assert (remote != NULL); /* Listen for the remove event when the connection becomes invisible */ - g_signal_connect (remote, "removed", G_CALLBACK (invis_removed_cb), &done); + g_signal_connect (remote, "notify::" NM_REMOTE_CONNECTION_VISIBLE, G_CALLBACK (visible_changed_cb), &visible_changed); + g_signal_connect (settings, "connection-removed", G_CALLBACK (connection_removed_cb), &connection_removed); path = g_strdup (nm_connection_get_path (NM_CONNECTION (remote))); proxy = dbus_g_proxy_new_for_name (bus, @@ -164,11 +160,12 @@ test_make_invisible (void) do { now = time (NULL); g_main_context_iteration (NULL, FALSE); - } while ((done == FALSE) && (now - start < 5)); - g_assert (done == TRUE); + } while ((!visible_changed || !connection_removed) && (now - start < 5)); + g_assert (visible_changed == TRUE); + g_assert (connection_removed == TRUE); - g_assert (remote); - g_signal_handlers_disconnect_by_func (remote, G_CALLBACK (invis_removed_cb), &done); + g_signal_handlers_disconnect_by_func (remote, G_CALLBACK (visible_changed_cb), &visible_changed); + g_signal_handlers_disconnect_by_func (settings, G_CALLBACK (connection_removed_cb), &connection_removed); /* Ensure NMRemoteSettings no longer has the connection */ list = nm_remote_settings_list_connections (settings); @@ -213,7 +210,7 @@ test_make_visible (void) g_assert (remote != NULL); /* Wait for the new-connection signal when the connection is visible again */ - g_signal_connect (settings, NM_REMOTE_SETTINGS_NEW_CONNECTION, + g_signal_connect (settings, NM_REMOTE_SETTINGS_CONNECTION_ADDED, G_CALLBACK (vis_new_connection_cb), &new); path = g_strdup (nm_connection_get_path (NM_CONNECTION (remote))); @@ -275,9 +272,10 @@ deleted_cb (DBusGProxy *proxy, } static void -removed_cb (NMRemoteConnection *connection, gboolean *done) +removed_cb (NMRemoteSettings *s, NMRemoteConnection *connection, gboolean *done) { - *done = TRUE; + if (connection == remote) + *done = TRUE; } static void @@ -298,7 +296,7 @@ test_remove_connection (void) g_assert (connection); g_assert (remote == connection); path = g_strdup (nm_connection_get_path (NM_CONNECTION (connection))); - g_signal_connect (connection, "removed", G_CALLBACK (removed_cb), &done); + g_signal_connect (settings, "connection-removed", G_CALLBACK (removed_cb), &done); proxy = dbus_g_proxy_new_for_name (bus, NM_DBUS_SERVICE, @@ -333,6 +331,61 @@ test_remove_connection (void) /*******************************************************************/ +#define TEST_ADD_REMOVE_ID "add-remove-test-connection" + +static void +add_remove_cb (NMRemoteSettings *s, + NMRemoteConnection *connection, + GError *error, + gpointer user_data) +{ + g_assert_error (error, NM_REMOTE_SETTINGS_ERROR, NM_REMOTE_SETTINGS_ERROR_CONNECTION_REMOVED); + g_assert (connection == NULL); + + *((gboolean *) user_data) = TRUE; +} + +static void +test_add_remove_connection (void) +{ + GVariant *ret; + GError *error = NULL; + NMConnection *connection; + gboolean success; + time_t start, now; + gboolean done = FALSE; + + /* This will cause the test server to immediately delete the connection + * after creating it. + */ + ret = g_dbus_proxy_call_sync (sinfo->proxy, + "AutoRemoveNextConnection", + NULL, + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, + &error); + g_assert_no_error (error); + g_variant_unref (ret); + + connection = nmtst_create_minimal_connection (TEST_ADD_REMOVE_ID, NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); + success = nm_remote_settings_add_connection (settings, + connection, + add_remove_cb, + &done); + g_assert (success == TRUE); + + start = time (NULL); + do { + now = time (NULL); + g_main_context_iteration (NULL, FALSE); + } while ((done == FALSE) && (now - start < 5)); + g_assert (done == TRUE); + + g_object_unref (connection); +} + +/*******************************************************************/ + static GMainLoop *loop; static gboolean @@ -343,9 +396,9 @@ loop_quit (gpointer user_data) } static void -settings_service_running_changed (GObject *client, - GParamSpec *pspec, - gpointer user_data) +settings_nm_running_changed (GObject *client, + GParamSpec *pspec, + gpointer user_data) { int *running_changed = user_data; @@ -354,7 +407,7 @@ settings_service_running_changed (GObject *client, } static void -test_service_running (void) +test_nm_running (void) { NMRemoteSettings *settings2; guint quit_id; @@ -365,7 +418,7 @@ test_service_running (void) loop = g_main_loop_new (NULL, FALSE); g_object_get (G_OBJECT (settings), - NM_REMOTE_SETTINGS_SERVICE_RUNNING, &running, + NM_REMOTE_SETTINGS_NM_RUNNING, &running, NULL); g_assert (running == TRUE); @@ -373,7 +426,7 @@ test_service_running (void) nm_test_service_cleanup (sinfo); settings2 = g_initable_new (NM_TYPE_REMOTE_SETTINGS, NULL, &error, - NM_REMOTE_SETTINGS_BUS, bus, + NM_OBJECT_DBUS_CONNECTION, bus, NULL); g_assert_no_error (error); g_assert (settings != NULL); @@ -382,23 +435,23 @@ test_service_running (void) * settings hasn't gotten the news yet. */ g_object_get (G_OBJECT (settings2), - NM_REMOTE_SETTINGS_SERVICE_RUNNING, &running, + NM_REMOTE_SETTINGS_NM_RUNNING, &running, NULL); g_assert (running == FALSE); g_object_get (G_OBJECT (settings), - NM_REMOTE_SETTINGS_SERVICE_RUNNING, &running, + NM_REMOTE_SETTINGS_NM_RUNNING, &running, NULL); g_assert (running == TRUE); - g_signal_connect (settings, "notify::" NM_REMOTE_SETTINGS_SERVICE_RUNNING, - G_CALLBACK (settings_service_running_changed), &running_changed); + g_signal_connect (settings, "notify::" NM_REMOTE_SETTINGS_NM_RUNNING, + G_CALLBACK (settings_nm_running_changed), &running_changed); quit_id = g_timeout_add_seconds (5, loop_quit, loop); g_main_loop_run (loop); g_assert_cmpint (running_changed, ==, 1); g_source_remove (quit_id); g_object_get (G_OBJECT (settings2), - NM_REMOTE_SETTINGS_SERVICE_RUNNING, &running, + NM_REMOTE_SETTINGS_NM_RUNNING, &running, NULL); g_assert (running == FALSE); @@ -411,7 +464,7 @@ test_service_running (void) g_source_remove (quit_id); g_object_get (G_OBJECT (settings2), - NM_REMOTE_SETTINGS_SERVICE_RUNNING, &running, + NM_REMOTE_SETTINGS_NM_RUNNING, &running, NULL); g_assert (running == TRUE); @@ -438,7 +491,7 @@ main (int argc, char **argv) sinfo = nm_test_service_init (); settings = g_initable_new (NM_TYPE_REMOTE_SETTINGS, NULL, &error, - NM_REMOTE_SETTINGS_BUS, bus, + NM_OBJECT_DBUS_CONNECTION, bus, NULL); g_assert_no_error (error); g_assert (settings != NULL); @@ -450,7 +503,8 @@ main (int argc, char **argv) g_test_add_func ("/remote_settings/make_invisible", test_make_invisible); g_test_add_func ("/remote_settings/make_visible", test_make_visible); g_test_add_func ("/remote_settings/remove_connection", test_remove_connection); - g_test_add_func ("/remote_settings/service_running", test_service_running); + g_test_add_func ("/remote_settings/add_remove_connection", test_add_remove_connection); + g_test_add_func ("/remote_settings/nm_running", test_nm_running); ret = g_test_run (); diff --git a/tools/test-networkmanager-service.py b/tools/test-networkmanager-service.py index 437381eb06..e04621fba2 100755 --- a/tools/test-networkmanager-service.py +++ b/tools/test-networkmanager-service.py @@ -747,6 +747,10 @@ class NetworkManager(ExportedObj): return raise UnknownDeviceException("Device not found") + @dbus.service.method(IFACE_TEST, in_signature='', out_signature='') + def AutoRemoveNextConnection(self): + settings.auto_remove_next_connection() + ################################################################### IFACE_CONNECTION = 'org.freedesktop.NetworkManager.Settings.Connection' @@ -789,6 +793,7 @@ class Connection(dbus.service.Object): @dbus.service.method(dbus_interface=IFACE_CONNECTION, in_signature='', out_signature='') def Delete(self): + self.remove_from_connection() self.remove_func(self) self.Removed() @@ -809,10 +814,14 @@ class Settings(dbus.service.Object): self.connections = {} self.bus = bus self.counter = 1 + self.remove_next_connection = False self.props = {} self.props['Hostname'] = "foobar.baz" self.props['CanModify'] = True + def auto_remove_next_connection(self): + self.remove_next_connection = True; + @dbus.service.method(dbus_interface=IFACE_SETTINGS, in_signature='', out_signature='ao') def ListConnections(self): return self.connections.keys() @@ -824,6 +833,11 @@ class Settings(dbus.service.Object): self.connections[path] = Connection(self.bus, path, settings, self.delete_connection) self.NewConnection(path) self.PropertiesChanged({ 'connections': dbus.Array(self.connections.keys(), 'o') }) + + if self.remove_next_connection: + self.remove_next_connection = False + self.connections[path].Delete() + return path def delete_connection(self, connection): @@ -870,8 +884,11 @@ def main(): random.seed() bus = dbus.SessionBus() + + global manager, settings manager = NetworkManager(bus, "/org/freedesktop/NetworkManager") settings = Settings(bus, "/org/freedesktop/NetworkManager/Settings") + if not bus.request_name("org.freedesktop.NetworkManager"): sys.exit(1)