diff options
Diffstat (limited to 'clients/cli')
| -rw-r--r-- | clients/cli/connections.c | 58 | ||||
| -rw-r--r-- | clients/cli/devices.c | 155 | ||||
| -rw-r--r-- | clients/cli/utils.c | 2 |
3 files changed, 143 insertions, 72 deletions
diff --git a/clients/cli/connections.c b/clients/cli/connections.c index bcd257ac..8a10691e 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -6534,6 +6534,12 @@ static gboolean nmc_editor_cb_called; static GError *nmc_editor_error; static MonitorACInfo *nmc_editor_monitor_ac; +static void +editor_connection_changed_cb (NMConnection *connection, gboolean *changed) +{ + *changed = TRUE; +} + /* * Store 'error' to shared 'nmc_editor_error' and monitoring info to * 'nmc_editor_monitor_ac' and signal the condition so that @@ -6579,8 +6585,8 @@ static gboolean progress_activation_editor_cb (gpointer user_data) { MonitorACInfo *info = (MonitorACInfo *) user_data; - gs_unref_object NMDevice *device = info->device; - gs_unref_object NMActiveConnection *ac = info->ac; + NMDevice *device = info->device; + NMActiveConnection *ac = info->ac; NMActiveConnectionState ac_state; NMDeviceState dev_state; @@ -6613,11 +6619,13 @@ progress_activation_editor_cb (gpointer user_data) nm_object_get_path (NM_OBJECT (connection))); } - return TRUE; + return G_SOURCE_CONTINUE; finish: + nm_g_object_unref (device); + nm_g_object_unref (ac); info->monitor_id = 0; - return FALSE; + return G_SOURCE_REMOVE; } static void @@ -7128,6 +7136,16 @@ menu_switch_to_level1 (const NmcConfig *nmc_config, } static gboolean +editor_save_timeout (gpointer user_data) +{ + gboolean *timeout = user_data; + + *timeout = TRUE; + + return G_SOURCE_REMOVE; +} + +static gboolean editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_type) { gs_unref_object NMRemoteConnection *rem_con = NULL; @@ -7646,6 +7664,10 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t /* Save the connection */ if (nm_connection_verify (connection, &err1)) { gboolean persistent = TRUE; + gboolean connection_changed; + nm_auto_unref_gsource GSource *source = NULL; + gboolean timeout = FALSE; + gulong handler_id = 0; /* parse argument */ if (cmd_arg) { @@ -7674,23 +7696,44 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t connection, add_connection_editor_cb, info); + connection_changed = TRUE; } else { /* Save/update already saved (existing) connection */ nm_connection_replace_settings_from_connection (NM_CONNECTION (rem_con), connection); update_connection (persistent, rem_con, update_connection_editor_cb, NULL); + + handler_id = g_signal_connect (rem_con, + NM_CONNECTION_CHANGED, + G_CALLBACK (editor_connection_changed_cb), + &connection_changed); + connection_changed = FALSE; } - //FIXME: add also a timeout for cases the callback is not called - while (!nmc_editor_cb_called) + source = g_timeout_source_new (10 * NM_UTILS_MSEC_PER_SECOND); + g_source_set_callback (source, editor_save_timeout, &timeout, NULL); + g_source_attach (source, g_main_loop_get_context (loop)); + + while (!nmc_editor_cb_called && !timeout) g_main_context_iteration (NULL, TRUE); + while (!connection_changed && !timeout) + g_main_context_iteration (NULL, TRUE); + + if (handler_id) + g_signal_handler_disconnect (rem_con, handler_id); + g_source_destroy (source); + if (nmc_editor_error) { g_print (_("Error: Failed to save '%s' (%s) connection: %s\n"), nm_connection_get_id (connection), nm_connection_get_uuid (connection), nmc_editor_error->message); g_error_free (nmc_editor_error); + } else if (timeout) { + g_print (_("Error: Timeout saving '%s' (%s) connection\n"), + nm_connection_get_id (connection), + nm_connection_get_uuid (connection)); } else { g_print (!rem_con ? _("Connection '%s' (%s) successfully saved.\n") : @@ -7713,9 +7756,10 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t if (menu_ctx.curr_setting) s_name = g_strdup (nm_setting_get_name (menu_ctx.curr_setting)); - /* Update settings in the local connection */ + /* Update settings and secrets in the local connection */ nm_connection_replace_settings_from_connection (connection, NM_CONNECTION (con_tmp)); + update_secrets_in_connection (con_tmp, connection); /* Also update setting for menu context and TAB-completion */ menu_ctx.curr_setting = s_name ? nm_connection_get_setting_by_name (connection, s_name) : NULL; diff --git a/clients/cli/devices.c b/clients/cli/devices.c index 029ca671..5aaf4ef8 100644 --- a/clients/cli/devices.c +++ b/clients/cli/devices.c @@ -2094,6 +2094,7 @@ typedef struct { GSList *queue; guint timeout_id; gboolean cmd_disconnect; + GCancellable *cancellable; } DeviceCbInfo; static void device_cb_info_finish (DeviceCbInfo *info, NMDevice *device); @@ -2166,7 +2167,10 @@ device_cb_info_finish (DeviceCbInfo *info, NMDevice *device) if (info->timeout_id) g_source_remove (info->timeout_id); + g_signal_handlers_disconnect_by_func (info->nmc->client, device_removed_cb, info); + nm_clear_g_cancellable (&info->cancellable); + g_slice_free (DeviceCbInfo, info); quit (); } @@ -2343,11 +2347,14 @@ disconnect_device_cb (GObject *object, GAsyncResult *result, gpointer user_data) { NMDevice *device = NM_DEVICE (object); DeviceCbInfo *info = (DeviceCbInfo *) user_data; - NmCli *nmc = info->nmc; + NmCli *nmc; NMDeviceState state; GError *error = NULL; if (!nm_device_disconnect_finish (device, result, &error)) { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + nmc = info->nmc; g_string_printf (nmc->return_text, _("Error: not all devices disconnected.")); g_printerr (_("Error: Device '%s' (%s) disconnecting failed: %s\n"), nm_device_get_iface (device), @@ -2357,6 +2364,7 @@ disconnect_device_cb (GObject *object, GAsyncResult *result, gpointer user_data) nmc->return_value = NMC_RESULT_ERROR_DEV_DISCONNECT; device_cb_info_finish (info, device); } else { + nmc = info->nmc; state = nm_device_get_state (device); if (nmc->nowait_flag || state <= NM_DEVICE_STATE_DISCONNECTED) { /* Don't want to wait or device already disconnected */ @@ -2393,6 +2401,7 @@ do_devices_disconnect (NmCli *nmc, int argc, char **argv) info = g_slice_new0 (DeviceCbInfo); info->nmc = nmc; info->cmd_disconnect = TRUE; + info->cancellable = g_cancellable_new (); if (nmc->timeout > 0) info->timeout_id = g_timeout_add_seconds (nmc->timeout, device_op_timeout_cb, info); @@ -2410,7 +2419,7 @@ do_devices_disconnect (NmCli *nmc, int argc, char **argv) G_CALLBACK (disconnect_state_cb), info); /* Now disconnect the device */ - nm_device_disconnect_async (device, NULL, disconnect_device_cb, info); + nm_device_disconnect_async (device, info->cancellable, disconnect_device_cb, info); } out: @@ -2795,7 +2804,7 @@ show_access_point_info (NMDeviceWifi *wifi, NmCli *nmc, NmcOutputData *out) aps = sort_access_points (nm_device_wifi_get_access_points (wifi)); g_ptr_array_foreach (aps, fill_output_access_point, &info); - g_ptr_array_free (aps, FALSE); + g_ptr_array_free (aps, TRUE); } print_data_prepare_width (out->output_data); @@ -2870,28 +2879,38 @@ wifi_print_aps (NMDeviceWifi *wifi, typedef struct { NmCli *nmc; - NMDeviceWifi *wifi; - const NMMetaAbstractInfo *const*tmpl; - + NMDevice **devices; + const NMMetaAbstractInfo *const *tmpl; const char *bssid_user; + GArray *out_indices; +} ScanInfo; + +typedef struct { + ScanInfo *scan_info; + NMDeviceWifi *wifi; gulong last_scan_id; guint timeout_id; GCancellable *scan_cancellable; - GArray *out_indices; } WifiListData; static void wifi_list_finish (WifiListData *data) { - NmCli *nmc = data->nmc; - - wifi_print_aps (data->wifi, data->nmc, data->out_indices, - data->tmpl, data->bssid_user); + ScanInfo *info = data->scan_info; + NmCli *nmc = info->nmc; + guint i; - if (--nmc->should_wait == 0) { + if (--info->nmc->should_wait == 0) { + for (i = 0; info->devices[i]; i++) { + wifi_print_aps (NM_DEVICE_WIFI (info->devices[i]), + info->nmc, + info->out_indices, + info->tmpl, + info->bssid_user); + } if (nmc->return_value == NMC_RESULT_ERROR_NOT_FOUND) { g_string_printf (nmc->return_text, _("Error: Access point with bssid '%s' not found."), - data->bssid_user); + data->scan_info->bssid_user); } g_main_loop_quit (loop); } @@ -2899,9 +2918,15 @@ wifi_list_finish (WifiListData *data) g_signal_handler_disconnect (data->wifi, data->last_scan_id); nm_clear_g_source (&data->timeout_id); nm_clear_g_cancellable (&data->scan_cancellable); - g_array_unref (data->out_indices); - g_object_unref (data->wifi); g_slice_free (WifiListData, data); + + if (info->nmc->should_wait == 0) { + for (i = 0; info->devices[i]; i++) + g_object_unref (info->devices[i]); + g_free (info->devices); + g_array_unref (info->out_indices); + g_free (info); + } } static void @@ -2946,49 +2971,6 @@ wifi_list_scan_timeout (gpointer user_data) } static void -wifi_list_aps (NMDeviceWifi *wifi, - NmCli *nmc, - GArray *out_indices, - const NMMetaAbstractInfo *const*tmpl, - const char *bssid_user, - gint64 rescan_cutoff) -{ - gboolean needs_rescan; - WifiListData *data; - - needs_rescan = rescan_cutoff < 0 || (rescan_cutoff > 0 && nm_device_wifi_get_last_scan (wifi) < rescan_cutoff); - - /* FIXME: nmcli should either - * - don't request any new scan for any device and print the full AP list right - * away. - * - or, when requesting a scan on one or more devices, don't print the result - * before all requests complete. - * - * Otherwise: - * - the printed output is not self consistent. E.g. it will print the result - * on one device at a certain time, while printing the result for another - * device at a later point in time. - * - the order in which we print the AP list per-device, is unstable. */ - if (needs_rescan) { - data = g_slice_new0 (WifiListData); - data->nmc = nmc; - data->wifi = g_object_ref (wifi); - data->tmpl = tmpl; - data->out_indices = g_array_ref (out_indices);; - data->bssid_user = bssid_user; - data->last_scan_id = g_signal_connect (wifi, "notify::" NM_DEVICE_WIFI_LAST_SCAN, - G_CALLBACK (wifi_last_scan_updated), data); - data->scan_cancellable = g_cancellable_new (); - data->timeout_id = g_timeout_add_seconds (15, wifi_list_scan_timeout, data); - nm_device_wifi_request_scan_async (wifi, data->scan_cancellable, wifi_list_rescan_cb, data); - - nmc->should_wait++; - } else { - wifi_print_aps (wifi, nmc, out_indices, tmpl, bssid_user); - } -} - -static void complete_aps (NMDevice **devices, const char *ifname, const char *bssid_prefix, const char *ssid_prefix) { @@ -3017,12 +2999,15 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv) const char *bssid_user = NULL; const char *rescan = NULL; gs_free NMDevice **devices = NULL; - guint i; const char *fields_str = NULL; const NMMetaAbstractInfo *const*tmpl; gs_unref_array GArray *out_indices = NULL; int option; guint64 rescan_cutoff; + NMDeviceWifi *wifi; + ScanInfo *scan_info = NULL; + WifiListData *data; + guint i, j; devices = nmc_get_devices_sorted (nmc->client); @@ -3110,7 +3095,8 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv) } if (NM_IS_DEVICE_WIFI (device)) { - wifi_list_aps (NM_DEVICE_WIFI (device), nmc, out_indices, tmpl, bssid_user, rescan_cutoff); + devices[0] = device; + devices[1] = NULL; } else { if ( nm_device_get_device_type (device) == NM_DEVICE_TYPE_GENERIC && g_strcmp0 (nm_device_get_type_description (device), "wifi") == 0) { @@ -3124,13 +3110,52 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv) } return NMC_RESULT_ERROR_UNKNOWN; } + } + + /* Filter out non-wifi devices */ + for (i = 0, j = 0; devices[i]; i++) { + if (NM_IS_DEVICE_WIFI (devices[i])) + devices[j++] = devices[i]; + } + devices[j] = NULL; + + /* Start a new scan for devices that need it */ + for (i = 0; devices[i]; i++) { + wifi = (NMDeviceWifi *) devices[i]; + g_object_ref (wifi); + + if ( rescan_cutoff == 0 + || (rescan_cutoff > 0 && nm_device_wifi_get_last_scan (wifi) >= rescan_cutoff)) + continue; + + if (!scan_info) { + scan_info = g_new0 (ScanInfo, 1); + scan_info->out_indices = g_array_ref (out_indices); + scan_info->tmpl = tmpl; + scan_info->bssid_user = bssid_user; + scan_info->nmc = nmc; + } + + nmc->should_wait++; + data = g_slice_new0 (WifiListData); + data->wifi = wifi; + data->scan_info = scan_info; + data->last_scan_id = g_signal_connect (wifi, "notify::" NM_DEVICE_WIFI_LAST_SCAN, + G_CALLBACK (wifi_last_scan_updated), data); + data->scan_cancellable = g_cancellable_new (); + data->timeout_id = g_timeout_add_seconds (15, wifi_list_scan_timeout, data); + nm_device_wifi_request_scan_async (wifi, data->scan_cancellable, wifi_list_rescan_cb, data); + } + + if (scan_info) { + scan_info->devices = g_steal_pointer (&devices); } else { + /* Print results right away if no scan is pending */ for (i = 0; devices[i]; i++) { - NMDevice *dev = devices[i]; - - if (NM_IS_DEVICE_WIFI (dev)) { - wifi_list_aps (NM_DEVICE_WIFI (dev), nmc, out_indices, tmpl, bssid_user, rescan_cutoff); - } + wifi_print_aps (NM_DEVICE_WIFI (devices[i]), + nmc, out_indices, + tmpl, bssid_user); + g_object_unref (devices[i]); } } diff --git a/clients/cli/utils.c b/clients/cli/utils.c index e21c108d..feb67221 100644 --- a/clients/cli/utils.c +++ b/clients/cli/utils.c @@ -919,6 +919,8 @@ nmc_empty_output_fields (NmcOutputData *output_data) /* Empty output_data array */ if (output_data->output_data->len > 0) g_ptr_array_remove_range (output_data->output_data, 0, output_data->output_data->len); + + g_ptr_array_unref (output_data->output_data); } /*****************************************************************************/ |