diff options
Diffstat (limited to 'clients/cli/devices.c')
| -rw-r--r-- | clients/cli/devices.c | 155 |
1 files changed, 90 insertions, 65 deletions
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]); } } |