diff --git a/ChangeLog b/ChangeLog index 7635a0e42f..7a72b9ce83 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,44 @@ +2005-03-25 Dan Williams + + * panel-applet/NMWirelessApplet.c + - (nmwa_about_cb): Add some more contributors + - (nmwa_update_state): show the applet when there's no connection + - Enable the "Stop/Resume all wireless devices" option in the + context menu + - New "no connection" icon + + * src/NetworkManager.c + - (nm_poll_and_update_wireless_link_state): don't do anything if + wireless is disabled or we're asleep + + * src/NetworkManagerDHCP.c + - Remove trailing "\n" on debug messages + + * src/NetworkManagerDbus.c + - (nm_dbus_network_status_from_data): new state "asleep" + + * src/NetworkManagerDevice.c + - Merge most of Peter Jones' "completion" patch that greatly reduces + latency and wait times for most operations + - (nm_device_wireless_scan): Don't scan when asleep + + * src/NetworkManagerPolicy.c + - (nm_policy_get_best_device): return no device when asleep + - (nm_policy_allowed_ap_list_update): From Bill Moss: merge properties + for all wireless devices on update, not just active device + + * src/NetworkManagerUtils.c + - Merge Peter Jones' "completion" patch + + * src/nm-dbus-nm.c + - (nm_dbus_nm_set_wireless_enabled): bring down wireless devices when + we're told to disable them + - (nm_dbus_nm_sleep, nm_dbus_nm_wake): new functions for sleep/wake + + * utils/nm-utils.h + - New variants of the warn/info/error/debug print functions that can take + variables rather than static strings + 2005-03-24 Dan Williams * src/NetworkManagerUtils.c diff --git a/named/nm-named-manager.c b/named/nm-named-manager.c index d39836150e..96185922cf 100644 --- a/named/nm-named-manager.c +++ b/named/nm-named-manager.c @@ -36,6 +36,7 @@ #include #include #include +#include "utils/nm-utils.h" #ifdef HAVE_SELINUX #include @@ -512,7 +513,7 @@ nm_named_manager_start (NMNamedManager *mgr, GError **error) return FALSE; } g_ptr_array_free (named_argv, TRUE); - syslog (LOG_INFO, "named started with pid %d", pid); + nm_info ("named started with pid %d", pid); mgr->priv->named_pid = pid; if (mgr->priv->child_watch) g_source_destroy (mgr->priv->child_watch); diff --git a/panel-applet/NMWirelessApplet.c b/panel-applet/NMWirelessApplet.c index 90e6804d85..86447e01cf 100644 --- a/panel-applet/NMWirelessApplet.c +++ b/panel-applet/NMWirelessApplet.c @@ -121,10 +121,16 @@ void nmwa_about_cb (NMWirelessApplet *applet) static const gchar *authors[] = { "The Red Hat Desktop Team, including:\n", - "Dan Williams ", "Jonathan Blandford ", "John Palmieri ", + "Ray Strode ", "Colin Walters ", + "Dan Williams ", + "\nAnd others, including:\n", + "Bill Moss", + "Tom Parker", + "j@bootlab.org", + "Peter Jones ", NULL }; @@ -375,7 +381,7 @@ nmwa_update_state (NMWirelessApplet *applet) switch (applet->applet_state) { case (APPLET_STATE_NO_CONNECTION): - show_applet = FALSE; + pixbuf = applet->no_connection_icon; tip = g_strdup (_("No network connection")); break; @@ -959,7 +965,7 @@ static void nmwa_set_wireless_enabled_cb (GtkWidget *widget, NMWirelessApplet *a { g_return_if_fail (applet != NULL); - nmwa_dbus_enable_scanning (applet, !applet->wireless_enabled); + nmwa_dbus_enable_wireless (applet, !applet->wireless_enabled); } @@ -1130,7 +1136,6 @@ static void nmwa_context_menu_update (NMWirelessApplet *applet) g_signal_connect (G_OBJECT (applet->stop_wireless_item), "activate", G_CALLBACK (nmwa_set_wireless_enabled_cb), applet); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (applet->stop_wireless_item), image); gtk_menu_shell_insert (GTK_MENU_SHELL (applet->context_menu), applet->stop_wireless_item, 1); - gtk_widget_set_sensitive (GTK_WIDGET (applet->stop_wireless_item), FALSE); gtk_widget_show_all (applet->stop_wireless_item); g_mutex_unlock (applet->data_mutex); @@ -1164,7 +1169,6 @@ static GtkWidget *nmwa_context_menu_create (NMWirelessApplet *applet) image = gtk_image_new_from_stock (GTK_STOCK_STOP, GTK_ICON_SIZE_MENU); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (applet->stop_wireless_item), image); gtk_menu_shell_append (GTK_MENU_SHELL (menu), applet->stop_wireless_item); - gtk_widget_set_sensitive (GTK_WIDGET (applet->stop_wireless_item), FALSE); menu_item = gtk_separator_menu_item_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); @@ -1395,6 +1399,7 @@ nmwa_icons_free (NMWirelessApplet *applet) gint i; g_object_unref (applet->no_nm_icon); + g_object_unref (applet->no_connection_icon); g_object_unref (applet->wired_icon); g_object_unref (applet->adhoc_icon); for (i = 0; i < NUM_WIRED_CONNECTING_FRAMES; i++) @@ -1417,6 +1422,7 @@ nmwa_icons_load_from_disk (NMWirelessApplet *applet, GtkIconTheme *icon_theme) gint icon_size = 22; applet->no_nm_icon = gtk_icon_theme_load_icon (icon_theme, "nm-device-broken", icon_size, 0, NULL); + applet->no_connection_icon = gtk_icon_theme_load_icon (icon_theme, "nm-no-connection", icon_size, 0, NULL); applet->wired_icon = gtk_icon_theme_load_icon (icon_theme, "nm-device-wired", icon_size, 0, NULL); applet->adhoc_icon = gtk_icon_theme_load_icon (icon_theme, "nm-adhoc", icon_size, 0, NULL); applet->wired_connecting_icons[0] = gtk_icon_theme_load_icon (icon_theme, "nm-connecting01", icon_size, 0, NULL); diff --git a/panel-applet/NMWirelessApplet.h b/panel-applet/NMWirelessApplet.h index f039bb96e4..00382c3c20 100644 --- a/panel-applet/NMWirelessApplet.h +++ b/panel-applet/NMWirelessApplet.h @@ -130,6 +130,7 @@ typedef struct char *dbus_nm_status; GdkPixbuf *no_nm_icon; + GdkPixbuf *no_connection_icon; GdkPixbuf *wired_icon; GdkPixbuf *adhoc_icon; #define NUM_WIRED_CONNECTING_FRAMES 11 diff --git a/panel-applet/icons/Makefile.am b/panel-applet/icons/Makefile.am index 160e7b1fd8..5fddd90db7 100644 --- a/panel-applet/icons/Makefile.am +++ b/panel-applet/icons/Makefile.am @@ -7,6 +7,7 @@ largeicon_DATA=\ smallicondir=${datadir}/icons/hicolor/22x22/apps smallicon_DATA= \ + nm-no-connection.png\ nm-device-wired.png \ nm-adhoc.png \ nm-connecting01.png \ diff --git a/panel-applet/icons/nm-no-connection.png b/panel-applet/icons/nm-no-connection.png new file mode 100644 index 0000000000..f9cd02c4cb Binary files /dev/null and b/panel-applet/icons/nm-no-connection.png differ diff --git a/src/NetworkManager.c b/src/NetworkManager.c index 04d79520d4..c0353a489a 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -377,6 +377,9 @@ gboolean nm_poll_and_update_wireless_link_state (NMData *data) { g_return_val_if_fail (data != NULL, TRUE); + if ((data->wireless_enabled == FALSE) || (data->asleep == TRUE)) + return (TRUE); + /* Attempt to acquire mutex for device list iteration. * If the acquire fails, just ignore the device deletion entirely. */ diff --git a/src/NetworkManagerDHCP.c b/src/NetworkManagerDHCP.c index ee36b58794..895c18a175 100644 --- a/src/NetworkManagerDHCP.c +++ b/src/NetworkManagerDHCP.c @@ -50,7 +50,7 @@ static void set_nameservers (NMDevice *dev, void *data, int len) GPOINTER_TO_UINT (elt->data), &error)) { - nm_warning ("Couldn't remove nameserver: %s\n", error->message); + nm_warning ("Couldn't remove nameserver: %s", error->message); g_clear_error (&error); } } @@ -66,7 +66,7 @@ static void set_nameservers (NMDevice *dev, void *data, int len) ((unsigned char *)data)[i+1], ((unsigned char *)data)[i+2], ((unsigned char *)data)[i+3]); - nm_warning ("Adding nameserver: %s\n", nameserver); + nm_info ("Adding nameserver: %s", nameserver); if ((id = nm_named_manager_add_nameserver_ipv4 (dev->app_data->named, nameserver, diff --git a/src/NetworkManagerDbus.c b/src/NetworkManagerDbus.c index fe92e5bea5..e3812877f6 100644 --- a/src/NetworkManagerDbus.c +++ b/src/NetworkManagerDbus.c @@ -343,6 +343,8 @@ char *nm_dbus_network_status_from_data (NMData *data) g_return_val_if_fail (data != NULL, NULL); + if (data->asleep == TRUE) + status = g_strdup ("asleep"); if (data->forcing_device) status = g_strdup ("scanning"); else if (data->active_device && nm_device_is_activating (data->active_device)) diff --git a/src/NetworkManagerDevice.c b/src/NetworkManagerDevice.c index 1eddedd1e6..89fe221101 100644 --- a/src/NetworkManagerDevice.c +++ b/src/NetworkManagerDevice.c @@ -48,6 +48,8 @@ static gboolean nm_device_activation_configure_ip (NMDevice *dev, gboolean do_on static gboolean nm_device_wireless_scan (gpointer user_data); static gboolean supports_mii_carrier_detect (NMDevice *dev); static gboolean supports_ethtool_carrier_detect (NMDevice *dev); +static gboolean nm_device_bring_up_wait (NMDevice *dev, gboolean cancelable); +static gboolean nm_device_activation_handle_cancel (NMDevice *dev); typedef struct { @@ -218,7 +220,7 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev, if (!app_data->enable_test_devices && test_dev) { nm_warning ("attempt to create a test device, but test devices were not enabled " - "on the command line. Will not create the device.\n"); + "on the command line. Will not create the device."); return (NULL); } @@ -252,8 +254,8 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev, goto err; /* Have to bring the device up before checking link status and other stuff */ - nm_device_bring_up (dev); - g_usleep (G_USEC_PER_SEC); + nm_device_bring_up_wait (dev, 0); + dev->driver_support_level = nm_get_driver_support_level (dev->app_data->hal_ctx, dev); /* Initialize wireless-specific options */ @@ -330,10 +332,12 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev, } /* Block until our device thread has actually had a chance to start. */ - nm_info ("waiting for device's worker thread to start.\n"); - while (dev->worker_started == FALSE) - g_usleep (G_USEC_PER_SEC / 2); - nm_info ("device's worker thread started, continuing.\n"); + nm_wait_for_completion (NM_COMPLETION_TRIES_INFINITY, + G_USEC_PER_SEC / 20, nm_completion_boolean_test, NULL, + &dev->worker_started, + "nm_device_new(): waiting for device's worker thread to start", + LOG_INFO, 0); + nm_info ("nm_device_new(): device's worker thread started, continuing."); return (dev); @@ -373,10 +377,8 @@ gboolean nm_device_unref (NMDevice *dev) dev->refcount--; if (dev->refcount <= 0) { - if (dev->loop) - g_main_loop_quit (dev->loop); - while (dev->worker_done == FALSE) - g_usleep (300); + nm_device_worker_thread_stop (dev); + nm_device_bring_down (dev); if (nm_device_is_wireless (dev)) { @@ -420,12 +422,10 @@ static gpointer nm_device_worker (gpointer user_data) if (!dev) { - nm_error ("received NULL device object, NetworkManager cannot continue.\n"); + nm_error ("received NULL device object, NetworkManager cannot continue."); exit (1); } - dev->worker_started = TRUE; - /* Do an initial wireless scan */ if (nm_device_is_wireless (dev)) { @@ -437,6 +437,7 @@ static gpointer nm_device_worker (gpointer user_data) g_source_unref (source); } + dev->worker_started = TRUE; g_main_loop_run (dev->loop); /* Remove any DHCP timeouts that might have been running */ @@ -460,9 +461,11 @@ void nm_device_worker_thread_stop (NMDevice *dev) { g_return_if_fail (dev != NULL); - g_main_loop_quit (dev->loop); - while (dev->worker_done == FALSE) - g_usleep (G_USEC_PER_SEC / 2); + if (dev->loop) + g_main_loop_quit (dev->loop); + nm_wait_for_completion(NM_COMPLETION_TRIES_INFINITY, 300, + nm_completion_boolean_test, NULL, &dev->worker_done, + NULL, NULL, 0); } @@ -1518,20 +1521,6 @@ static void nm_device_set_up_down (NMDevice *dev, gboolean up) * Interface state functions: bring up, down, check * */ -void nm_device_bring_up (NMDevice *dev) -{ - g_return_if_fail (dev != NULL); - - nm_device_set_up_down (dev, TRUE); -} - -void nm_device_bring_down (NMDevice *dev) -{ - g_return_if_fail (dev != NULL); - - nm_device_set_up_down (dev, FALSE); -} - gboolean nm_device_is_up (NMDevice *dev) { int sk; @@ -1558,6 +1547,94 @@ gboolean nm_device_is_up (NMDevice *dev) return (FALSE); } +/* I really wish nm_v_wait_for_completion_or_timeout could translate these + * to first class args instead of a va_list, so these helpers could be nice + * and _tiny_. + * + * ... and we can probably do that with __builtin_apply(), or libffi, + * but that's kindof cheating. */ +gboolean nm_completion_device_is_up_test(int tries, va_list args) +{ + NMDevice *dev = va_arg(args, NMDevice *); + gboolean *err = va_arg(args, gboolean *); + gboolean cancelable = va_arg(args, gboolean); + + g_return_val_if_fail(dev != NULL, TRUE); + g_return_val_if_fail(err != NULL, TRUE); + + *err = FALSE; + if (cancelable && nm_device_activation_handle_cancel(dev)) { + *err = TRUE; + return TRUE; + } + if (nm_device_is_up (dev)) + return TRUE; + return FALSE; +} + +void nm_device_bring_up (NMDevice *dev) +{ + g_return_if_fail (dev != NULL); + + nm_device_set_up_down (dev, TRUE); +} + +gboolean nm_device_bring_up_wait (NMDevice *dev, gboolean cancelable) +{ + gboolean err = FALSE; + + g_return_val_if_fail (dev != NULL, TRUE); + + nm_device_bring_up (dev); + nm_wait_for_completion(400, G_USEC_PER_SEC / 200, NULL, + nm_completion_device_is_up_test, dev, + &err, cancelable); + if (err) + syslog (LOG_INFO, "failed to bring device up"); + return err; +} + +void nm_device_bring_down (NMDevice *dev) +{ + g_return_if_fail (dev != NULL); + + nm_device_set_up_down (dev, FALSE); +} + +gboolean nm_completion_device_is_down_test(int tries, va_list args) +{ + NMDevice *dev = va_arg(args, NMDevice *); + gboolean *err = va_arg(args, gboolean *); + gboolean cancelable = va_arg(args, gboolean); + + g_return_val_if_fail(dev != NULL, TRUE); + g_return_val_if_fail(err != NULL, TRUE); + + *err = FALSE; + if (cancelable && nm_device_activation_handle_cancel(dev)) { + *err = TRUE; + return TRUE; + } + if (!nm_device_is_up (dev)) + return TRUE; + return FALSE; +} + +gboolean nm_device_bring_down_wait (NMDevice *dev, gboolean cancelable) +{ + gboolean err = FALSE; + + g_return_val_if_fail (dev != NULL, TRUE); + + nm_device_bring_down (dev); + nm_wait_for_completion(400, G_USEC_PER_SEC / 200, NULL, + nm_completion_device_is_down_test, dev, + &err, cancelable); + if (err) + syslog (LOG_INFO, "failed to bring device down"); + return err; +} + /* * nm_device_get_mode @@ -1755,6 +1832,47 @@ static gboolean nm_device_activation_handle_cancel (NMDevice *dev) } +static gboolean nm_dwwfl_test (int tries, va_list args) +{ + NMDevice *dev = va_arg (args, NMDevice *); + guint *assoc_count = va_arg (args, guint *); + double *last_freq = va_arg (args, double *); + char *essid = va_arg (args, char *); + int required = va_arg (args, int); + + double cur_freq = nm_device_get_frequency (dev); + gboolean assoc = nm_device_wireless_is_associated (dev); + const char * cur_essid = nm_device_get_essid (dev); + + /* If we've been cancelled, return that we should stop */ + if (nm_device_activation_should_cancel (dev)) + return TRUE; + + /* If we're on the same frequency and essid, and we're associated, + * increment the count for how many iterations we've been associated; + * otherwise start over. */ + /* XXX floating point comparison this way is dangerous, IIRC */ + if ((cur_freq == *last_freq) && assoc && !strcmp (essid, cur_essid)) + { + (*assoc_count)++; + } + else + { + *assoc_count = 0; + *last_freq = cur_freq; + } + + /* If we're told to cancel, return that we're finished. + * If we've the frequency has been stable for more than the required + * interval, return that we're finished. + * Otherwise, we're not finished. */ + if (nm_device_activation_should_cancel (dev) || *assoc_count >= required) + return TRUE; + + return FALSE; +} + + /* * nm_device_wireless_wait_for_link * @@ -1764,59 +1882,73 @@ static gboolean nm_device_activation_handle_cancel (NMDevice *dev) */ static gboolean nm_device_wireless_wait_for_link (NMDevice *dev, const char *essid) { - struct timeval end_time; - struct timeval cur_time; - gboolean link = FALSE; + guint assoc = 0; double last_freq = 0; guint assoc_count = 0; - gint pause_value; + struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 }; + + /* we want to sleep for a very short amount of time, to minimize + * hysteresis on the boundaries of our required time. But we + * also want the maximum to be based on what the card */ + const guint delay = 30; + const guint required_tries = 10; + const guint min_delay = 2 * (required_tries / delay); g_return_val_if_fail (dev != NULL, FALSE); g_return_val_if_fail (time > 0, FALSE); - pause_value = nm_device_get_association_pause_value (dev); - if (pause_value < 1) - return FALSE; + /* for cards which don't scan many frequencies, this will return + * 5 seconds, which we'll bump up to 6 seconds below. Oh well. */ + timeout.tv_sec = (time_t)nm_device_get_association_pause_value (dev); - gettimeofday (&end_time, NULL); - end_time.tv_sec += pause_value; + /* Refuse to to have a timeout that's _less_ than twice the total time + * required before calling a link valid */ + if (timeout.tv_sec < min_delay) + timeout.tv_sec = min_delay; - /* We more or less keep asking the driver for the frequency the card is on, and - * when the frequency has stabilized (the driver has to scan channels to find the AP, - * and when it finds the AP it stops scanning) and the MAC is valid, we think we - * have a link. - */ - gettimeofday (&cur_time, NULL); - while (cur_time.tv_sec < end_time.tv_sec) - { - double cur_freq = nm_device_get_frequency (dev); - gboolean assoc = nm_device_wireless_is_associated (dev); - char *cur_essid = nm_device_get_essid (dev); - - if ((cur_freq == last_freq) && assoc && !strcmp (essid, cur_essid)) - assoc_count++; - else - assoc_count = 0; - last_freq = cur_freq; - - g_usleep (G_USEC_PER_SEC / 2); - if (nm_device_activation_should_cancel (dev)) - break; - - gettimeofday (&cur_time, NULL); - if ((cur_time.tv_sec >= end_time.tv_sec) && (cur_time.tv_usec >= end_time.tv_usec)) - break; - - /* Assume that if we've been associated this long, we might as well just stop. */ - if (assoc_count >= 9) - break; - } + /* We more or less keep asking the driver for the frequency the + * card is listening on until it connects to an AP. Once it's + * associated, the driver stops scanning. To detect that, we look + * for the essid and frequency to remain constant for 3 seconds. + * When it remains constant, we assume it's a real link. */ + nm_wait_for_timeout (&timeout, G_USEC_PER_SEC / delay, + nm_dwwfl_test, nm_dwwfl_test, dev, &assoc, + &last_freq, essid, required_tries * 2); /* If we've had a reasonable association count, we say we have a link */ - if (assoc_count > 6) - link = TRUE; + if (assoc > required_tries) + return TRUE; + return FALSE; +} - return (link); + +static gboolean nm_device_link_test(int tries, va_list args) +{ + NMDevice *dev = va_arg(args, NMDevice *); + gboolean *err = va_arg(args, gboolean *); + + g_return_val_if_fail(dev != NULL, TRUE); + g_return_val_if_fail(err != NULL, TRUE); + + if (nm_device_wireless_is_associated (dev) && nm_device_get_essid (dev)) + { + *err = FALSE; + return TRUE; + } + *err = TRUE; + return FALSE; +} + +static gboolean nm_device_is_up_and_associated_wait (NMDevice *dev, int timeout, int interval) +{ + gboolean err; + const gint delay = (G_USEC_PER_SEC * nm_device_get_association_pause_value (dev)) / interval; + const gint max_cycles = timeout * interval; + + g_return_val_if_fail (dev != NULL, TRUE); + + nm_wait_for_completion (max_cycles, delay, NULL, nm_device_link_test, dev, &err); + return !err; } @@ -1841,10 +1973,9 @@ static gboolean nm_device_set_wireless_config (NMDevice *dev, NMAccessPoint *ap) g_return_val_if_fail (nm_ap_get_auth_method (ap) != NM_DEVICE_AUTH_METHOD_UNKNOWN, FALSE); /* Force the card into Managed/Infrastructure mode */ - nm_device_bring_down (dev); - g_usleep (G_USEC_PER_SEC * 2); - nm_device_bring_up (dev); - g_usleep (G_USEC_PER_SEC * 2); + nm_device_bring_down_wait (dev, 0); + nm_device_bring_up_wait (dev, 0); + nm_device_set_mode (dev, NETWORK_MODE_INFRA); essid = nm_ap_get_essid (ap); @@ -1882,8 +2013,11 @@ static gboolean nm_device_set_wireless_config (NMDevice *dev, NMAccessPoint *ap) ((auth == NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM) ? "Open System" : ((auth == NM_DEVICE_AUTH_METHOD_SHARED_KEY) ? "Shared Key" : "unknown"))); - /* Bring the device up and pause to allow card to associate. */ - g_usleep (G_USEC_PER_SEC * nm_device_get_association_pause_value (dev)); + /* Bring the device up and pause to allow card to associate. After we set the ESSID + * on the card, the card has to scan all channels to find our requested AP (which can + * take a long time if it is an A/B/G chipset like the Atheros 5212, for example). + */ + nm_device_is_up_and_associated_wait (dev, 2, 100); /* Some cards don't really work well in ad-hoc mode unless you explicitly set the bitrate * on them. (Netgear WG511T/Atheros 5212 with madwifi drivers). Until we can get rate information @@ -1981,7 +2115,7 @@ static gboolean nm_device_activate_wireless_adhoc (NMDevice *dev, NMAccessPoint { nm_ap_set_freq (ap, freq_to_use); - nm_info ("Will create network '%s' with frequency %f.\n", nm_ap_get_essid (ap), nm_ap_get_freq (ap)); + nm_info ("Will create network '%s' with frequency %f.", nm_ap_get_essid (ap), nm_ap_get_freq (ap)); if ((success = nm_device_set_wireless_config (dev, ap))) success = nm_device_activation_configure_ip (dev, TRUE); } @@ -2079,6 +2213,41 @@ void invalidate_ap (NMDevice *dev, NMAccessPoint *ap) } +/* this gets called without the scan mutex held */ +static gboolean nm_wa_test (int tries, va_list args) +{ + NMDevice *dev = va_arg(args, NMDevice *); + NMAccessPoint **best_ap = va_arg(args, NMAccessPoint **); + gboolean *err = va_arg(args, gboolean *); + + g_return_val_if_fail(dev != NULL, TRUE); + g_return_val_if_fail(best_ap != NULL, TRUE); + g_return_val_if_fail(err != NULL, TRUE); + + *err = TRUE; + if (nm_device_activation_handle_cancel(dev)) + return TRUE; + + if (tries % 100 == 0) + nm_info ("Activation (%s/wireless): waiting for access point. (attempt %d)", nm_device_get_iface(dev), tries); + + *best_ap = nm_device_get_best_ap(dev); + if (*best_ap) { + /* Set ESSID early so that when we send out the + * DeviceStatusChanged signal below, we are able to + * respond correctly to queries for "getActiveNetwork" + * against our device. nm_device_get_path_for_ap() uses + * the /card's/ AP, not the best_ap. */ + nm_device_set_essid (dev, nm_ap_get_essid (*best_ap)); + nm_device_set_now_scanning (dev, FALSE); + *err = FALSE; + return TRUE; + } + + return FALSE; +} + + /* * nm_device_activate_wireless * @@ -2089,12 +2258,13 @@ void invalidate_ap (NMDevice *dev, NMAccessPoint *ap) */ static gboolean nm_device_activate_wireless (NMDevice *dev) { - NMAccessPoint *best_ap; + NMAccessPoint *best_ap = NULL; gboolean success = FALSE; guint8 attempt = 1; char last_essid [50] = "\0"; gboolean need_key = FALSE; gboolean found_ap = FALSE; + gboolean err = FALSE; g_return_val_if_fail (dev != NULL, FALSE); g_return_val_if_fail (dev->app_data != NULL, FALSE); @@ -2104,9 +2274,7 @@ static gboolean nm_device_activate_wireless (NMDevice *dev) */ nm_lock_mutex (dev->options.wireless.scan_mutex, __FUNCTION__); - if (!nm_device_is_up (dev)) - nm_device_bring_up (dev); - g_usleep (G_USEC_PER_SEC); + nm_device_bring_up_wait (dev, 1); get_ap: /* If we were told to quit activation, stop the thread and return */ @@ -2117,24 +2285,19 @@ get_ap: * lock here because this might take a while. */ nm_unlock_mutex (dev->options.wireless.scan_mutex, __FUNCTION__); - while (!(best_ap = nm_device_get_best_ap (dev))) - { - nm_device_set_now_scanning (dev, TRUE); - if (!found_ap) - nm_warning ("Activation (%s/wireless): waiting for an access point.", nm_device_get_iface (dev)); - g_usleep (G_USEC_PER_SEC * 2); - /* If we were told to quit activation, stop the thread and return */ - if (nm_device_activation_handle_cancel (dev)) - { - /* Wierd as it may seem, we lock here to balance the unlock in "out:" */ - nm_lock_mutex (dev->options.wireless.scan_mutex, __FUNCTION__); - goto out; - } - found_ap = TRUE; + /* Get a valid "best" access point we should connect to. */ + nm_device_set_now_scanning (dev, TRUE); + + /* at most wait 10 seconds, but check every 50th to see if we're done */ + nm_wait_for_completion(NM_COMPLETION_TRIES_INFINITY, G_USEC_PER_SEC / 50, nm_wa_test, NULL, dev, &best_ap, &err); + if (err) + { + /* Wierd as it may seem, we lock here to balance the unlock in "out:" */ + nm_lock_mutex (dev->options.wireless.scan_mutex, __FUNCTION__); + goto out; } - if (found_ap) - nm_warning ("Activation (%s/wireless): found access point '%s' to use.", nm_device_get_iface (dev), nm_ap_get_essid (best_ap)); + nm_info ("Activation (%s/wireless): found access point '%s' to use.", nm_device_get_iface (dev), nm_ap_get_essid (best_ap)); /* Set ESSID early so that when we send out the DeviceStatusChanged signal below, * we are able to respond correctly to queries for "getActiveNetwork" against @@ -2164,6 +2327,8 @@ get_ap: need_key = AP_NEED_KEY (dev, best_ap); need_key: + if (nm_device_activation_handle_cancel (dev)) + goto out; if (need_key) { char *essid = nm_ap_get_essid (best_ap); @@ -2259,8 +2424,15 @@ try_connect: * and also for Open System mode (where you cannot know WEP key is wrong ever), we try to * do DHCP and if that fails, fall back to next auth mode and try again. */ + success = FALSE; if ((success = nm_device_activation_configure_ip (dev, adhoc))) { + if (nm_device_activation_handle_cancel (dev)) + { + success = FALSE; + goto out; + } + /* Cache the last known good auth method in both NetworkManagerInfo and our allowed AP list */ nm_dbus_update_network_auth_method (dev->app_data->dbus_connection, nm_ap_get_essid (best_ap), nm_ap_get_auth_method (best_ap)); if ((tmp_ap = nm_ap_list_get_ap_by_essid (dev->app_data->allowed_ap_list, nm_ap_get_essid (best_ap)))) @@ -2268,7 +2440,6 @@ try_connect: } else { - /* If we were told to quit activation, stop the thread and return */ if (nm_device_activation_handle_cancel (dev)) goto out; @@ -2300,11 +2471,14 @@ try_connect: connect_done: /* If we were told to quit activation, stop the thread and return */ if (nm_device_activation_handle_cancel (dev)) + { + success = FALSE; goto out; + } if (success) { - nm_debug ("Activation (%s/wireless): Success! Connected to access point '%s' and got an IP address.", + nm_info ("Activation (%s/wireless): Success! Connected to access point '%s' and got an IP address.", nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)"); nm_ap_unref (best_ap); } @@ -2388,7 +2562,7 @@ static gboolean nm_device_activate (gpointer user_data) g_return_val_if_fail (dev != NULL, FALSE); g_return_val_if_fail (dev->app_data != NULL, FALSE); - nm_warning ("Activation (%s) started...", nm_device_get_iface (dev)); + nm_info ("Activation (%s) started...", nm_device_get_iface (dev)); /* Bring the device up */ if (!nm_device_is_up (dev)); @@ -2404,9 +2578,9 @@ static gboolean nm_device_activate (gpointer user_data) if (nm_ap_get_user_created (best_ap)) { create_network = TRUE; - nm_info ("Creating wireless network '%s'.\n", nm_ap_get_essid (best_ap)); + nm_info ("Creating wireless network '%s'.", nm_ap_get_essid (best_ap)); success = nm_device_activate_wireless_adhoc (dev, best_ap); - nm_info ("Wireless network creation for '%s' was %s.\n", nm_ap_get_essid (best_ap), success ? "successful" : "unsuccessful"); + nm_info ("Wireless network creation for '%s' was %s.", nm_ap_get_essid (best_ap), success ? "successful" : "unsuccessful"); } nm_ap_unref (best_ap); } @@ -2422,15 +2596,15 @@ static gboolean nm_device_activate (gpointer user_data) goto out; if (success) - nm_info ("Activation (%s) IP configuration/DHCP successful!\n", nm_device_get_iface (dev)); + nm_info ("Activation (%s) IP configuration/DHCP successful!", nm_device_get_iface (dev)); else - nm_info ("Activation (%s) IP configuration/DHCP unsuccessful! Ending activation...\n", + nm_info ("Activation (%s) IP configuration/DHCP unsuccessful! Ending activation...", nm_device_get_iface (dev)); finished = TRUE; out: - nm_debug ("Activation (%s) ended.\n", nm_device_get_iface (dev)); + nm_info ("Activation (%s) ended.", nm_device_get_iface (dev)); dev->activating = FALSE; dev->quit_activation = FALSE; if (finished) @@ -2468,6 +2642,35 @@ gboolean nm_device_activation_should_cancel (NMDevice *dev) } +static gboolean nm_ac_test (int tries, va_list args) +{ + NMDevice *dev = va_arg (args, NMDevice *); + + g_return_val_if_fail (dev != NULL, TRUE); + + if (tries == 0 && nm_device_get_dhcp_iface (dev)) + nm_device_dhcp_cease (dev); + + if (nm_device_is_activating(dev)) + { + /* Nice race here between quit activation and dhcp. We may + * not have started DHCP when we're told to quit activation, + * so we need to keep signalling dhcp to quit, which it will + * pick up whenever it starts. + * + * This should really be taken care of a better way. + */ + if (nm_device_get_dhcp_iface (dev)) + nm_device_dhcp_cease (dev); + if (tries % 20 == 0) + nm_debug ("Activation (%s/wireless): waiting on dhcp to cease or device to finish activation", nm_device_get_iface(dev)); + return FALSE; + } + + return TRUE; +} + + /* * nm_device_activation_cancel * @@ -2480,26 +2683,16 @@ void nm_device_activation_cancel (NMDevice *dev) if (nm_device_is_activating (dev)) { - nm_debug ("nm_device_activation_cancel(%s): cancelling...", nm_device_get_iface (dev)); + nm_debug ("Activation (%s/wireless): cancelling...", nm_device_get_iface (dev)); dev->quit_activation = TRUE; /* Spin until cancelled. Possible race conditions or deadlocks here. * The other problem with waiting here is that we hold up dbus traffic * that we should respond to. */ - while (nm_device_is_activating (dev)) - { - /* Nice race here between quit activation and dhcp. We may not have - * started DHCP when we're told to quit activation, so we need to keep - * signalling dhcp to quit, which it will pick up whenever it starts. - * This should really be taken care of a better way. - */ - if (dev->dhcp_iface) - nm_device_dhcp_cease (dev); - - g_usleep (G_USEC_PER_SEC / 2); - } - nm_debug ("nm_device_activation_cancel(%s): cancelled.", nm_device_get_iface (dev)); + nm_wait_for_completion(NM_COMPLETION_TRIES_INFINITY, + G_USEC_PER_SEC / 20, nm_ac_test, NULL, dev); + nm_debug ("Activation (%s/wireless): cancelled.", nm_device_get_iface(dev)); } } @@ -3128,7 +3321,7 @@ static void nm_device_do_pseudo_scan (NMDevice *dev) nm_device_set_essid (dev, nm_ap_get_essid (ap)); /* Wait a bit for association */ - g_usleep (G_USEC_PER_SEC * nm_device_get_association_pause_value (dev)); + nm_device_is_up_and_associated_wait (dev, 2, 100); /* Do we have a valid MAC address? */ nm_device_get_ap_address (dev, &cur_ap_addr); @@ -3436,6 +3629,44 @@ static gboolean nm_device_wireless_process_scan_results (gpointer user_data) } +static gboolean nm_completion_scan_has_results (int tries, va_list args) +{ + NMDevice *dev = va_arg (args, NMDevice *); + gboolean *err = va_arg (args, gboolean *); + int sk = va_arg (args, int); + NMWirelessScanResults *scan_results = va_arg (args, NMWirelessScanResults *); + int rc; + + g_return_val_if_fail (dev != NULL, TRUE); + g_return_val_if_fail (err != NULL, TRUE); + g_return_val_if_fail (scan_results != NULL, TRUE); + + rc = iw_scan(sk, (char *)nm_device_get_iface (dev), WIRELESS_EXT, &(scan_results->scan_head)); + if (rc == -1 && errno == ETIME) + { + nm_error ("Warning: the wireless card (%s) requires too much time for scans. Its driver needs to be fixed.", nm_device_get_iface (dev)); + scan_results->scan_head.result = NULL; + *err = TRUE; + return TRUE; + } + *err = FALSE; + if ((rc == -1 && errno == ENODATA) || (rc == 0 && scan_results->scan_head.result == NULL)) + { + /* Card hasn't had time yet to compile full access point list. + * Give it some more time and scan again. If that doesn't + * work, we eventually give up. */ + scan_results->scan_head.result = NULL; + return FALSE; + } + else if (rc == -1) + { + scan_results->scan_head.result = NULL; + return TRUE; + } + return TRUE; +} + + /* * nm_device_wireless_scan * @@ -3457,7 +3688,8 @@ static gboolean nm_device_wireless_scan (gpointer user_data) /* Just reschedule ourselves if scanning or all wireless is disabled */ if ( (dev->app_data->scanning_enabled == FALSE) - || (dev->app_data->wireless_enabled == FALSE)) + || (dev->app_data->wireless_enabled == FALSE) + || (dev->app_data->asleep == TRUE)) { dev->options.wireless.scan_interval = 10; goto reschedule; @@ -3466,17 +3698,24 @@ static gboolean nm_device_wireless_scan (gpointer user_data) /* Grab the scan mutex */ if (nm_try_acquire_mutex (dev->options.wireless.scan_mutex, __FUNCTION__)) { + gboolean devup_err; + /* Device must be up before we can scan */ - if (!nm_device_is_up (dev)) - nm_device_bring_up (dev); - g_usleep (G_USEC_PER_SEC); + devup_err = nm_device_bring_up_wait(dev, 1); + if (devup_err) + { + nm_unlock_mutex (dev->options.wireless.scan_mutex, __FUNCTION__); + nm_device_wireless_schedule_scan (dev); + return FALSE; + } if ((sk = iw_sockets_open ()) >= 0) { - int err; - NMNetworkMode orig_mode = NETWORK_MODE_INFRA; - double orig_freq = 0; - int orig_rate = 0; + int err; + NMNetworkMode orig_mode = NETWORK_MODE_INFRA; + double orig_freq = 0; + int orig_rate = 0; + const int max_wait = G_USEC_PER_SEC * nm_device_get_association_pause_value (dev) /2; orig_mode = nm_device_get_mode (dev); if (orig_mode == NETWORK_MODE_ADHOC) @@ -3492,6 +3731,11 @@ static gboolean nm_device_wireless_scan (gpointer user_data) nm_device_set_frequency (dev, 0); scan_results = g_malloc0 (sizeof (NMWirelessScanResults)); + nm_wait_for_completion(max_wait, max_wait/20, + nm_completion_scan_has_results, NULL, + dev, &err, sk, scan_results); + + err = iw_scan (sk, (char *)nm_device_get_iface (dev), WIRELESS_EXT, &(scan_results->scan_head)); if ((err == -1) && (errno == ENODATA)) { diff --git a/src/NetworkManagerMain.h b/src/NetworkManagerMain.h index fcd756a429..ff3b150845 100644 --- a/src/NetworkManagerMain.h +++ b/src/NetworkManagerMain.h @@ -69,6 +69,7 @@ typedef struct NMData gboolean scanning_enabled; gboolean wireless_enabled; + gboolean asleep; struct NMAccessPointList *allowed_ap_list; struct NMAccessPointList *invalid_ap_list; diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c index e2f421060a..7a59d754df 100644 --- a/src/NetworkManagerPolicy.c +++ b/src/NetworkManagerPolicy.c @@ -166,6 +166,12 @@ static NMDevice * nm_policy_get_best_device (NMDevice *switch_to_dev, NMData *da if (should_lock_on_activate) *should_lock_on_activate = FALSE; + if (data->asleep == TRUE) + { + data->active_device_locked = FALSE; + return NULL; + } + /* Prefer a device forced on us by the user */ if (switch_to_dev && !nm_device_get_removed (switch_to_dev)) { @@ -469,7 +475,8 @@ void nm_policy_schedule_device_switch (NMDevice *switch_to_dev, NMData *app_data */ static gboolean nm_policy_allowed_ap_list_update (gpointer user_data) { - NMData *data = (NMData *)user_data; + NMData *data = (NMData *)user_data; + GSList *elt; g_return_val_if_fail (data != NULL, FALSE); @@ -482,6 +489,20 @@ static gboolean nm_policy_allowed_ap_list_update (gpointer user_data) if (data->allowed_ap_list) nm_ap_list_populate_from_nmi (data->allowed_ap_list, data); + for (elt = data->dev_list; elt != NULL; elt = g_slist_next (elt)) + { + NMDevice *dev = (NMDevice *)(elt->data); + if (nm_device_is_wireless (dev)) + { + /* Once we have the list, copy in any relevant information from our Allowed list and fill + * in the ESSID of base stations that aren't broadcasting their ESSID, if we have their + * MAC address in our allowed list. + */ + nm_ap_list_copy_essids_by_address (nm_device_ap_list_get (dev), data->allowed_ap_list); + nm_ap_list_copy_properties (nm_device_ap_list_get (dev), data->allowed_ap_list); + } + } + /* If the active device doesn't have a best_ap already, make it update to * get the new data. */ @@ -491,13 +512,6 @@ static gboolean nm_policy_allowed_ap_list_update (gpointer user_data) { NMAccessPoint *best_ap; - /* Once we have the list, copy in any relevant information from our Allowed list and fill - * in the ESSID of base stations that aren't broadcasting their ESSID, if we have their - * MAC address in our allowed list. - */ - nm_ap_list_copy_essids_by_address (nm_device_ap_list_get (data->active_device), data->allowed_ap_list); - nm_ap_list_copy_properties (nm_device_ap_list_get (data->active_device), data->allowed_ap_list); - best_ap = nm_device_get_best_ap (data->active_device); if (!best_ap) nm_device_update_best_ap (data->active_device); diff --git a/src/NetworkManagerSystem.c b/src/NetworkManagerSystem.c index 489cfe5401..9ddcfb43cc 100644 --- a/src/NetworkManagerSystem.c +++ b/src/NetworkManagerSystem.c @@ -81,7 +81,7 @@ gboolean nm_system_device_set_ip4_address (NMDevice *dev, int ip4_address) else { success = TRUE; - nm_info ("Your IP address = %u.%u.%u.%u\n", + nm_info ("Your IP address = %u.%u.%u.%u", ((unsigned char *)&ip4_address)[0], ((unsigned char *)&ip4_address)[1], ((unsigned char *)&ip4_address)[2], ((unsigned char *)&ip4_address)[3]); } diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 537443a0fc..a4bad39a39 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -25,6 +25,9 @@ #include #include #include +#include +#include +#include #include "NetworkManager.h" #include "NetworkManagerUtils.h" @@ -426,3 +429,223 @@ NMDriverSupportLevel nm_get_driver_support_level (LibHalContext *ctx, NMDevice * g_free (driver); return (level); } + +static inline int nm_timeval_cmp(const struct timeval *a, + const struct timeval *b) +{ + int x; + x = a->tv_sec - b->tv_sec; + x *= G_USEC_PER_SEC; + if (x) + return x; + x = a->tv_usec - b->tv_usec; + if (x) + return x; + return 0; +} + +static inline int nm_timeval_has_passed(const struct timeval *a) +{ + struct timeval current; + + gettimeofday(¤t, NULL); + + return (nm_timeval_cmp(¤t, a) >= 0); +} + +static inline void nm_timeval_add(struct timeval *a, + const struct timeval *b) +{ + struct timeval b1; + + memmove(&b1, b, sizeof b1); + + /* normalize a and b to be positive for everything */ + while (a->tv_usec < 0) + { + a->tv_sec--; + a->tv_usec += G_USEC_PER_SEC; + } + while (b1.tv_usec < 0) + { + b1.tv_sec--; + b1.tv_usec += G_USEC_PER_SEC; + } + + /* now add secs and usecs */ + a->tv_sec += b1.tv_sec; + a->tv_usec += b1.tv_usec; + + /* and handle our overflow */ + if (a->tv_usec > G_USEC_PER_SEC) + { + a->tv_sec++; + a->tv_usec -= G_USEC_PER_SEC; + } +} + +static void nm_v_wait_for_completion_or_timeout( + const int max_tries, + const struct timeval *max_time, + const guint interval_usecs, + nm_completion_func test_func, + nm_completion_func action_func, + va_list args) +{ + int try; + gboolean finished = FALSE; + struct timeval finish_time; + + g_return_if_fail (test_func || action_func); + + if (max_time) { + gettimeofday(&finish_time, NULL); + nm_timeval_add(&finish_time, max_time); + } + + try = -1; + while (!finished && + (max_tries == NM_COMPLETION_TRIES_INFINITY || try < max_tries)) + { + if (max_time && nm_timeval_has_passed(&finish_time)) + break; + try++; + if (test_func) + { + finished = (*test_func)(try, args); + if (finished) + break; + } + +#if 0 +#define NM_SLEEP_DEBUG +#endif +#ifdef NM_SLEEP_DEBUG + syslog (LOG_INFO, "sleeping or %d usecs", interval_usecs); +#endif + g_usleep(interval_usecs); + if (action_func) + finished = (*action_func)(try, args); + } +} + +void nm_wait_for_completion_or_timeout( + const int max_tries, + const struct timeval *max_time, + const guint interval_usecs, + nm_completion_func test_func, + nm_completion_func action_func, + ...) +{ + va_list ap; + va_start(ap, action_func); + + nm_v_wait_for_completion_or_timeout(max_tries, max_time, + interval_usecs, test_func, + action_func, ap); + va_end(ap); +} + +void nm_wait_for_completion( + const int max_tries, + const guint interval_usecs, + nm_completion_func test_func, + nm_completion_func action_func, + ...) +{ + va_list ap; + va_start(ap, action_func); + + nm_v_wait_for_completion_or_timeout(max_tries, NULL, + interval_usecs, test_func, + action_func, ap); + va_end(ap); +} + +void nm_wait_for_timeout( + const struct timeval *max_time, + const guint interval_usecs, + nm_completion_func test_func, + nm_completion_func action_func, + ...) +{ + va_list ap; + va_start(ap, action_func); + + nm_v_wait_for_completion_or_timeout(-1, max_time, + interval_usecs, test_func, + action_func, ap); + va_end(ap); +} + +/* you can use these, but they're really just examples */ +gboolean nm_completion_boolean_test(int tries, va_list args) +{ + gboolean *condition = va_arg(args, gboolean *); + char *message = va_arg(args, char *); + int log_level = va_arg(args, int); + int log_interval = va_arg(args, int); + + g_return_val_if_fail (condition != NULL, TRUE); + + if (message) + if ((log_interval == 0 && tries == 0) || (log_interval != 0 && tries % log_interval == 0)) + { + if (log_level == LOG_WARNING) + nm_warning_str (message); + else if (log_level == LOG_ERR) + nm_error_str (message); + else if (log_level == LOG_DEBUG) + nm_debug_str (message); + else + nm_info_str (message); + } + + if (*condition) + return TRUE; + return FALSE; +} + +gboolean nm_completion_boolean_function1_test(int tries, va_list args) +{ + nm_completion_boolean_function_1 condition = + va_arg(args, nm_completion_boolean_function_1); + char *message = va_arg(args, char *); + int log_level = va_arg(args, int); + int log_interval = va_arg(args, int); + u_int64_t arg0 = va_arg(args, unsigned long long); + + g_return_val_if_fail (condition, TRUE); + + if (message) + if ((log_interval == 0 && tries == 0) + || (log_interval != 0 && tries % log_interval == 0)) + syslog(log_level, message); + + if (!(*condition)(arg0)) + return TRUE; + return FALSE; +} + +gboolean nm_completion_boolean_function2_test(int tries, va_list args) +{ + nm_completion_boolean_function_2 condition = + va_arg(args, nm_completion_boolean_function_2); + char *message = va_arg(args, char *); + int log_level = va_arg(args, int); + int log_interval = va_arg(args, int); + u_int64_t arg0 = va_arg(args, unsigned long long); + u_int64_t arg1 = va_arg(args, unsigned long long); + + g_return_val_if_fail (condition, TRUE); + + if (message) + if ((log_interval == 0 && tries == 0) + || (log_interval != 0 && tries % log_interval == 0)) + syslog(log_level, message); + + if (!(*condition)(arg0, arg1)) + return TRUE; + return FALSE; +} + diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h index b46c89c318..7a9d1c1cc1 100644 --- a/src/NetworkManagerUtils.h +++ b/src/NetworkManagerUtils.h @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include "NetworkManager.h" #include "NetworkManagerMain.h" @@ -48,4 +50,38 @@ int nm_spawn_process (char *args); NMDriverSupportLevel nm_get_driver_support_level (LibHalContext *ctx, NMDevice *dev); +#define NM_COMPLETION_TRIES_INFINITY -1 + +typedef gboolean (*nm_completion_func)(int tries, va_list args); +typedef gboolean (*nm_completion_boolean_function_1)(u_int64_t arg); +typedef gboolean (*nm_completion_boolean_function_2)( + u_int64_t arg0, u_int64_t arg1); + +void nm_wait_for_completion( + const int max_tries, + const guint interval_usecs, + nm_completion_func test_func, + nm_completion_func action_func, + ...); + +void nm_wait_for_completion_or_timeout( + const int max_tries, + const struct timeval *max_time, + const guint interval_usecs, + nm_completion_func test_func, + nm_completion_func action_func, + ...); + +void nm_wait_for_timeout( + const struct timeval *max_time, + const guint interval_usecs, + nm_completion_func test_func, + nm_completion_func action_func, + ...); + +gboolean nm_completion_boolean_test(int tries, va_list args); +gboolean nm_completion_boolean_function1_test(int tries, va_list args); +gboolean nm_completion_boolean_function2_test(int tries, va_list args); +#define nm_completion_boolean_function_test nm_completion_boolean_function1_test + #endif diff --git a/src/backends/NetworkManagerRedHat.c b/src/backends/NetworkManagerRedHat.c index dcd3a9f764..847db5d748 100644 --- a/src/backends/NetworkManagerRedHat.c +++ b/src/backends/NetworkManagerRedHat.c @@ -333,7 +333,7 @@ void nm_system_restart_mdns_responder (void) fclose (fp); if (res == 1) { - nm_info ("Restarting mDNSResponder.\n"); + nm_info ("Restarting mDNSResponder."); kill (pid, SIGUSR1); } } diff --git a/src/nm-dbus-nm.c b/src/nm-dbus-nm.c index fb8dd7f3f7..6ba447f966 100644 --- a/src/nm-dbus-nm.c +++ b/src/nm-dbus-nm.c @@ -460,8 +460,25 @@ static DBusMessage *nm_dbus_nm_set_wireless_enabled (DBusConnection *connection, dbus_error_init (&err); if (dbus_message_get_args (message, &err, DBUS_TYPE_BOOLEAN, &enabled, DBUS_TYPE_INVALID)) { - data->data->wireless_enabled = enabled; - nm_policy_schedule_state_update (data->data); + GSList *elt; + NMData *app_data; + + app_data = data->data; + app_data->wireless_enabled = enabled; + + /* Physically down all wireless devices */ + nm_lock_mutex (app_data->dev_list_mutex, __FUNCTION__); + for (elt = app_data->dev_list; elt; elt = g_slist_next (elt)) + { + NMDevice *dev = (NMDevice *)(elt->data); + if (nm_device_is_wireless (dev)) + { + nm_device_deactivate (dev, FALSE); + nm_device_bring_down (dev); + } + } + nm_unlock_mutex (app_data->dev_list_mutex, __FUNCTION__); + nm_policy_schedule_state_update (app_data); } return NULL; @@ -479,6 +496,51 @@ static DBusMessage *nm_dbus_nm_get_wireless_enabled (DBusConnection *connection, return reply; } +static DBusMessage *nm_dbus_nm_sleep (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +{ + GSList *elt; + NMData *app_data; + + g_return_val_if_fail (data && data->data && connection && message, NULL); + + app_data = data->data; + if (app_data->asleep == FALSE) + { + app_data->asleep = TRUE; + + /* Physically down all devices */ + nm_lock_mutex (app_data->dev_list_mutex, __FUNCTION__); + for (elt = app_data->dev_list; elt; elt = g_slist_next (elt)) + { + NMDevice *dev = (NMDevice *)(elt->data); + + nm_device_deactivate (dev, FALSE); + nm_device_bring_down (dev); + } + nm_unlock_mutex (app_data->dev_list_mutex, __FUNCTION__); + nm_policy_schedule_state_update (app_data); + } + + return NULL; +} + +static DBusMessage *nm_dbus_nm_wake (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +{ + GSList *elt; + NMData *app_data; + + g_return_val_if_fail (data && data->data && connection && message, NULL); + + app_data = data->data; + if (app_data->asleep == TRUE) + { + app_data->asleep = FALSE; + nm_policy_schedule_state_update (app_data); + } + + return NULL; +} + static DBusMessage *nm_dbus_nm_get_status (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) { DBusMessage *reply = NULL; @@ -514,6 +576,8 @@ NMDbusMethodList *nm_dbus_nm_methods_setup (void) nm_dbus_method_list_add_method (list, "getScanningEnabled", nm_dbus_nm_get_scanning_enabled); nm_dbus_method_list_add_method (list, "setWirelessEnabled", nm_dbus_nm_set_wireless_enabled); nm_dbus_method_list_add_method (list, "getWirelessEnabled", nm_dbus_nm_get_wireless_enabled); + nm_dbus_method_list_add_method (list, "sleep", nm_dbus_nm_sleep); + nm_dbus_method_list_add_method (list, "wake", nm_dbus_nm_wake); nm_dbus_method_list_add_method (list, "status", nm_dbus_nm_get_status); nm_dbus_method_list_add_method (list, "createTestDevice", nm_dbus_nm_create_test_device); nm_dbus_method_list_add_method (list, "removeTestDevice", nm_dbus_nm_remove_test_device); diff --git a/utils/.cvsignore b/utils/.cvsignore new file mode 100644 index 0000000000..3dda72986f --- /dev/null +++ b/utils/.cvsignore @@ -0,0 +1,2 @@ +Makefile.in +Makefile diff --git a/utils/nm-utils.h b/utils/nm-utils.h index a3cefc76d1..5c548ac186 100644 --- a/utils/nm-utils.h +++ b/utils/nm-utils.h @@ -65,6 +65,12 @@ G_STMT_START \ g_message ("\t" fmt "\n", ##args); \ } G_STMT_END +#define nm_info_str(fmt_str, args...) \ +G_STMT_START \ +{ \ + g_message ("\t%s\n", fmt_str, ##args); \ +} G_STMT_END + #define nm_debug(fmt, args...) \ G_STMT_START \ { \ @@ -74,6 +80,15 @@ G_STMT_START \ G_GNUC_PRETTY_FUNCTION, ##args); \ } G_STMT_END +#define nm_debug_str(fmt_str, args...) \ +G_STMT_START \ +{ \ + gdouble _timestamp; \ + nm_get_timestamp (&_timestamp); \ + g_debug ("\t[%f] %s (): %s\n", _timestamp, \ + G_GNUC_PRETTY_FUNCTION, fmt_str, ##args); \ +} G_STMT_END + #define nm_warning(fmt, args...) \ G_STMT_START \ { \ @@ -81,6 +96,13 @@ G_STMT_START \ G_GNUC_PRETTY_FUNCTION, ##args); \ } G_STMT_END +#define nm_warning_str(fmt_str, args...) \ +G_STMT_START \ +{ \ + g_warning ("\t %s (): %s\n", \ + G_GNUC_PRETTY_FUNCTION, fmt_str, ##args); \ +} G_STMT_END + #define nm_error(fmt, args...) \ G_STMT_START \ { \ @@ -92,6 +114,16 @@ G_STMT_START \ G_BREAKPOINT (); \ } G_STMT_END +#define nm_error_str(fmt_str, args...) \ +G_STMT_START \ +{ \ + gdouble _timestamp; \ + nm_get_timestamp (&_timestamp); \ + g_critical ("\t[%f] %s (): %s\n", _timestamp, \ + G_GNUC_PRETTY_FUNCTION, fmt_str, ##args); \ + nm_print_backtrace (); \ + G_BREAKPOINT (); \ +} G_STMT_END gchar *nm_dbus_escape_object_path (const gchar *utf8_string); gchar *nm_dbus_unescape_object_path (const gchar *object_path);