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 */
NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED,
/* The supplicant is now available */
NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE,
/* Unused */
NM_DEVICE_STATE_REASON_LAST = 0xFFFF
} NMDeviceStateReason;

View file

@ -380,6 +380,11 @@
<tp:docstring>
The device's existing connection was assumed.
</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:enum>

View file

@ -38,8 +38,6 @@ typedef struct {
guint32 ip_method;
char *device;
guint state_to_disconnected_id;
/* PPP stats */
guint32 in_bytes;
guint32 out_bytes;
@ -415,15 +413,6 @@ real_get_generic_capabilities (NMDevice *dev)
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
device_state_changed (NMDeviceInterface *device,
NMDeviceState new_state,
@ -434,19 +423,6 @@ device_state_changed (NMDeviceInterface *device,
NMModem *self = NM_MODEM (user_data);
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 */
switch (new_state) {
case NM_DEVICE_STATE_NEED_AUTH:
@ -601,11 +577,6 @@ finalize (GObject *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)
g_object_unref (priv->proxy);

View file

@ -51,7 +51,6 @@ typedef struct {
char *name;
guint32 capabilities;
guint state_to_disconnected_id;
DBusGProxy *type_proxy;
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
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
@ -822,11 +772,6 @@ finalize (GObject *object)
g_free (priv->bdaddr);
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);
}
@ -838,7 +783,6 @@ nm_device_bt_class_init (NMDeviceBtClass *klass)
g_type_class_add_private (object_class, sizeof (NMDeviceBtPrivate));
object_class->constructor = constructor;
object_class->get_property = get_property;
object_class->set_property = set_property;
object_class->finalize = finalize;

View file

@ -106,7 +106,6 @@ typedef struct {
struct ether_addr hw_addr;
gboolean carrier;
guint32 ifindex;
guint state_to_disconnected_id;
NMNetlinkMonitor * monitor;
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*
constructor (GType type,
guint n_construct_params,
@ -319,8 +285,6 @@ constructor (GType type,
priv->carrier = TRUE;
}
g_signal_connect (self, "state-changed", G_CALLBACK (device_state_changed), self);
return object;
}
@ -1698,11 +1662,6 @@ dispose (GObject *object)
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);
}

View file

@ -156,7 +156,6 @@ struct _NMDeviceWifiPrivate {
NMAccessPoint * current_ap;
guint32 rate;
gboolean enabled; /* rfkilled or not */
guint state_to_disconnected_id;
glong scheduled_scan_time;
guint8 scan_interval; /* seconds */
@ -2249,6 +2248,15 @@ supplicant_iface_state_cb_handler (gpointer user_data)
/* Request a scan to get latest results */
cancel_pending_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) {
cleanup_association_attempt (self, FALSE);
supplicant_interface_release (self);
@ -3224,15 +3232,6 @@ spec_match_list (NMDevice *device, const GSList *specs)
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
device_state_changed (NMDevice *device,
NMDeviceState new_state,
@ -3244,12 +3243,6 @@ device_state_changed (NMDevice *device,
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
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) {
/* Clean up the supplicant interface because in these states the
* device cannot be used.
@ -3276,9 +3269,6 @@ device_state_changed (NMDevice *device,
if (!priv->supplicant.iface)
supplicant_interface_acquire (self);
if (priv->supplicant.iface)
priv->state_to_disconnected_id = g_idle_add (unavailable_to_disconnected, self);
}
clear_aps = TRUE;
break;
@ -3459,11 +3449,6 @@ dispose (GObject *object)
set_current_ap (self, NULL);
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);
}

View file

@ -77,6 +77,7 @@ typedef struct {
NMDeviceState state;
guint failed_to_disconnected_id;
guint unavailable_to_disconnected_id;
char * udi;
char * path;
@ -1960,6 +1961,21 @@ clear_act_request (NMDevice *self)
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
*
@ -1981,10 +1997,8 @@ nm_device_deactivate_quickly (NMDevice *self)
activation_source_clear (self, TRUE, AF_INET);
activation_source_clear (self, TRUE, AF_INET6);
if (priv->failed_to_disconnected_id) {
g_source_remove (priv->failed_to_disconnected_id);
priv->failed_to_disconnected_id = 0;
}
/* Clear any delayed transitions */
delayed_transitions_clear (self);
/* Stop any ongoing DHCP transaction on this device */
if (nm_device_get_act_request (self)) {
@ -2723,10 +2737,8 @@ dispose (GObject *object)
}
}
if (priv->failed_to_disconnected_id) {
g_source_remove (priv->failed_to_disconnected_id);
priv->failed_to_disconnected_id = 0;
}
/* Clear any delayed transitions */
delayed_transitions_clear (self);
if (priv->managed && take_down) {
NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE;
@ -2985,6 +2997,17 @@ failed_to_disconnected (gpointer user_data)
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
nm_device_state_changed (NMDevice *device,
NMDeviceState state,
@ -3006,10 +3029,8 @@ nm_device_state_changed (NMDevice *device,
nm_info ("(%s): device state change: %d -> %d (reason %d)",
nm_device_get_iface (device), old_state, state, reason);
if (priv->failed_to_disconnected_id) {
g_source_remove (priv->failed_to_disconnected_id);
priv->failed_to_disconnected_id = 0;
}
/* Clear any delayed transitions */
delayed_transitions_clear (device);
/* Cache the activation request for the dispatcher */
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 */
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:
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);
break;
case NM_DEVICE_STATE_FAILED:
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);
break;
default: