core: generalize unavailable -> disconnected delayed transition

Instead of doing this in every device subclass, do it in the NMDevice
superclass.  nm_device_can_activate() already did the same logic that
each of the subclass device_state_changed() handlers were doing to
figure out whether they could do the transition from unavailable
to disconnected, so just use that in NMDevice and kill lots of code.
This commit is contained in:
Dan Williams
2009-09-14 13:24:29 -07:00
parent f01c565230
commit 393bdd3737
7 changed files with 64 additions and 162 deletions

View File

@@ -362,6 +362,9 @@ typedef enum {
/* The device's existing connection was assumed */ /* The device's existing connection was assumed */
NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED,
/* The supplicant is now available */
NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE,
/* Unused */ /* Unused */
NM_DEVICE_STATE_REASON_LAST = 0xFFFF NM_DEVICE_STATE_REASON_LAST = 0xFFFF
} NMDeviceStateReason; } NMDeviceStateReason;

View File

@@ -380,6 +380,11 @@
<tp:docstring> <tp:docstring>
The device's existing connection was assumed. The device's existing connection was assumed.
</tp:docstring> </tp:docstring>
</tp:enumvalue>
<tp:enumvalue suffix="SUPPLICANT_AVAILABLE" value="42">
<tp:docstring>
The 802.1x supplicant is now available.
</tp:docstring>
</tp:enumvalue> </tp:enumvalue>
</tp:enum> </tp:enum>

View File

@@ -38,8 +38,6 @@ typedef struct {
guint32 ip_method; guint32 ip_method;
char *device; char *device;
guint state_to_disconnected_id;
/* PPP stats */ /* PPP stats */
guint32 in_bytes; guint32 in_bytes;
guint32 out_bytes; guint32 out_bytes;
@@ -415,15 +413,6 @@ real_get_generic_capabilities (NMDevice *dev)
return NM_DEVICE_CAP_NM_SUPPORTED; return NM_DEVICE_CAP_NM_SUPPORTED;
} }
static gboolean
unavailable_to_disconnected (gpointer user_data)
{
nm_device_state_changed (NM_DEVICE (user_data),
NM_DEVICE_STATE_DISCONNECTED,
NM_DEVICE_STATE_REASON_NONE);
return FALSE;
}
static void static void
device_state_changed (NMDeviceInterface *device, device_state_changed (NMDeviceInterface *device,
NMDeviceState new_state, NMDeviceState new_state,
@@ -434,19 +423,6 @@ device_state_changed (NMDeviceInterface *device,
NMModem *self = NM_MODEM (user_data); NMModem *self = NM_MODEM (user_data);
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
/* Remove any previous delayed transition to disconnected */
if (priv->state_to_disconnected_id) {
g_source_remove (priv->state_to_disconnected_id);
priv->state_to_disconnected_id = 0;
}
/* If transitioning to UNAVAILBLE and we have a carrier, transition to
* DISCONNECTED because the device is ready to use. Otherwise the carrier-on
* handler will handle the transition to DISCONNECTED when the carrier is detected.
*/
if (new_state == NM_DEVICE_STATE_UNAVAILABLE)
priv->state_to_disconnected_id = g_idle_add (unavailable_to_disconnected, user_data);
/* Make sure we don't leave the serial device open */ /* Make sure we don't leave the serial device open */
switch (new_state) { switch (new_state) {
case NM_DEVICE_STATE_NEED_AUTH: case NM_DEVICE_STATE_NEED_AUTH:
@@ -601,11 +577,6 @@ finalize (GObject *object)
{ {
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object); NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object);
if (priv->state_to_disconnected_id) {
g_source_remove (priv->state_to_disconnected_id);
priv->state_to_disconnected_id = 0;
}
if (priv->proxy) if (priv->proxy)
g_object_unref (priv->proxy); g_object_unref (priv->proxy);

View File

@@ -51,7 +51,6 @@ typedef struct {
char *name; char *name;
guint32 capabilities; guint32 capabilities;
guint state_to_disconnected_id;
DBusGProxy *type_proxy; DBusGProxy *type_proxy;
NMPPPManager *ppp_manager; NMPPPManager *ppp_manager;
@@ -715,55 +714,6 @@ nm_device_bt_init (NMDeviceBt *self)
{ {
} }
static gboolean
unavailable_to_disconnected (gpointer user_data)
{
nm_device_state_changed (NM_DEVICE (user_data),
NM_DEVICE_STATE_DISCONNECTED,
NM_DEVICE_STATE_REASON_NONE);
return FALSE;
}
static void
device_state_changed (NMDeviceInterface *device,
NMDeviceState new_state,
NMDeviceState old_state,
NMDeviceStateReason reason,
gpointer user_data)
{
NMDeviceBt *self = NM_DEVICE_BT (user_data);
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self);
/* Remove any previous delayed transition to disconnected */
if (priv->state_to_disconnected_id) {
g_source_remove (priv->state_to_disconnected_id);
priv->state_to_disconnected_id = 0;
}
/* Transition to DISCONNECTED from an idle handler */
if (new_state == NM_DEVICE_STATE_UNAVAILABLE)
priv->state_to_disconnected_id = g_idle_add (unavailable_to_disconnected, self);
}
static GObject*
constructor (GType type,
guint n_construct_params,
GObjectConstructParam *construct_params)
{
GObject *object;
object = G_OBJECT_CLASS (nm_device_bt_parent_class)->constructor (type,
n_construct_params,
construct_params);
if (!object)
return NULL;
g_signal_connect (NM_DEVICE (object), "state-changed",
G_CALLBACK (device_state_changed), NM_DEVICE_BT (object));
return object;
}
static void static void
set_property (GObject *object, guint prop_id, set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec) const GValue *value, GParamSpec *pspec)
@@ -822,11 +772,6 @@ finalize (GObject *object)
g_free (priv->bdaddr); g_free (priv->bdaddr);
g_free (priv->name); g_free (priv->name);
if (priv->state_to_disconnected_id) {
g_source_remove (priv->state_to_disconnected_id);
priv->state_to_disconnected_id = 0;
}
G_OBJECT_CLASS (nm_device_bt_parent_class)->finalize (object); G_OBJECT_CLASS (nm_device_bt_parent_class)->finalize (object);
} }
@@ -838,7 +783,6 @@ nm_device_bt_class_init (NMDeviceBtClass *klass)
g_type_class_add_private (object_class, sizeof (NMDeviceBtPrivate)); g_type_class_add_private (object_class, sizeof (NMDeviceBtPrivate));
object_class->constructor = constructor;
object_class->get_property = get_property; object_class->get_property = get_property;
object_class->set_property = set_property; object_class->set_property = set_property;
object_class->finalize = finalize; object_class->finalize = finalize;

View File

@@ -106,7 +106,6 @@ typedef struct {
struct ether_addr hw_addr; struct ether_addr hw_addr;
gboolean carrier; gboolean carrier;
guint32 ifindex; guint32 ifindex;
guint state_to_disconnected_id;
NMNetlinkMonitor * monitor; NMNetlinkMonitor * monitor;
gulong link_connected_id; gulong link_connected_id;
@@ -242,39 +241,6 @@ carrier_off (NMNetlinkMonitor *monitor,
} }
} }
static gboolean
unavailable_to_disconnected (gpointer user_data)
{
nm_device_state_changed (NM_DEVICE (user_data), NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE);
return FALSE;
}
static void
device_state_changed (NMDeviceInterface *device,
NMDeviceState new_state,
NMDeviceState old_state,
NMDeviceStateReason reason,
gpointer user_data)
{
NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data);
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
/* Remove any previous delayed transition to disconnected */
if (priv->state_to_disconnected_id) {
g_source_remove (priv->state_to_disconnected_id);
priv->state_to_disconnected_id = 0;
}
/* If transitioning to UNAVAILBLE and we have a carrier, transition to
* DISCONNECTED because the device is ready to use. Otherwise the carrier-on
* handler will handle the transition to DISCONNECTED when the carrier is detected.
*/
if ((new_state == NM_DEVICE_STATE_UNAVAILABLE) && priv->carrier) {
priv->state_to_disconnected_id = g_idle_add (unavailable_to_disconnected, self);
return;
}
}
static GObject* static GObject*
constructor (GType type, constructor (GType type,
guint n_construct_params, guint n_construct_params,
@@ -319,8 +285,6 @@ constructor (GType type,
priv->carrier = TRUE; priv->carrier = TRUE;
} }
g_signal_connect (self, "state-changed", G_CALLBACK (device_state_changed), self);
return object; return object;
} }
@@ -1698,11 +1662,6 @@ dispose (GObject *object)
priv->monitor = NULL; priv->monitor = NULL;
} }
if (priv->state_to_disconnected_id) {
g_source_remove (priv->state_to_disconnected_id);
priv->state_to_disconnected_id = 0;
}
G_OBJECT_CLASS (nm_device_ethernet_parent_class)->dispose (object); G_OBJECT_CLASS (nm_device_ethernet_parent_class)->dispose (object);
} }

View File

@@ -156,7 +156,6 @@ struct _NMDeviceWifiPrivate {
NMAccessPoint * current_ap; NMAccessPoint * current_ap;
guint32 rate; guint32 rate;
gboolean enabled; /* rfkilled or not */ gboolean enabled; /* rfkilled or not */
guint state_to_disconnected_id;
glong scheduled_scan_time; glong scheduled_scan_time;
guint8 scan_interval; /* seconds */ guint8 scan_interval; /* seconds */
@@ -2249,6 +2248,15 @@ supplicant_iface_state_cb_handler (gpointer user_data)
/* Request a scan to get latest results */ /* Request a scan to get latest results */
cancel_pending_scan (self); cancel_pending_scan (self);
request_wireless_scan (self); request_wireless_scan (self);
/* If the interface can now be activated because the supplicant is now
* available, transition to DISCONNECTED.
*/
if ( (nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_UNAVAILABLE)
&& nm_device_can_activate (NM_DEVICE (self))) {
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_DISCONNECTED,
NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE);
}
} else if (task->new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) { } else if (task->new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) {
cleanup_association_attempt (self, FALSE); cleanup_association_attempt (self, FALSE);
supplicant_interface_release (self); supplicant_interface_release (self);
@@ -3224,15 +3232,6 @@ spec_match_list (NMDevice *device, const GSList *specs)
return matched; return matched;
} }
static gboolean
unavailable_to_disconnected (gpointer user_data)
{
nm_device_state_changed (NM_DEVICE (user_data),
NM_DEVICE_STATE_DISCONNECTED,
NM_DEVICE_STATE_REASON_NONE);
return FALSE;
}
static void static void
device_state_changed (NMDevice *device, device_state_changed (NMDevice *device,
NMDeviceState new_state, NMDeviceState new_state,
@@ -3244,12 +3243,6 @@ device_state_changed (NMDevice *device,
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
gboolean clear_aps = FALSE; gboolean clear_aps = FALSE;
/* Remove any previous delayed transition to disconnected */
if (priv->state_to_disconnected_id) {
g_source_remove (priv->state_to_disconnected_id);
priv->state_to_disconnected_id = 0;
}
if (new_state <= NM_DEVICE_STATE_UNAVAILABLE) { if (new_state <= NM_DEVICE_STATE_UNAVAILABLE) {
/* Clean up the supplicant interface because in these states the /* Clean up the supplicant interface because in these states the
* device cannot be used. * device cannot be used.
@@ -3276,9 +3269,6 @@ device_state_changed (NMDevice *device,
if (!priv->supplicant.iface) if (!priv->supplicant.iface)
supplicant_interface_acquire (self); supplicant_interface_acquire (self);
if (priv->supplicant.iface)
priv->state_to_disconnected_id = g_idle_add (unavailable_to_disconnected, self);
} }
clear_aps = TRUE; clear_aps = TRUE;
break; break;
@@ -3459,11 +3449,6 @@ dispose (GObject *object)
set_current_ap (self, NULL); set_current_ap (self, NULL);
remove_all_aps (self); remove_all_aps (self);
if (priv->state_to_disconnected_id) {
g_source_remove (priv->state_to_disconnected_id);
priv->state_to_disconnected_id = 0;
}
G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object); G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object);
} }

View File

@@ -77,6 +77,7 @@ typedef struct {
NMDeviceState state; NMDeviceState state;
guint failed_to_disconnected_id; guint failed_to_disconnected_id;
guint unavailable_to_disconnected_id;
char * udi; char * udi;
char * path; char * path;
@@ -1960,6 +1961,21 @@ clear_act_request (NMDevice *self)
priv->act_request = NULL; priv->act_request = NULL;
} }
static void
delayed_transitions_clear (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
if (priv->failed_to_disconnected_id) {
g_source_remove (priv->failed_to_disconnected_id);
priv->failed_to_disconnected_id = 0;
}
if (priv->unavailable_to_disconnected_id) {
g_source_remove (priv->unavailable_to_disconnected_id);
priv->unavailable_to_disconnected_id = 0;
}
}
/* /*
* nm_device_deactivate_quickly * nm_device_deactivate_quickly
* *
@@ -1981,10 +1997,8 @@ nm_device_deactivate_quickly (NMDevice *self)
activation_source_clear (self, TRUE, AF_INET); activation_source_clear (self, TRUE, AF_INET);
activation_source_clear (self, TRUE, AF_INET6); activation_source_clear (self, TRUE, AF_INET6);
if (priv->failed_to_disconnected_id) { /* Clear any delayed transitions */
g_source_remove (priv->failed_to_disconnected_id); delayed_transitions_clear (self);
priv->failed_to_disconnected_id = 0;
}
/* Stop any ongoing DHCP transaction on this device */ /* Stop any ongoing DHCP transaction on this device */
if (nm_device_get_act_request (self)) { if (nm_device_get_act_request (self)) {
@@ -2723,10 +2737,8 @@ dispose (GObject *object)
} }
} }
if (priv->failed_to_disconnected_id) { /* Clear any delayed transitions */
g_source_remove (priv->failed_to_disconnected_id); delayed_transitions_clear (self);
priv->failed_to_disconnected_id = 0;
}
if (priv->managed && take_down) { if (priv->managed && take_down) {
NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE; NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE;
@@ -2985,6 +2997,17 @@ failed_to_disconnected (gpointer user_data)
return FALSE; return FALSE;
} }
static gboolean
unavailable_to_disconnected (gpointer user_data)
{
NMDevice *self = NM_DEVICE (user_data);
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
priv->unavailable_to_disconnected_id = 0;
nm_device_state_changed (self, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE);
return FALSE;
}
void void
nm_device_state_changed (NMDevice *device, nm_device_state_changed (NMDevice *device,
NMDeviceState state, NMDeviceState state,
@@ -3006,10 +3029,8 @@ nm_device_state_changed (NMDevice *device,
nm_info ("(%s): device state change: %d -> %d (reason %d)", nm_info ("(%s): device state change: %d -> %d (reason %d)",
nm_device_get_iface (device), old_state, state, reason); nm_device_get_iface (device), old_state, state, reason);
if (priv->failed_to_disconnected_id) { /* Clear any delayed transitions */
g_source_remove (priv->failed_to_disconnected_id); delayed_transitions_clear (device);
priv->failed_to_disconnected_id = 0;
}
/* Cache the activation request for the dispatcher */ /* Cache the activation request for the dispatcher */
req = priv->act_request ? g_object_ref (priv->act_request) : NULL; req = priv->act_request ? g_object_ref (priv->act_request) : NULL;
@@ -3049,12 +3070,26 @@ nm_device_state_changed (NMDevice *device,
/* Post-process the event after internal notification */ /* Post-process the event after internal notification */
switch (state) { switch (state) {
case NM_DEVICE_STATE_UNAVAILABLE:
/* If the device can activate now (ie, it's got a carrier, the supplicant
* is active, or whatever) schedule a delayed transition to DISCONNECTED
* to get things rolling. The device can't transition immediately becuase
* we can't change states again from the state handler for a variety of
* reasons.
*/
if (nm_device_can_activate (device))
priv->unavailable_to_disconnected_id = g_idle_add (unavailable_to_disconnected, device);
break;
case NM_DEVICE_STATE_ACTIVATED: case NM_DEVICE_STATE_ACTIVATED:
nm_info ("Activation (%s) successful, device activated.", nm_device_get_iface (device)); nm_info ("Activation (%s) successful, device activated.", nm_device_get_iface (device));
nm_utils_call_dispatcher ("up", nm_act_request_get_connection (req), device, NULL); nm_utils_call_dispatcher ("up", nm_act_request_get_connection (req), device, NULL);
break; break;
case NM_DEVICE_STATE_FAILED: case NM_DEVICE_STATE_FAILED:
nm_info ("Activation (%s) failed.", nm_device_get_iface (device)); nm_info ("Activation (%s) failed.", nm_device_get_iface (device));
/* Schedule the transition to DISCONNECTED. The device can't transition
* immediately becuase we can't change states again from the state
* handler for a variety of reasons.
*/
priv->failed_to_disconnected_id = g_idle_add (failed_to_disconnected, device); priv->failed_to_disconnected_id = g_idle_add (failed_to_disconnected, device);
break; break;
default: default: