From 71c4e2338bfa6f27d51fbb5e54276c5b8afe2455 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 5 Oct 2010 14:19:43 -0500 Subject: [PATCH 1/9] supplicant: simplify supplicant interface object Move GObject stuff to the bottom to reduce prototype abuse and remove unneeded prefixes from stuff that's private to the class itself. We also don't need the 'supplicant-manager' or 'device' properties since they weren't used anywhere. --- .../nm-supplicant-interface.c | 568 ++++++++---------- 1 file changed, 245 insertions(+), 323 deletions(-) diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c index a65a458f5b..c04dc5e1cf 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2006 - 2008 Red Hat, Inc. + * Copyright (C) 2006 - 2010 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -47,26 +47,11 @@ G_DEFINE_TYPE (NMSupplicantInterface, nm_supplicant_interface, G_TYPE_OBJECT) NM_TYPE_SUPPLICANT_INTERFACE, \ NMSupplicantInterfacePrivate)) -static void nm_supplicant_interface_set_property (GObject * object, - guint prop_id, - const GValue * value, - GParamSpec * pspec); - -static void nm_supplicant_interface_get_property (GObject * object, - guint prop_id, - GValue * value, - GParamSpec * pspec); - static void nm_supplicant_interface_start (NMSupplicantInterface *self); static void nm_supplicant_interface_add_to_supplicant (NMSupplicantInterface *self, gboolean get_only); -static void nm_supplicant_interface_smgr_state_changed (NMSupplicantManager *smgr, - guint32 new_state, - guint32 old_state, - gpointer user_data); - static void nm_supplicant_interface_set_state (NMSupplicantInterface *self, guint32 new_state); @@ -82,14 +67,12 @@ enum { CONNECTION_ERROR, /* an error occurred during a connection request */ LAST_SIGNAL }; -static guint nm_supplicant_interface_signals[LAST_SIGNAL] = { 0 }; +static guint signals[LAST_SIGNAL] = { 0 }; /* Properties */ enum { PROP_0 = 0, - PROP_SUPPLICANT_MANAGER, - PROP_DEVICE, PROP_STATE, PROP_CONNECTION_STATE, PROP_SCANNING, @@ -121,7 +104,7 @@ typedef struct NMSupplicantConfig * cfg; - gboolean dispose_has_run; + gboolean disposed; } NMSupplicantInterfacePrivate; static gboolean @@ -203,103 +186,6 @@ nm_supplicant_info_destroy (gpointer user_data) } } - -NMSupplicantInterface * -nm_supplicant_interface_new (NMSupplicantManager * smgr, const char *ifname, gboolean is_wireless) -{ - NMSupplicantInterface * iface; - - g_return_val_if_fail (NM_IS_SUPPLICANT_MANAGER (smgr), NULL); - g_return_val_if_fail (ifname != NULL, NULL); - - iface = g_object_new (NM_TYPE_SUPPLICANT_INTERFACE, - "supplicant-manager", smgr, - "device", ifname, - NULL); - if (iface) { - NM_SUPPLICANT_INTERFACE_GET_PRIVATE (iface)->is_wireless = is_wireless; - nm_supplicant_interface_start (iface); - } - - return iface; -} - -static void -nm_supplicant_interface_init (NMSupplicantInterface * self) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - - priv->state = NM_SUPPLICANT_INTERFACE_STATE_INIT; - priv->con_state = NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED; - priv->assoc_pcalls = nm_call_store_new (); - priv->other_pcalls = nm_call_store_new (); - - priv->dispose_has_run = FALSE; - - priv->dbus_mgr = nm_dbus_manager_get (); -} - - -static void -nm_supplicant_interface_set_property (GObject * object, - guint prop_id, - const GValue * value, - GParamSpec * pspec) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object); - gulong id; - - switch (prop_id) { - case PROP_SUPPLICANT_MANAGER: - priv->smgr = NM_SUPPLICANT_MANAGER (g_value_get_object (value)); - g_object_ref (G_OBJECT (priv->smgr)); - - id = g_signal_connect (priv->smgr, - "state", - G_CALLBACK (nm_supplicant_interface_smgr_state_changed), - object); - priv->smgr_state_sig_handler = id; - break; - case PROP_DEVICE: - /* Construct-only */ - priv->dev = g_strdup (g_value_get_string (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_supplicant_interface_get_property (GObject * object, - guint prop_id, - GValue * value, - GParamSpec * pspec) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_SUPPLICANT_MANAGER: - g_value_set_object (value, G_OBJECT (priv->smgr)); - break; - case PROP_DEVICE: - g_value_set_string (value, priv->dev); - break; - case PROP_STATE: - g_value_set_uint (value, priv->state); - break; - case PROP_CONNECTION_STATE: - g_value_set_uint (value, priv->con_state); - break; - case PROP_SCANNING: - g_value_set_boolean (value, priv->scanning); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - static void try_remove_iface (DBusGConnection *g_connection, const char *path) @@ -322,175 +208,6 @@ try_remove_iface (DBusGConnection *g_connection, g_object_unref (proxy); } -static void -nm_supplicant_interface_dispose (GObject *object) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object); - guint32 sm_state; - - if (priv->dispose_has_run) { - G_OBJECT_CLASS (nm_supplicant_interface_parent_class)->dispose (object); - return; - } - - priv->dispose_has_run = TRUE; - - /* Ask wpa_supplicant to remove this interface */ - sm_state = nm_supplicant_manager_get_state (priv->smgr); - if (sm_state == NM_SUPPLICANT_MANAGER_STATE_IDLE) { - if (priv->object_path) { - try_remove_iface (nm_dbus_manager_get_connection (priv->dbus_mgr), - priv->object_path); - } - } - - if (priv->iface_proxy) - g_object_unref (priv->iface_proxy); - - if (priv->net_proxy) - g_object_unref (priv->net_proxy); - - if (priv->scan_results_timeout) - g_source_remove (priv->scan_results_timeout); - - if (priv->smgr) { - g_signal_handler_disconnect (priv->smgr, - priv->smgr_state_sig_handler); - g_object_unref (priv->smgr); - } - - g_free (priv->dev); - - /* Cancel pending calls before unrefing the dbus manager */ - cancel_all_callbacks (priv->other_pcalls); - nm_call_store_destroy (priv->other_pcalls); - - cancel_all_callbacks (priv->assoc_pcalls); - nm_call_store_destroy (priv->assoc_pcalls); - - if (priv->dbus_mgr) - g_object_unref (priv->dbus_mgr); - - if (priv->cfg) - g_object_unref (priv->cfg); - - g_free (priv->object_path); - - /* Chain up to the parent class */ - G_OBJECT_CLASS (nm_supplicant_interface_parent_class)->dispose (object); -} - -static void -nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMSupplicantInterfacePrivate)); - - object_class->dispose = nm_supplicant_interface_dispose; - object_class->set_property = nm_supplicant_interface_set_property; - object_class->get_property = nm_supplicant_interface_get_property; - - /* Properties */ - g_object_class_install_property (object_class, - PROP_SUPPLICANT_MANAGER, - g_param_spec_object ("supplicant-manager", - "Supplicant Manager", - "Supplicant manager to which this interface belongs", - NM_TYPE_SUPPLICANT_MANAGER, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (object_class, - PROP_DEVICE, - g_param_spec_string ("device", - "Device", - "Device which this interface represents to the supplicant", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (object_class, - PROP_STATE, - g_param_spec_uint ("state", - "State", - "State of the supplicant interface; INIT, READY, or DOWN", - NM_SUPPLICANT_INTERFACE_STATE_INIT, - NM_SUPPLICANT_INTERFACE_STATE_LAST - 1, - NM_SUPPLICANT_INTERFACE_STATE_INIT, - G_PARAM_READABLE)); - - g_object_class_install_property (object_class, - PROP_SCANNING, - g_param_spec_boolean ("scanning", - "Scanning", - "Scanning", - FALSE, - G_PARAM_READABLE)); - - /* Signals */ - nm_supplicant_interface_signals[STATE] = - g_signal_new ("state", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, state), - NULL, NULL, - _nm_marshal_VOID__UINT_UINT, - G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); - - nm_supplicant_interface_signals[REMOVED] = - g_signal_new ("removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, removed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - nm_supplicant_interface_signals[SCANNED_AP] = - g_signal_new ("scanned-ap", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scanned_ap), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - - nm_supplicant_interface_signals[SCAN_REQ_RESULT] = - g_signal_new ("scan-req-result", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scan_req_result), - NULL, NULL, - g_cclosure_marshal_VOID__BOOLEAN, - G_TYPE_NONE, 1, G_TYPE_BOOLEAN); - - nm_supplicant_interface_signals[SCAN_RESULTS] = - g_signal_new ("scan-results", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scan_results), - NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); - - nm_supplicant_interface_signals[CONNECTION_STATE] = - g_signal_new ("connection-state", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, connection_state), - NULL, NULL, - _nm_marshal_VOID__UINT_UINT, - G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); - - nm_supplicant_interface_signals[CONNECTION_ERROR] = - g_signal_new ("connection-error", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, connection_error), - NULL, NULL, - _nm_marshal_VOID__STRING_STRING, - G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); -} - static void emit_error_helper (NMSupplicantInterface *self, GError *err) @@ -500,11 +217,7 @@ emit_error_helper (NMSupplicantInterface *self, if (err->domain == DBUS_GERROR && err->code == DBUS_GERROR_REMOTE_EXCEPTION) name = dbus_g_error_get_name (err); - g_signal_emit (self, - nm_supplicant_interface_signals[CONNECTION_ERROR], - 0, - name, - err->message); + g_signal_emit (self, signals[CONNECTION_ERROR], 0, name, err->message); } static void @@ -523,11 +236,7 @@ bssid_properties_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_ } g_error_free (err); } else { - g_signal_emit (info->interface, - nm_supplicant_interface_signals[SCANNED_AP], - 0, - hash); - + g_signal_emit (info->interface, signals[SCANNED_AP], 0, hash); g_hash_table_destroy (hash); } } @@ -571,10 +280,7 @@ scan_results_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; /* Notify listeners of the result of the scan */ - g_signal_emit (info->interface, - nm_supplicant_interface_signals[SCAN_RESULTS], - 0, - array->len); + g_signal_emit (info->interface, signals[SCAN_RESULTS], 0, array->len); /* Fire off a "properties" call for each returned BSSID */ for (i = 0; i < array->len; i++) { @@ -674,13 +380,8 @@ wpas_iface_handle_state_change (DBusGProxy *proxy, enum_new_state = wpas_state_string_to_enum (str_new_state); old_state = priv->con_state; priv->con_state = enum_new_state; - if (priv->con_state != old_state) { - g_signal_emit (user_data, - nm_supplicant_interface_signals[CONNECTION_STATE], - 0, - priv->con_state, - old_state); - } + if (priv->con_state != old_state) + g_signal_emit (user_data, signals[CONNECTION_STATE], 0, priv->con_state, old_state); } @@ -967,18 +668,14 @@ nm_supplicant_interface_set_state (NMSupplicantInterface * self, } priv->state = new_state; - g_signal_emit (self, - nm_supplicant_interface_signals[STATE], - 0, - priv->state, - old_state); + g_signal_emit (self, signals[STATE], 0, priv->state, old_state); } static void -nm_supplicant_interface_smgr_state_changed (NMSupplicantManager * smgr, - guint32 new_state, - guint32 old_state, - gpointer user_data) +smgr_state_changed (NMSupplicantManager *smgr, + guint32 new_state, + guint32 old_state, + gpointer user_data) { NMSupplicantInterface * self = NM_SUPPLICANT_INTERFACE (user_data); @@ -1194,9 +891,7 @@ call_set_blobs (NMSupplicantInfo *info, GHashTable *orig_blobs) const char *msg = "Not enough memory to create blob table."; nm_log_warn (LOGD_SUPPLICANT, "%s", msg); - g_signal_emit (info->interface, - nm_supplicant_interface_signals[CONNECTION_ERROR], - 0, "SendBlobError", msg); + g_signal_emit (info->interface, signals[CONNECTION_ERROR], 0, "SendBlobError", msg); return; } @@ -1339,10 +1034,7 @@ scan_request_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) } /* Notify listeners of the result of the scan */ - g_signal_emit (info->interface, - nm_supplicant_interface_signals[SCAN_REQ_RESULT], - 0, - success ? TRUE : FALSE); + g_signal_emit (info->interface, signals[SCAN_REQ_RESULT], 0, !!success); } gboolean @@ -1427,3 +1119,233 @@ nm_supplicant_interface_connection_state_to_string (guint32 state) return "unknown"; } +/*******************************************************************/ + +NMSupplicantInterface * +nm_supplicant_interface_new (NMSupplicantManager *smgr, + const char *ifname, + gboolean is_wireless) +{ + NMSupplicantInterface *self; + NMSupplicantInterfacePrivate *priv; + guint id; + + g_return_val_if_fail (NM_IS_SUPPLICANT_MANAGER (smgr), NULL); + g_return_val_if_fail (ifname != NULL, NULL); + + self = g_object_new (NM_TYPE_SUPPLICANT_INTERFACE, NULL); + if (self) { + priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + + priv->smgr = g_object_ref (smgr); + id = g_signal_connect (priv->smgr, + "state", + G_CALLBACK (smgr_state_changed), + self); + priv->smgr_state_sig_handler = id; + + priv->dev = g_strdup (ifname); + priv->is_wireless = is_wireless; + nm_supplicant_interface_start (self); + } + + return self; +} + +static void +nm_supplicant_interface_init (NMSupplicantInterface * self) +{ + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + + priv->state = NM_SUPPLICANT_INTERFACE_STATE_INIT; + priv->con_state = NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED; + priv->assoc_pcalls = nm_call_store_new (); + priv->other_pcalls = nm_call_store_new (); + priv->dbus_mgr = nm_dbus_manager_get (); +} + +static void +set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_STATE: + g_value_set_uint (value, NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object)->state); + break; + case PROP_CONNECTION_STATE: + g_value_set_uint (value, NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object)->con_state); + break; + case PROP_SCANNING: + g_value_set_boolean (value, NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object)->scanning); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object); + guint32 sm_state; + + if (priv->disposed) { + G_OBJECT_CLASS (nm_supplicant_interface_parent_class)->dispose (object); + return; + } + priv->disposed = TRUE; + + /* Ask wpa_supplicant to remove this interface */ + sm_state = nm_supplicant_manager_get_state (priv->smgr); + if (sm_state == NM_SUPPLICANT_MANAGER_STATE_IDLE) { + if (priv->object_path) { + try_remove_iface (nm_dbus_manager_get_connection (priv->dbus_mgr), + priv->object_path); + } + } + + if (priv->iface_proxy) + g_object_unref (priv->iface_proxy); + + if (priv->net_proxy) + g_object_unref (priv->net_proxy); + + if (priv->scan_results_timeout) + g_source_remove (priv->scan_results_timeout); + + if (priv->smgr) { + g_signal_handler_disconnect (priv->smgr, + priv->smgr_state_sig_handler); + g_object_unref (priv->smgr); + } + + g_free (priv->dev); + + /* Cancel pending calls before unrefing the dbus manager */ + cancel_all_callbacks (priv->other_pcalls); + nm_call_store_destroy (priv->other_pcalls); + + cancel_all_callbacks (priv->assoc_pcalls); + nm_call_store_destroy (priv->assoc_pcalls); + + if (priv->dbus_mgr) + g_object_unref (priv->dbus_mgr); + + if (priv->cfg) + g_object_unref (priv->cfg); + + g_free (priv->object_path); + + /* Chain up to the parent class */ + G_OBJECT_CLASS (nm_supplicant_interface_parent_class)->dispose (object); +} + +static void +nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMSupplicantInterfacePrivate)); + + object_class->dispose = dispose; + object_class->set_property = set_property; + object_class->get_property = get_property; + + /* Properties */ + g_object_class_install_property (object_class, PROP_STATE, + g_param_spec_uint ("state", + "State", + "State of the supplicant interface; INIT, READY, or DOWN", + NM_SUPPLICANT_INTERFACE_STATE_INIT, + NM_SUPPLICANT_INTERFACE_STATE_LAST - 1, + NM_SUPPLICANT_INTERFACE_STATE_INIT, + G_PARAM_READABLE)); + + g_object_class_install_property (object_class, PROP_SCANNING, + g_param_spec_boolean ("scanning", + "Scanning", + "Scanning", + FALSE, + G_PARAM_READABLE)); + + /* Signals */ + signals[STATE] = + g_signal_new ("state", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMSupplicantInterfaceClass, state), + NULL, NULL, + _nm_marshal_VOID__UINT_UINT, + G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); + + signals[REMOVED] = + g_signal_new ("removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMSupplicantInterfaceClass, removed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[SCANNED_AP] = + g_signal_new ("scanned-ap", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scanned_ap), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + + signals[SCAN_REQ_RESULT] = + g_signal_new ("scan-req-result", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scan_req_result), + NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + + signals[SCAN_RESULTS] = + g_signal_new ("scan-results", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scan_results), + NULL, NULL, + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, 1, G_TYPE_UINT); + + signals[CONNECTION_STATE] = + g_signal_new ("connection-state", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMSupplicantInterfaceClass, connection_state), + NULL, NULL, + _nm_marshal_VOID__UINT_UINT, + G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); + + signals[CONNECTION_ERROR] = + g_signal_new ("connection-error", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMSupplicantInterfaceClass, connection_error), + NULL, NULL, + _nm_marshal_VOID__STRING_STRING, + G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); +} + From 262db04e2015bd3911f1d9649ea49549f3f50dff Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 5 Oct 2010 14:19:56 -0500 Subject: [PATCH 2/9] supplicant: use a GHashTable instead of a GSList for tracking interfaces It's just less code. Yay. --- .../nm-supplicant-interface.c | 8 ++++ .../nm-supplicant-interface.h | 4 +- .../nm-supplicant-manager.c | 46 ++++++------------- 3 files changed, 25 insertions(+), 33 deletions(-) diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c index c04dc5e1cf..3c3fe52f84 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -1119,6 +1119,14 @@ nm_supplicant_interface_connection_state_to_string (guint32 state) return "unknown"; } +const char * +nm_supplicant_interface_get_ifname (NMSupplicantInterface *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + + return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->dev; +} + /*******************************************************************/ NMSupplicantInterface * diff --git a/src/supplicant-manager/nm-supplicant-interface.h b/src/supplicant-manager/nm-supplicant-interface.h index bee5436f5a..3e56f4efaf 100644 --- a/src/supplicant-manager/nm-supplicant-interface.h +++ b/src/supplicant-manager/nm-supplicant-interface.h @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2006 - 2008 Red Hat, Inc. + * Copyright (C) 2006 - 2010 Red Hat, Inc. * Copyright (C) 2007 - 2008 Novell, Inc. */ @@ -140,6 +140,8 @@ const char *nm_supplicant_interface_connection_state_to_string (guint32 state); gboolean nm_supplicant_interface_get_scanning (NMSupplicantInterface *self); +const char *nm_supplicant_interface_get_ifname (NMSupplicantInterface *self); + G_END_DECLS #endif /* NM_SUPPLICANT_INTERFACE_H */ diff --git a/src/supplicant-manager/nm-supplicant-manager.c b/src/supplicant-manager/nm-supplicant-manager.c index a2cf58eb8f..1077da8d7f 100644 --- a/src/supplicant-manager/nm-supplicant-manager.c +++ b/src/supplicant-manager/nm-supplicant-manager.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2006 - 2008 Red Hat, Inc. + * Copyright (C) 2006 - 2010 Red Hat, Inc. * Copyright (C) 2007 - 2008 Novell, Inc. */ @@ -35,7 +35,7 @@ typedef struct { NMDBusManager * dbus_mgr; guint32 state; - GSList * ifaces; + GHashTable * ifaces; gboolean dispose_has_run; guint poke_id; } NMSupplicantManagerPrivate; @@ -125,6 +125,8 @@ nm_supplicant_manager_init (NMSupplicantManager * self) priv->dbus_mgr = nm_dbus_manager_get (); priv->poke_id = 0; + priv->ifaces = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + running = nm_supplicant_manager_startup (self); g_signal_connect (priv->dbus_mgr, @@ -265,33 +267,23 @@ nm_supplicant_manager_startup (NMSupplicantManager * self) NMSupplicantInterface * nm_supplicant_manager_get_iface (NMSupplicantManager * self, - const char *ifname, - gboolean is_wireless) + const char *ifname, + gboolean is_wireless) { NMSupplicantManagerPrivate *priv; NMSupplicantInterface * iface = NULL; - GSList * elt; g_return_val_if_fail (NM_IS_SUPPLICANT_MANAGER (self), NULL); g_return_val_if_fail (ifname != NULL, NULL); priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self); - /* Ensure we don't already have this interface */ - for (elt = priv->ifaces; elt; elt = g_slist_next (elt)) { - NMSupplicantInterface * if_tmp = (NMSupplicantInterface *) elt->data; - - if (!strcmp (ifname, nm_supplicant_interface_get_device (if_tmp))) { - iface = if_tmp; - break; - } - } - + iface = g_hash_table_lookup (priv->ifaces, ifname); if (!iface) { nm_log_dbg (LOGD_SUPPLICANT, "(%s): creating new supplicant interface", ifname); iface = nm_supplicant_interface_new (self, ifname, is_wireless); if (iface) - priv->ifaces = g_slist_append (priv->ifaces, iface); + g_hash_table_insert (priv->ifaces, g_strdup (ifname), iface); } else { nm_log_dbg (LOGD_SUPPLICANT, "(%s): returning existing supplicant interface", ifname); } @@ -300,30 +292,20 @@ nm_supplicant_manager_get_iface (NMSupplicantManager * self, } void -nm_supplicant_manager_release_iface (NMSupplicantManager * self, - NMSupplicantInterface * iface) +nm_supplicant_manager_release_iface (NMSupplicantManager *self, + NMSupplicantInterface *iface) { NMSupplicantManagerPrivate *priv; - GSList * elt; + const char *ifname; g_return_if_fail (NM_IS_SUPPLICANT_MANAGER (self)); g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (iface)); priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self); - for (elt = priv->ifaces; elt; elt = g_slist_next (elt)) { - NMSupplicantInterface * if_tmp = (NMSupplicantInterface *) elt->data; - - if (if_tmp == iface) { - /* Remove the iface from the supplicant manager's list and - * dereference to match additional reference in get_iface. - */ - priv->ifaces = g_slist_remove_link (priv->ifaces, elt); - g_slist_free_1 (elt); - g_object_unref (iface); - break; - } - } + ifname = nm_supplicant_interface_get_ifname (iface); + g_assert (ifname); + g_hash_table_remove (priv->ifaces, ifname); } const char * From 4d63f084031bfe88887b6d655ecad2b81a135005 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 5 Oct 2010 14:20:23 -0500 Subject: [PATCH 3/9] supplicant: reorganize supplicant manager class Gets rid of prototypes and simplifies the code a bit. --- .../nm-supplicant-manager.c | 289 ++++++++---------- 1 file changed, 134 insertions(+), 155 deletions(-) diff --git a/src/supplicant-manager/nm-supplicant-manager.c b/src/supplicant-manager/nm-supplicant-manager.c index 1077da8d7f..56a5e58d63 100644 --- a/src/supplicant-manager/nm-supplicant-manager.c +++ b/src/supplicant-manager/nm-supplicant-manager.c @@ -36,8 +36,8 @@ typedef struct { NMDBusManager * dbus_mgr; guint32 state; GHashTable * ifaces; - gboolean dispose_has_run; - guint poke_id; + gboolean disposed; + guint poke_id; } NMSupplicantManagerPrivate; #define NM_SUPPLICANT_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ @@ -46,41 +46,14 @@ typedef struct { G_DEFINE_TYPE (NMSupplicantManager, nm_supplicant_manager, G_TYPE_OBJECT) - -static void nm_supplicant_manager_name_owner_changed (NMDBusManager *dbus_mgr, - const char *name, - const char *old, - const char *new, - gpointer user_data); - -static void nm_supplicant_manager_set_state (NMSupplicantManager * self, - guint32 new_state); - -static gboolean nm_supplicant_manager_startup (NMSupplicantManager * self); - - /* Signals */ enum { STATE, /* change in the manager's state */ LAST_SIGNAL }; -static guint nm_supplicant_manager_signals[LAST_SIGNAL] = { 0 }; +static guint signals[LAST_SIGNAL] = { 0 }; - -NMSupplicantManager * -nm_supplicant_manager_get (void) -{ - static NMSupplicantManager * singleton = NULL; - - if (!singleton) { - singleton = NM_SUPPLICANT_MANAGER (g_object_new (NM_TYPE_SUPPLICANT_MANAGER, NULL)); - } else { - g_object_ref (singleton); - } - - g_assert (singleton); - return singleton; -} +/********************************************************************/ static gboolean poke_supplicant_cb (gpointer user_data) @@ -114,117 +87,6 @@ out: return FALSE; } -static void -nm_supplicant_manager_init (NMSupplicantManager * self) -{ - NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self); - gboolean running; - - priv->dispose_has_run = FALSE; - priv->state = NM_SUPPLICANT_MANAGER_STATE_DOWN; - priv->dbus_mgr = nm_dbus_manager_get (); - priv->poke_id = 0; - - priv->ifaces = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); - - running = nm_supplicant_manager_startup (self); - - g_signal_connect (priv->dbus_mgr, - "name-owner-changed", - G_CALLBACK (nm_supplicant_manager_name_owner_changed), - self); - - if (!running) { - /* Try to activate the supplicant */ - priv->poke_id = g_idle_add (poke_supplicant_cb, (gpointer) self); - } -} - -static void -nm_supplicant_manager_dispose (GObject *object) -{ - NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (object); - - if (priv->dispose_has_run) { - G_OBJECT_CLASS (nm_supplicant_manager_parent_class)->dispose (object); - return; - } - - priv->dispose_has_run = TRUE; - - if (priv->poke_id) { - g_source_remove (priv->poke_id); - priv->poke_id = 0; - } - - if (priv->dbus_mgr) { - g_object_unref (G_OBJECT (priv->dbus_mgr)); - priv->dbus_mgr = NULL; - } - - /* Chain up to the parent class */ - G_OBJECT_CLASS (nm_supplicant_manager_parent_class)->dispose (object); -} - -static void -nm_supplicant_manager_class_init (NMSupplicantManagerClass *klass) -{ - GObjectClass * object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMSupplicantManagerPrivate)); - - object_class->dispose = nm_supplicant_manager_dispose; - - /* Signals */ - nm_supplicant_manager_signals[STATE] = - g_signal_new ("state", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantManagerClass, state), - NULL, NULL, - _nm_marshal_VOID__UINT_UINT, - G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); -} - -static void -nm_supplicant_manager_name_owner_changed (NMDBusManager *dbus_mgr, - const char *name, - const char *old_owner, - const char *new_owner, - gpointer user_data) -{ - NMSupplicantManager * self = (NMSupplicantManager *) user_data; - NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self); - gboolean old_owner_good = (old_owner && strlen (old_owner)); - gboolean new_owner_good = (new_owner && strlen (new_owner)); - - /* Can't handle the signal if its not from the supplicant service */ - if (strcmp (WPAS_DBUS_SERVICE, name) != 0) - return; - - if (!old_owner_good && new_owner_good) { - gboolean running; - - running = nm_supplicant_manager_startup (self); - - if (running && priv->poke_id) { - g_source_remove (priv->poke_id); - priv->poke_id = 0; - } - } else if (old_owner_good && !new_owner_good) { - nm_supplicant_manager_set_state (self, NM_SUPPLICANT_MANAGER_STATE_DOWN); - - if (priv->poke_id) - g_source_remove (priv->poke_id); - - /* Poke the supplicant so that it gets activated by dbus system bus - * activation. - */ - priv->poke_id = g_idle_add (poke_supplicant_cb, (gpointer) self); - } -} - - guint32 nm_supplicant_manager_get_state (NMSupplicantManager * self) { @@ -234,25 +96,20 @@ nm_supplicant_manager_get_state (NMSupplicantManager * self) } static void -nm_supplicant_manager_set_state (NMSupplicantManager * self, guint32 new_state) +set_state (NMSupplicantManager *self, guint32 new_state) { NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self); guint32 old_state; - if (new_state == priv->state) - return; - - old_state = priv->state; - priv->state = new_state; - g_signal_emit (self, - nm_supplicant_manager_signals[STATE], - 0, - priv->state, - old_state); + if (new_state != priv->state) { + old_state = priv->state; + priv->state = new_state; + g_signal_emit (self, signals[STATE], 0, priv->state, old_state); + } } static gboolean -nm_supplicant_manager_startup (NMSupplicantManager * self) +startup (NMSupplicantManager * self) { gboolean running; @@ -260,7 +117,7 @@ nm_supplicant_manager_startup (NMSupplicantManager * self) running = nm_dbus_manager_name_has_owner (NM_SUPPLICANT_MANAGER_GET_PRIVATE (self)->dbus_mgr, WPAS_DBUS_SERVICE); if (running) - nm_supplicant_manager_set_state (self, NM_SUPPLICANT_MANAGER_STATE_IDLE); + set_state (self, NM_SUPPLICANT_MANAGER_STATE_IDLE); return running; } @@ -322,4 +179,126 @@ nm_supplicant_manager_state_to_string (guint32 state) return "unknown"; } +static void +name_owner_changed (NMDBusManager *dbus_mgr, + const char *name, + const char *old_owner, + const char *new_owner, + gpointer user_data) +{ + NMSupplicantManager * self = (NMSupplicantManager *) user_data; + NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self); + gboolean old_owner_good = (old_owner && strlen (old_owner)); + gboolean new_owner_good = (new_owner && strlen (new_owner)); + + /* Can't handle the signal if its not from the supplicant service */ + if (strcmp (WPAS_DBUS_SERVICE, name) != 0) + return; + + if (!old_owner_good && new_owner_good) { + gboolean running; + + running = startup (self); + + if (running && priv->poke_id) { + g_source_remove (priv->poke_id); + priv->poke_id = 0; + } + } else if (old_owner_good && !new_owner_good) { + set_state (self, NM_SUPPLICANT_MANAGER_STATE_DOWN); + + if (priv->poke_id) + g_source_remove (priv->poke_id); + + /* Poke the supplicant so that it gets activated by dbus system bus + * activation. + */ + priv->poke_id = g_idle_add (poke_supplicant_cb, (gpointer) self); + } +} + +/*******************************************************************/ + +NMSupplicantManager * +nm_supplicant_manager_get (void) +{ + static NMSupplicantManager *singleton = NULL; + + if (!singleton) + singleton = NM_SUPPLICANT_MANAGER (g_object_new (NM_TYPE_SUPPLICANT_MANAGER, NULL)); + else + g_object_ref (singleton); + + g_assert (singleton); + return singleton; +} + +static void +nm_supplicant_manager_init (NMSupplicantManager * self) +{ + NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self); + gboolean running; + + priv->state = NM_SUPPLICANT_MANAGER_STATE_DOWN; + priv->dbus_mgr = nm_dbus_manager_get (); + priv->poke_id = 0; + + priv->ifaces = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + + running = startup (self); + + g_signal_connect (priv->dbus_mgr, + "name-owner-changed", + G_CALLBACK (name_owner_changed), + self); + + if (!running) { + /* Try to activate the supplicant */ + priv->poke_id = g_idle_add (poke_supplicant_cb, (gpointer) self); + } +} + +static void +dispose (GObject *object) +{ + NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (object); + + if (priv->disposed) { + G_OBJECT_CLASS (nm_supplicant_manager_parent_class)->dispose (object); + return; + } + priv->disposed = TRUE; + + if (priv->poke_id) { + g_source_remove (priv->poke_id); + priv->poke_id = 0; + } + + if (priv->dbus_mgr) { + g_object_unref (G_OBJECT (priv->dbus_mgr)); + priv->dbus_mgr = NULL; + } + + /* Chain up to the parent class */ + G_OBJECT_CLASS (nm_supplicant_manager_parent_class)->dispose (object); +} + +static void +nm_supplicant_manager_class_init (NMSupplicantManagerClass *klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMSupplicantManagerPrivate)); + + object_class->dispose = dispose; + + /* Signals */ + signals[STATE] = g_signal_new ("state", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NMSupplicantManagerClass, state), + NULL, NULL, + _nm_marshal_VOID__UINT_UINT, + G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); +} From f3a1366b55f5367c87afb95a2208cbb40729f5bf Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 6 Oct 2010 11:05:21 -0500 Subject: [PATCH 4/9] supplicant: collapse supplicant interface states We only really need one state for the supplicant interface which simplifies handling in the Wifi and Wired device classes quite a bit. It also simplifies the supplicant interface class too. One behavioral change in the device classes is not running the supplicant interface state changes from an idle; we'll have to see if that causes problems. ISTR long ago that processing the state change signals directly caused some issues, but we've significantly reworked somethings since then so we may be able to get away with this now. --- src/nm-device-ethernet.c | 298 ++-------- src/nm-device-wifi.c | 354 ++--------- .../nm-supplicant-interface.c | 562 ++++++++---------- .../nm-supplicant-interface.h | 53 +- .../nm-supplicant-manager.c | 232 +++----- .../nm-supplicant-manager.h | 38 +- 6 files changed, 470 insertions(+), 1067 deletions(-) diff --git a/src/nm-device-ethernet.c b/src/nm-device-ethernet.c index 08bbc50112..13139542fa 100644 --- a/src/nm-device-ethernet.c +++ b/src/nm-device-ethernet.c @@ -78,30 +78,17 @@ typedef enum #define NM_ETHERNET_ERROR (nm_ethernet_error_quark ()) #define NM_TYPE_ETHERNET_ERROR (nm_ethernet_error_get_type ()) -typedef struct SupplicantStateTask { - NMDeviceEthernet *self; - guint32 new_state; - guint32 old_state; - gboolean mgr_task; - guint source_id; -} SupplicantStateTask; - typedef struct Supplicant { NMSupplicantManager *mgr; NMSupplicantInterface *iface; /* signal handler ids */ - guint mgr_state_id; guint iface_error_id; guint iface_state_id; - guint iface_con_state_id; /* Timeouts and idles */ guint iface_con_error_cb_id; guint con_timeout_id; - - GSList *iface_tasks; - GSList *mgr_tasks; } Supplicant; typedef struct { @@ -996,30 +983,6 @@ remove_supplicant_timeouts (NMDeviceEthernet *self) } } -static void -finish_supplicant_task (SupplicantStateTask *task, gboolean remove_source) -{ - NMDeviceEthernet *self = task->self; - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - - /* idle/timeout handlers should pass FALSE for remove_source, since they - * will tell glib to remove their source from the mainloop by returning - * FALSE when they exit. When called from this NMDevice's dispose handler, - * remove_source should be TRUE to cancel all outstanding idle/timeout - * handlers asynchronously. - */ - if (task->source_id && remove_source) - g_source_remove (task->source_id); - - if (task->mgr_task) - priv->supplicant.mgr_tasks = g_slist_remove (priv->supplicant.mgr_tasks, task); - else - priv->supplicant.iface_tasks = g_slist_remove (priv->supplicant.iface_tasks, task); - - memset (task, 0, sizeof (SupplicantStateTask)); - g_slice_free (SupplicantStateTask, task); -} - static void remove_supplicant_interface_error_handler (NMDeviceEthernet *self) { @@ -1044,28 +1007,14 @@ supplicant_interface_release (NMDeviceEthernet *self) remove_supplicant_timeouts (self); remove_supplicant_interface_error_handler (self); - /* Clean up all pending supplicant interface state idle tasks */ - while (priv->supplicant.iface_tasks) - finish_supplicant_task ((SupplicantStateTask *) priv->supplicant.iface_tasks->data, TRUE); - - if (priv->supplicant.iface_con_state_id) { - g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_con_state_id); - priv->supplicant.iface_con_state_id = 0; - } - if (priv->supplicant.iface_state_id > 0) { g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_state_id); priv->supplicant.iface_state_id = 0; } - if (priv->supplicant.mgr_state_id) { - g_signal_handler_disconnect (priv->supplicant.mgr, priv->supplicant.mgr_state_id); - priv->supplicant.mgr_state_id = 0; - } - if (priv->supplicant.iface) { nm_supplicant_interface_disconnect (priv->supplicant.iface); - nm_supplicant_manager_release_iface (priv->supplicant.mgr, priv->supplicant.iface); + nm_supplicant_manager_iface_release (priv->supplicant.mgr, priv->supplicant.iface); priv->supplicant.iface = NULL; } } @@ -1127,77 +1076,6 @@ time_out: return FALSE; } -static gboolean -schedule_state_handler (NMDeviceEthernet *self, - GSourceFunc handler, - guint32 new_state, - guint32 old_state, - gboolean mgr_task) -{ - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - SupplicantStateTask *task; - - if (new_state == old_state) - return TRUE; - - task = g_slice_new0 (SupplicantStateTask); - if (!task) { - nm_log_err (LOGD_DEVICE, "Not enough memory to process supplicant manager state change."); - return FALSE; - } - - task->self = self; - task->new_state = new_state; - task->old_state = old_state; - task->mgr_task = mgr_task; - - task->source_id = g_idle_add (handler, task); - if (mgr_task) - priv->supplicant.mgr_tasks = g_slist_append (priv->supplicant.mgr_tasks, task); - else - priv->supplicant.iface_tasks = g_slist_append (priv->supplicant.iface_tasks, task); - return TRUE; -} - -static gboolean -supplicant_mgr_state_cb_handler (gpointer user_data) -{ - SupplicantStateTask *task = (SupplicantStateTask *) user_data; - NMDevice *device = NM_DEVICE (task->self); - - /* If the supplicant went away, release the supplicant interface */ - if (task->new_state == NM_SUPPLICANT_MANAGER_STATE_DOWN) { - supplicant_interface_release (task->self); - - if (nm_device_get_state (device) > NM_DEVICE_STATE_UNAVAILABLE) { - nm_device_state_changed (device, NM_DEVICE_STATE_UNAVAILABLE, - NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); - } - } - - finish_supplicant_task (task, FALSE); - return FALSE; -} - -static void -supplicant_mgr_state_cb (NMSupplicantInterface * iface, - guint32 new_state, - guint32 old_state, - gpointer user_data) -{ - nm_log_info (LOGD_DEVICE | LOGD_ETHER, - "(%s): supplicant manager state: %s -> %s", - nm_device_get_iface (NM_DEVICE (user_data)), - nm_supplicant_manager_state_to_string (old_state), - nm_supplicant_manager_state_to_string (new_state)); - - schedule_state_handler (NM_DEVICE_ETHERNET (user_data), - supplicant_mgr_state_cb_handler, - new_state, - old_state, - TRUE); -} - static NMSupplicantConfig * build_supplicant_config (NMDeviceEthernet *self) { @@ -1224,20 +1102,33 @@ build_supplicant_config (NMDeviceEthernet *self) return config; } -static gboolean -supplicant_iface_state_cb_handler (gpointer user_data) +static void +supplicant_iface_state_cb (NMSupplicantInterface *iface, + guint32 new_state, + guint32 old_state, + gpointer user_data) { - SupplicantStateTask *task = (SupplicantStateTask *) user_data; - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (task->self); - NMDevice *device = NM_DEVICE (task->self); + NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data); + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + NMDevice *device = NM_DEVICE (self); + NMSupplicantConfig *config; + gboolean success = FALSE; + NMDeviceState devstate; - if (task->new_state == NM_SUPPLICANT_INTERFACE_STATE_READY) { - NMSupplicantConfig *config; - const char *iface; - gboolean success = FALSE; + if (new_state == old_state) + return; - iface = nm_device_get_iface (device); - config = build_supplicant_config (task->self); + nm_log_info (LOGD_DEVICE | LOGD_ETHER, + "(%s): supplicant interface state: %s -> %s", + nm_device_get_iface (device), + nm_supplicant_interface_state_to_string (old_state), + nm_supplicant_interface_state_to_string (new_state)); + + devstate = nm_device_get_state (device); + + switch (new_state) { + case NM_SUPPLICANT_INTERFACE_STATE_READY: + config = build_supplicant_config (self); if (config) { success = nm_supplicant_interface_set_config (priv->supplicant.iface, config); g_object_unref (config); @@ -1246,99 +1137,54 @@ supplicant_iface_state_cb_handler (gpointer user_data) nm_log_err (LOGD_DEVICE | LOGD_ETHER, "Activation (%s/wired): couldn't send security " "configuration to the supplicant.", - iface); + nm_device_get_iface (device)); } } else { nm_log_warn (LOGD_DEVICE | LOGD_ETHER, "Activation (%s/wired): couldn't build security configuration.", - iface); + nm_device_get_iface (device)); } - if (!success) - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED); - } else if (task->new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) { - NMDeviceState state = nm_device_get_state (device); - - supplicant_interface_release (task->self); - - if (nm_device_is_activating (device) || state == NM_DEVICE_STATE_ACTIVATED) - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); - } - - finish_supplicant_task (task, FALSE); - return FALSE; -} - -static void -supplicant_iface_state_cb (NMSupplicantInterface * iface, - guint32 new_state, - guint32 old_state, - gpointer user_data) -{ - - nm_log_info (LOGD_DEVICE | LOGD_ETHER, - "(%s): supplicant interface state: %s -> %s", - nm_device_get_iface (NM_DEVICE (user_data)), - nm_supplicant_interface_state_to_string (old_state), - nm_supplicant_interface_state_to_string (new_state)); - - schedule_state_handler (NM_DEVICE_ETHERNET (user_data), - supplicant_iface_state_cb_handler, - new_state, - old_state, - FALSE); -} - -static gboolean -supplicant_iface_connection_state_cb_handler (gpointer user_data) -{ - SupplicantStateTask *task = (SupplicantStateTask *) user_data; - NMDevice *dev = NM_DEVICE (task->self); - - if (task->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED) { - remove_supplicant_interface_error_handler (task->self); - remove_supplicant_timeouts (task->self); + if (!success) { + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED); + } + break; + case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED: + remove_supplicant_interface_error_handler (self); + remove_supplicant_timeouts (self); /* If this is the initial association during device activation, * schedule the next activation stage. */ - if (nm_device_get_state (dev) == NM_DEVICE_STATE_CONFIG) { + if (devstate == NM_DEVICE_STATE_CONFIG) { nm_log_info (LOGD_DEVICE | LOGD_ETHER, "Activation (%s/wired) Stage 2 of 5 (Device Configure) successful.", - nm_device_get_iface (dev)); - nm_device_activate_schedule_stage3_ip_config_start (dev); + nm_device_get_iface (device)); + nm_device_activate_schedule_stage3_ip_config_start (device); } - } else if (task->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED) { - if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED || nm_device_is_activating (dev)) { - NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (task->self); - + break; + case NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED: + if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) { /* Start the link timeout so we allow some time for reauthentication */ if (!priv->supplicant_timeout_id) - priv->supplicant_timeout_id = g_timeout_add_seconds (15, link_timeout_cb, dev); + priv->supplicant_timeout_id = g_timeout_add_seconds (15, link_timeout_cb, device); } + break; + case NM_SUPPLICANT_INTERFACE_STATE_DOWN: + supplicant_interface_release (self); + remove_supplicant_timeouts (self); + + if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) { + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + } + break; + default: + break; } - - finish_supplicant_task (task, FALSE); - return FALSE; -} - -static void -supplicant_iface_connection_state_cb (NMSupplicantInterface * iface, - guint32 new_state, - guint32 old_state, - gpointer user_data) -{ - nm_log_info (LOGD_DEVICE | LOGD_ETHER, - "(%s) supplicant connection state: %s -> %s", - nm_device_get_iface (NM_DEVICE (user_data)), - nm_supplicant_interface_connection_state_to_string (old_state), - nm_supplicant_interface_connection_state_to_string (new_state)); - - schedule_state_handler (NM_DEVICE_ETHERNET (user_data), - supplicant_iface_connection_state_cb_handler, - new_state, - old_state, - FALSE); } static gboolean @@ -1456,38 +1302,26 @@ supplicant_interface_init (NMDeviceEthernet *self) iface = nm_device_get_iface (NM_DEVICE (self)); /* Create supplicant interface */ - priv->supplicant.iface = nm_supplicant_manager_get_iface (priv->supplicant.mgr, iface, FALSE); + priv->supplicant.iface = nm_supplicant_manager_iface_get (priv->supplicant.mgr, iface, FALSE); if (!priv->supplicant.iface) { nm_log_err (LOGD_DEVICE | LOGD_ETHER, "Couldn't initialize supplicant interface for %s.", iface); supplicant_interface_release (self); - return FALSE; } /* Listen for it's state signals */ priv->supplicant.iface_state_id = g_signal_connect (priv->supplicant.iface, - "state", - G_CALLBACK (supplicant_iface_state_cb), - self); + "state", + G_CALLBACK (supplicant_iface_state_cb), + self); /* Hook up error signal handler to capture association errors */ priv->supplicant.iface_error_id = g_signal_connect (priv->supplicant.iface, - "connection-error", - G_CALLBACK (supplicant_iface_connection_error_cb), - self); - - priv->supplicant.iface_con_state_id = g_signal_connect (priv->supplicant.iface, - "connection-state", - G_CALLBACK (supplicant_iface_connection_state_cb), - self); - - /* Listen for supplicant manager state changes */ - priv->supplicant.mgr_state_id = g_signal_connect (priv->supplicant.mgr, - "state", - G_CALLBACK (supplicant_mgr_state_cb), - self); + "connection-error", + G_CALLBACK (supplicant_iface_connection_error_cb), + self); /* Set up a timeout on the connection attempt to fail it after 25 seconds */ priv->supplicant.con_timeout_id = g_timeout_add_seconds (25, supplicant_connection_timeout_cb, self); @@ -2047,12 +1881,6 @@ dispose (GObject *object) priv->disposed = TRUE; - /* Clean up all pending supplicant tasks */ - while (priv->supplicant.iface_tasks) - finish_supplicant_task ((SupplicantStateTask *) priv->supplicant.iface_tasks->data, TRUE); - while (priv->supplicant.mgr_tasks) - finish_supplicant_task ((SupplicantStateTask *) priv->supplicant.mgr_tasks->data, TRUE); - if (priv->link_connected_id) { g_signal_handler_disconnect (priv->monitor, priv->link_connected_id); priv->link_connected_id = 0; diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c index b09d112547..44d5a12754 100644 --- a/src/nm-device-wifi.c +++ b/src/nm-device-wifi.c @@ -113,34 +113,21 @@ typedef enum { #define NM_WIFI_ERROR (nm_wifi_error_quark ()) #define NM_TYPE_WIFI_ERROR (nm_wifi_error_get_type ()) -typedef struct SupplicantStateTask { - NMDeviceWifi *self; - guint32 new_state; - guint32 old_state; - gboolean mgr_task; - guint source_id; -} SupplicantStateTask; - typedef struct Supplicant { NMSupplicantManager *mgr; NMSupplicantInterface *iface; /* signal handler ids */ - guint mgr_state_id; guint iface_error_id; guint iface_state_id; guint iface_scanned_ap_id; guint iface_scan_request_result_id; guint iface_scan_results_id; - guint iface_con_state_id; guint iface_notify_scanning_id; /* Timeouts and idles */ guint iface_con_error_cb_id; guint con_timeout_id; - - GSList *mgr_tasks; - GSList *iface_tasks; } Supplicant; struct _NMDeviceWifiPrivate { @@ -199,15 +186,10 @@ static void cleanup_association_attempt (NMDeviceWifi * self, static void remove_supplicant_timeouts (NMDeviceWifi *self); -static void supplicant_iface_state_cb (NMSupplicantInterface * iface, +static void supplicant_iface_state_cb (NMSupplicantInterface *iface, guint32 new_state, guint32 old_state, - NMDeviceWifi *self); - -static void supplicant_iface_connection_state_cb (NMSupplicantInterface * iface, - guint32 new_state, - guint32 old_state, - NMDeviceWifi *self); + gpointer user_data); static void supplicant_iface_scanned_ap_cb (NMSupplicantInterface * iface, GHashTable *properties, @@ -221,11 +203,6 @@ static void supplicant_iface_scan_results_cb (NMSupplicantInterface * iface, guint32 num_bssids, NMDeviceWifi * self); -static void supplicant_mgr_state_cb (NMSupplicantInterface * iface, - guint32 new_state, - guint32 old_state, - NMDeviceWifi *self); - static void supplicant_iface_notify_scanning_cb (NMSupplicantInterface * iface, GParamSpec * pspec, NMDeviceWifi * self); @@ -625,10 +602,7 @@ constructor (GType type, /* Connect to the supplicant manager */ priv->supplicant.mgr = nm_supplicant_manager_get (); - priv->supplicant.mgr_state_id = g_signal_connect (priv->supplicant.mgr, - "state", - G_CALLBACK (supplicant_mgr_state_cb), - self); + g_assert (priv->supplicant.mgr); /* The ipw2x00 drivers don't integrate with the kernel rfkill subsystem until * 2.6.33. Thus all our nice libgudev magic is useless. So we get to poll. @@ -657,17 +631,13 @@ static gboolean supplicant_interface_acquire (NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - guint id, mgr_state; + guint id; g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (priv->supplicant.mgr != NULL, FALSE); /* interface already acquired? */ g_return_val_if_fail (priv->supplicant.iface == NULL, TRUE); - mgr_state = nm_supplicant_manager_get_state (priv->supplicant.mgr); - g_return_val_if_fail (mgr_state == NM_SUPPLICANT_MANAGER_STATE_IDLE, FALSE); - - priv->supplicant.iface = nm_supplicant_manager_get_iface (priv->supplicant.mgr, + priv->supplicant.iface = nm_supplicant_manager_iface_get (priv->supplicant.mgr, nm_device_get_iface (NM_DEVICE (self)), TRUE); if (priv->supplicant.iface == NULL) { @@ -700,12 +670,6 @@ supplicant_interface_acquire (NMDeviceWifi *self) self); priv->supplicant.iface_scan_results_id = id; - id = g_signal_connect (priv->supplicant.iface, - "connection-state", - G_CALLBACK (supplicant_iface_connection_state_cb), - self); - priv->supplicant.iface_con_state_id = id; - id = g_signal_connect (priv->supplicant.iface, "notify::scanning", G_CALLBACK (supplicant_iface_notify_scanning_cb), @@ -715,30 +679,6 @@ supplicant_interface_acquire (NMDeviceWifi *self) return TRUE; } -static void -finish_supplicant_task (SupplicantStateTask *task, gboolean remove_source) -{ - NMDeviceWifi *self = task->self; - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - /* idle/timeout handlers should pass FALSE for remove_source, since they - * will tell glib to remove their source from the mainloop by returning - * FALSE when they exit. When called from this NMDevice's dispose handler, - * remove_source should be TRUE to cancel all outstanding idle/timeout - * handlers asynchronously. - */ - if (task->source_id && remove_source) - g_source_remove (task->source_id); - - if (task->mgr_task) - priv->supplicant.mgr_tasks = g_slist_remove (priv->supplicant.mgr_tasks, task); - else - priv->supplicant.iface_tasks = g_slist_remove (priv->supplicant.iface_tasks, task); - - memset (task, 0, sizeof (SupplicantStateTask)); - g_slice_free (SupplicantStateTask, task); -} - static void remove_supplicant_interface_error_handler (NMDeviceWifi *self) { @@ -776,10 +716,6 @@ supplicant_interface_release (NMDeviceWifi *self) remove_supplicant_interface_error_handler (self); - /* Clean up all pending supplicant interface state idle tasks */ - while (priv->supplicant.iface_tasks) - finish_supplicant_task ((SupplicantStateTask *) priv->supplicant.iface_tasks->data, TRUE); - if (priv->supplicant.iface_state_id > 0) { g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_state_id); priv->supplicant.iface_state_id = 0; @@ -800,11 +736,6 @@ supplicant_interface_release (NMDeviceWifi *self) priv->supplicant.iface_scan_results_id = 0; } - if (priv->supplicant.iface_con_state_id > 0) { - g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_con_state_id); - priv->supplicant.iface_con_state_id = 0; - } - if (priv->supplicant.iface_notify_scanning_id > 0) { g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_notify_scanning_id); priv->supplicant.iface_notify_scanning_id = 0; @@ -814,7 +745,7 @@ supplicant_interface_release (NMDeviceWifi *self) /* Tell the supplicant to disconnect from the current AP */ nm_supplicant_interface_disconnect (priv->supplicant.iface); - nm_supplicant_manager_release_iface (priv->supplicant.mgr, priv->supplicant.iface); + nm_supplicant_manager_iface_release (priv->supplicant.mgr, priv->supplicant.iface); priv->supplicant.iface = NULL; } } @@ -1837,11 +1768,11 @@ scanning_allowed (NMDeviceWifi *self) } /* Don't scan if the supplicant is busy */ - sup_state = nm_supplicant_interface_get_connection_state (priv->supplicant.iface); - if ( sup_state == NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATING - || sup_state == NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATED - || sup_state == NM_SUPPLICANT_INTERFACE_CON_STATE_4WAY_HANDSHAKE - || sup_state == NM_SUPPLICANT_INTERFACE_CON_STATE_GROUP_HANDSHAKE + sup_state = nm_supplicant_interface_get_state (priv->supplicant.iface); + if ( sup_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING + || sup_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED + || sup_state == NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE + || sup_state == NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE || nm_supplicant_interface_get_scanning (priv->supplicant.iface)) return FALSE; @@ -2441,253 +2372,97 @@ time_out: return FALSE; } -static gboolean -schedule_state_handler (NMDeviceWifi *self, - GSourceFunc handler, - guint32 new_state, - guint32 old_state, - gboolean mgr_task) +static void +supplicant_iface_state_cb (NMSupplicantInterface *iface, + guint32 new_state, + guint32 old_state, + gpointer user_data) { - NMDeviceWifiPrivate *priv; - SupplicantStateTask *task; - - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (handler != NULL, FALSE); + NMDeviceWifi *self = NM_DEVICE_WIFI (user_data); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + NMDevice *device = NM_DEVICE (self); + NMDeviceState devstate; + gboolean scanning; if (new_state == old_state) - return TRUE; + return; - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + nm_log_info (LOGD_DEVICE | LOGD_WIFI, + "(%s): supplicant interface state: %s -> %s", + nm_device_get_iface (device), + nm_supplicant_interface_state_to_string (old_state), + nm_supplicant_interface_state_to_string (new_state)); - task = g_slice_new0 (SupplicantStateTask); - if (!task) { - nm_log_err (LOGD_WIFI, "Not enough memory to process supplicant manager state change."); - return FALSE; - } + devstate = nm_device_get_state (device); + scanning = nm_supplicant_interface_get_scanning (iface); - task->self = self; - task->new_state = new_state; - task->old_state = old_state; - task->mgr_task = mgr_task; - - task->source_id = g_idle_add (handler, task); - if (mgr_task) - priv->supplicant.mgr_tasks = g_slist_append (priv->supplicant.mgr_tasks, task); - else - priv->supplicant.iface_tasks = g_slist_append (priv->supplicant.iface_tasks, task); - - return TRUE; -} - -static gboolean -supplicant_iface_state_cb_handler (gpointer user_data) -{ - SupplicantStateTask *task = (SupplicantStateTask *) user_data; - NMDeviceWifi *self; - NMDeviceWifiPrivate *priv; - - g_return_val_if_fail (task != NULL, FALSE); - - self = task->self; - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - nm_log_info (LOGD_WIFI, "(%s): supplicant interface state: %s -> %s", - nm_device_get_iface (NM_DEVICE (self)), - nm_supplicant_interface_state_to_string (task->old_state), - nm_supplicant_interface_state_to_string (task->new_state)); - - if (task->new_state == NM_SUPPLICANT_INTERFACE_STATE_READY) { + switch (new_state) { + case NM_SUPPLICANT_INTERFACE_STATE_READY: priv->scan_interval = SCAN_INTERVAL_MIN; /* 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_is_available (NM_DEVICE (self))) { - nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_DISCONNECTED, + if ((devstate == NM_DEVICE_STATE_UNAVAILABLE) && nm_device_is_available (device)) { + nm_device_state_changed (device, + NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE); } - nm_log_dbg (LOGD_WIFI_SCAN, "(%s): supplicant ready, requesting initial scan", - nm_device_get_iface (NM_DEVICE (self))); + nm_log_dbg (LOGD_WIFI_SCAN, + "(%s): supplicant ready, requesting initial scan", + nm_device_get_iface (device)); /* Request a scan to get latest results */ cancel_pending_scan (self); request_wireless_scan (self); - } else if (task->new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) { - cleanup_association_attempt (self, FALSE); - supplicant_interface_release (self); - nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_UNAVAILABLE, - NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); - } - - finish_supplicant_task (task, FALSE); - return FALSE; -} - - -static void -supplicant_iface_state_cb (NMSupplicantInterface * iface, - guint32 new_state, - guint32 old_state, - NMDeviceWifi *self) -{ - g_return_if_fail (self != NULL); - - schedule_state_handler (self, - supplicant_iface_state_cb_handler, - new_state, - old_state, - FALSE); -} - - -static gboolean -supplicant_iface_connection_state_cb_handler (gpointer user_data) -{ - SupplicantStateTask *task = (SupplicantStateTask *) user_data; - NMDeviceWifi *self = task->self; - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - NMDevice *dev = NM_DEVICE (self); - gboolean scanning; - - if (!nm_device_get_act_request (dev)) { - /* The device is not activating or already activated; do nothing. */ - goto out; - } - - nm_log_info (LOGD_WIFI, "(%s): supplicant connection state: %s -> %s", - nm_device_get_iface (dev), - nm_supplicant_interface_connection_state_to_string (task->old_state), - nm_supplicant_interface_connection_state_to_string (task->new_state)); - - scanning = nm_supplicant_interface_get_scanning (priv->supplicant.iface); - - if (task->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED) { + break; + case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED: remove_supplicant_interface_error_handler (self); remove_supplicant_timeouts (self); /* If this is the initial association during device activation, * schedule the next activation stage. */ - if (nm_device_get_state (dev) == NM_DEVICE_STATE_CONFIG) { + if (devstate == NM_DEVICE_STATE_CONFIG) { NMAccessPoint *ap = nm_device_wifi_get_activation_ap (self); - const GByteArray * ssid = nm_ap_get_ssid (ap); + const GByteArray *ssid = nm_ap_get_ssid (ap); nm_log_info (LOGD_DEVICE | LOGD_WIFI, "Activation (%s/wireless) Stage 2 of 5 (Device Configure) " "successful. Connected to wireless network '%s'.", - nm_device_get_iface (dev), + nm_device_get_iface (device), ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)"); - nm_device_activate_schedule_stage3_ip_config_start (dev); + nm_device_activate_schedule_stage3_ip_config_start (device); } - } else if (task->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED) { - if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED || nm_device_is_activating (dev)) { + break; + case NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED: + if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) { /* Start the link timeout so we allow some time for reauthentication, * use a longer timeout if we are scanning since some cards take a * while to scan. */ if (!priv->link_timeout_id) { priv->link_timeout_id = g_timeout_add_seconds (scanning ? 30 : 15, - link_timeout_cb, self); + link_timeout_cb, self); } } + break; + case NM_SUPPLICANT_INTERFACE_STATE_DOWN: + cleanup_association_attempt (self, FALSE); + supplicant_interface_release (self); + nm_device_state_changed (device, + NM_DEVICE_STATE_UNAVAILABLE, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + break; + default: + break; } -out: /* Signal scanning state changes */ - if ( task->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING - || task->old_state == NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING) + if ( new_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING + || old_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING) g_object_notify (G_OBJECT (self), "scanning"); - - finish_supplicant_task (task, FALSE); - return FALSE; -} - - -static void -supplicant_iface_connection_state_cb (NMSupplicantInterface * iface, - guint32 new_state, - guint32 old_state, - NMDeviceWifi *self) -{ - g_return_if_fail (self != NULL); - - schedule_state_handler (self, - supplicant_iface_connection_state_cb_handler, - new_state, - old_state, - FALSE); -} - - -static gboolean -supplicant_mgr_state_cb_handler (gpointer user_data) -{ - SupplicantStateTask *task = (SupplicantStateTask *) user_data; - NMDeviceWifi *self; - NMDeviceWifiPrivate *priv; - NMDevice *dev; - NMDeviceState dev_state; - - g_return_val_if_fail (task != NULL, FALSE); - - self = task->self; - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - dev = NM_DEVICE (self); - - nm_log_info (LOGD_WIFI, "(%s): supplicant manager state: %s -> %s", - nm_device_get_iface (NM_DEVICE (self)), - nm_supplicant_manager_state_to_string (task->old_state), - nm_supplicant_manager_state_to_string (task->new_state)); - - /* If the supplicant went away, release the supplicant interface */ - if (task->new_state == NM_SUPPLICANT_MANAGER_STATE_DOWN) { - if (priv->supplicant.iface) { - cleanup_association_attempt (self, FALSE); - supplicant_interface_release (self); - } - - if (nm_device_get_state (dev) > NM_DEVICE_STATE_UNAVAILABLE) { - nm_device_state_changed (dev, NM_DEVICE_STATE_UNAVAILABLE, - NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); - } - } else if (task->new_state == NM_SUPPLICANT_MANAGER_STATE_IDLE) { - dev_state = nm_device_get_state (dev); - if ( priv->enabled - && !priv->supplicant.iface - && (dev_state >= NM_DEVICE_STATE_UNAVAILABLE) - && (nm_device_get_firmware_missing (NM_DEVICE (self)) == FALSE)) { - /* request a supplicant interface from the supplicant manager */ - supplicant_interface_acquire (self); - - /* if wireless is enabled and we have a supplicant interface, - * we can transition to the DISCONNECTED state. - */ - if (priv->supplicant.iface) { - nm_device_state_changed (dev, NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_NONE); - } - } - } - - finish_supplicant_task (task, FALSE); - return FALSE; -} - -static void -supplicant_mgr_state_cb (NMSupplicantInterface * iface, - guint32 new_state, - guint32 old_state, - NMDeviceWifi *self) -{ - g_return_if_fail (self != NULL); - - schedule_state_handler (self, - supplicant_mgr_state_cb_handler, - new_state, - old_state, - TRUE); } struct iface_con_error_cb_data { @@ -3845,20 +3620,9 @@ dispose (GObject *object) priv->periodic_source_id = 0; } - /* Clean up all pending supplicant tasks */ - while (priv->supplicant.iface_tasks) - finish_supplicant_task ((SupplicantStateTask *) priv->supplicant.iface_tasks->data, TRUE); - while (priv->supplicant.mgr_tasks) - finish_supplicant_task ((SupplicantStateTask *) priv->supplicant.mgr_tasks->data, TRUE); - cleanup_association_attempt (self, TRUE); supplicant_interface_release (self); - if (priv->supplicant.mgr_state_id) { - g_signal_handler_disconnect (priv->supplicant.mgr, priv->supplicant.mgr_state_id); - priv->supplicant.mgr_state_id = 0; - } - if (priv->supplicant.mgr) { g_object_unref (priv->supplicant.mgr); priv->supplicant.mgr = NULL; diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c index 3c3fe52f84..20cce6de5c 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -47,15 +47,6 @@ G_DEFINE_TYPE (NMSupplicantInterface, nm_supplicant_interface, G_TYPE_OBJECT) NM_TYPE_SUPPLICANT_INTERFACE, \ NMSupplicantInterfacePrivate)) -static void nm_supplicant_interface_start (NMSupplicantInterface *self); - -static void nm_supplicant_interface_add_to_supplicant (NMSupplicantInterface *self, - gboolean get_only); - -static void nm_supplicant_interface_set_state (NMSupplicantInterface *self, - guint32 new_state); - - /* Signals */ enum { STATE, /* change in the interface's state */ @@ -63,7 +54,6 @@ enum { SCANNED_AP, /* interface saw a new access point from a scan */ SCAN_REQ_RESULT, /* result of a wireless scan request */ SCAN_RESULTS, /* scan results returned from supplicant */ - CONNECTION_STATE, /* link state of the device's connection */ CONNECTION_ERROR, /* an error occurred during a connection request */ LAST_SIGNAL }; @@ -74,16 +64,14 @@ static guint signals[LAST_SIGNAL] = { 0 }; enum { PROP_0 = 0, PROP_STATE, - PROP_CONNECTION_STATE, PROP_SCANNING, LAST_PROP }; -typedef struct -{ +typedef struct { NMSupplicantManager * smgr; - gulong smgr_state_sig_handler; + gulong smgr_running_id; NMDBusManager * dbus_mgr; char * dev; gboolean is_wireless; @@ -93,9 +81,9 @@ typedef struct NMCallStore * assoc_pcalls; NMCallStore * other_pcalls; - guint32 con_state; gboolean scanning; + DBusGProxy * wpas_proxy; DBusGProxy * iface_proxy; DBusGProxy * net_proxy; @@ -186,28 +174,6 @@ nm_supplicant_info_destroy (gpointer user_data) } } -static void -try_remove_iface (DBusGConnection *g_connection, - const char *path) -{ - DBusGProxy *proxy; - - g_return_if_fail (g_connection != NULL); - g_return_if_fail (path != NULL); - - proxy = dbus_g_proxy_new_for_name (g_connection, - WPAS_DBUS_SERVICE, - WPAS_DBUS_PATH, - WPAS_DBUS_INTERFACE); - if (!proxy) - return; - - dbus_g_proxy_call_no_reply (proxy, "removeInterface", - DBUS_TYPE_G_OBJECT_PATH, path, - G_TYPE_INVALID); - g_object_unref (proxy); -} - static void emit_error_helper (NMSupplicantInterface *self, GError *err) @@ -344,50 +310,80 @@ wpas_iface_query_scan_results (DBusGProxy *proxy, gpointer user_data) } static guint32 -wpas_state_string_to_enum (const char * str_state) +wpas_state_string_to_enum (const char *str_state) { - guint32 enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED; + guint32 enum_state = NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED; if (!strcmp (str_state, "DISCONNECTED")) - enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED; + enum_state = NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED; else if (!strcmp (str_state, "INACTIVE")) - enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_INACTIVE; + enum_state = NM_SUPPLICANT_INTERFACE_STATE_INACTIVE; else if (!strcmp (str_state, "SCANNING")) - enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING; + enum_state = NM_SUPPLICANT_INTERFACE_STATE_SCANNING; else if (!strcmp (str_state, "ASSOCIATING")) - enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATING; + enum_state = NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING; else if (!strcmp (str_state, "ASSOCIATED")) - enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATED; + enum_state = NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED; else if (!strcmp (str_state, "4WAY_HANDSHAKE")) - enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_4WAY_HANDSHAKE; + enum_state = NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE; else if (!strcmp (str_state, "GROUP_HANDSHAKE")) - enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_GROUP_HANDSHAKE; + enum_state = NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE; else if (!strcmp (str_state, "COMPLETED")) - enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED; + enum_state = NM_SUPPLICANT_INTERFACE_STATE_COMPLETED; return enum_state; } +static void +set_state (NMSupplicantInterface *self, guint32 new_state) +{ + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + guint32 old_state = priv->state; + + g_return_if_fail (new_state < NM_SUPPLICANT_INTERFACE_STATE_LAST); + + if (new_state == priv->state) + return; + + /* DOWN is a terminal state */ + g_return_if_fail (priv->state != NM_SUPPLICANT_INTERFACE_STATE_DOWN); + + /* Cannot regress to READY or INIT from higher states */ + if (priv->state <= NM_SUPPLICANT_INTERFACE_STATE_READY) + g_return_if_fail (new_state > priv->state); + + if (new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) { + /* Cancel all pending calls when going down */ + cancel_all_callbacks (priv->other_pcalls); + cancel_all_callbacks (priv->assoc_pcalls); + + /* Disconnect supplicant manager state listeners since we're done */ + if (priv->smgr_running_id) { + g_signal_handler_disconnect (priv->smgr, priv->smgr_running_id); + priv->smgr_running_id = 0; + } + } + + priv->state = new_state; + g_signal_emit (self, signals[STATE], 0, priv->state, old_state); +} + +/* Supplicant state signal handler */ static void wpas_iface_handle_state_change (DBusGProxy *proxy, const char *str_new_state, const char *str_old_state, gpointer user_data) { - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (user_data); - guint32 old_state, enum_new_state; - - enum_new_state = wpas_state_string_to_enum (str_new_state); - old_state = priv->con_state; - priv->con_state = enum_new_state; - if (priv->con_state != old_state) - g_signal_emit (user_data, signals[CONNECTION_STATE], 0, priv->con_state, old_state); + set_state (NM_SUPPLICANT_INTERFACE (user_data), + wpas_state_string_to_enum (str_new_state)); } - +/* Explicit state request reply handler */ static void iface_state_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { + NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; GError *err = NULL; char *state_str = NULL; @@ -397,12 +393,8 @@ iface_state_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) nm_log_warn (LOGD_SUPPLICANT, "could not get interface state: %s.", err->message); g_error_free (err); } else { - NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); - - priv->con_state = wpas_state_string_to_enum (state_str); + set_state (info->interface, wpas_state_string_to_enum (state_str)); g_free (state_str); - nm_supplicant_interface_set_state (info->interface, NM_SUPPLICANT_INTERFACE_STATE_READY); } } @@ -479,225 +471,181 @@ nm_supplicant_interface_get_scanning (NMSupplicantInterface *self) priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); if (priv->scanning) return TRUE; - if (priv->con_state == NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING) + if (priv->state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING) return TRUE; return FALSE; } static void -nm_supplicant_interface_add_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) +interface_add_done (NMSupplicantInterface *self, char *path) +{ + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + + nm_log_dbg (LOGD_SUPPLICANT, "(%s): interface added to supplicant", priv->dev); + + priv->object_path = path; + + priv->iface_proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), + WPAS_DBUS_SERVICE, + path, + WPAS_DBUS_IFACE_INTERFACE); + + dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_STRING, + G_TYPE_NONE, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_INVALID); + dbus_g_proxy_add_signal (priv->iface_proxy, "StateChange", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->iface_proxy, "StateChange", + G_CALLBACK (wpas_iface_handle_state_change), + self, + NULL); + + dbus_g_proxy_add_signal (priv->iface_proxy, "ScanResultsAvailable", G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->iface_proxy, "ScanResultsAvailable", + G_CALLBACK (wpas_iface_query_scan_results), + self, + NULL); + + dbus_g_proxy_add_signal (priv->iface_proxy, "Scanning", G_TYPE_BOOLEAN, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->iface_proxy, "Scanning", + G_CALLBACK (wpas_iface_handle_scanning), + self, + NULL); + + /* Interface added to the supplicant; get its initial state. */ + wpas_iface_get_state (self); + wpas_iface_get_scanning (self); + + set_state (self, NM_SUPPLICANT_INTERFACE_STATE_READY); +} + +static void +interface_get_cb (DBusGProxy *proxy, + DBusGProxyCall *call_id, + gpointer user_data) { NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); - GError *err = NULL; + GError *error = NULL; char *path = NULL; - if (!dbus_g_proxy_end_call (proxy, call_id, &err, - DBUS_TYPE_G_OBJECT_PATH, &path, - G_TYPE_INVALID)) { - - if (dbus_g_error_has_name (err, WPAS_ERROR_INVALID_IFACE)) { - /* Interface not added, try to add it */ - nm_supplicant_interface_add_to_supplicant (info->interface, FALSE); - } else if (dbus_g_error_has_name (err, WPAS_ERROR_EXISTS_ERROR)) { - /* Interface already added, just try to get the interface */ - nm_supplicant_interface_add_to_supplicant (info->interface, TRUE); - } else { - nm_log_err (LOGD_SUPPLICANT, "(%s): error getting interface: %s", - priv->dev, err->message); - } - - g_error_free (err); + if (dbus_g_proxy_end_call (proxy, call_id, &error, + DBUS_TYPE_G_OBJECT_PATH, &path, + G_TYPE_INVALID)) { + interface_add_done (info->interface, path); } else { - nm_log_dbg (LOGD_SUPPLICANT, "(%s): interface added to supplicant", priv->dev); - - priv->object_path = path; - - priv->iface_proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), - WPAS_DBUS_SERVICE, - path, - WPAS_DBUS_IFACE_INTERFACE); - - dbus_g_proxy_add_signal (priv->iface_proxy, "ScanResultsAvailable", G_TYPE_INVALID); - - dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_STRING, - G_TYPE_NONE, - G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_INVALID); - - dbus_g_proxy_add_signal (priv->iface_proxy, "StateChange", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); - - dbus_g_proxy_connect_signal (priv->iface_proxy, "ScanResultsAvailable", - G_CALLBACK (wpas_iface_query_scan_results), - info->interface, - NULL); - - dbus_g_proxy_connect_signal (priv->iface_proxy, "StateChange", - G_CALLBACK (wpas_iface_handle_state_change), - info->interface, - NULL); - - dbus_g_proxy_add_signal (priv->iface_proxy, "Scanning", G_TYPE_BOOLEAN, G_TYPE_INVALID); - - dbus_g_proxy_connect_signal (priv->iface_proxy, "Scanning", - G_CALLBACK (wpas_iface_handle_scanning), - info->interface, - NULL); - - /* Interface added to the supplicant; get its initial state. */ - wpas_iface_get_state (info->interface); - wpas_iface_get_scanning (info->interface); + nm_log_err (LOGD_SUPPLICANT, "(%s): error adding interface: %s", + priv->dev, error->message); + g_clear_error (&error); } } static void -nm_supplicant_interface_add_to_supplicant (NMSupplicantInterface * self, - gboolean get_only) +interface_get (NMSupplicantInterface *self) { NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); NMSupplicantInfo *info; - DBusGProxy *proxy; DBusGProxyCall *call; - proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), - WPAS_DBUS_SERVICE, - WPAS_DBUS_PATH, - WPAS_DBUS_INTERFACE); - info = nm_supplicant_info_new (self, proxy, priv->other_pcalls); - - if (get_only) { - call = dbus_g_proxy_begin_call (proxy, "getInterface", - nm_supplicant_interface_add_cb, - info, - nm_supplicant_info_destroy, - G_TYPE_STRING, priv->dev, - G_TYPE_INVALID); - } else { - GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal); - GValue *driver; - - driver = g_new0 (GValue, 1); - g_value_init (driver, G_TYPE_STRING); - g_value_set_string (driver, priv->is_wireless ? "wext" : "wired"); - g_hash_table_insert (hash, "driver", driver); - - call = dbus_g_proxy_begin_call (proxy, "addInterface", - nm_supplicant_interface_add_cb, - info, - nm_supplicant_info_destroy, - G_TYPE_STRING, priv->dev, - DBUS_TYPE_G_MAP_OF_VARIANT, hash, - G_TYPE_INVALID); - - g_value_unset (driver); - g_free (driver); - g_hash_table_destroy (hash); - } - - g_object_unref (proxy); - + info = nm_supplicant_info_new (self, priv->wpas_proxy, priv->other_pcalls); + call = dbus_g_proxy_begin_call (priv->wpas_proxy, "getInterface", + interface_get_cb, + info, + nm_supplicant_info_destroy, + G_TYPE_STRING, priv->dev, + G_TYPE_INVALID); nm_supplicant_info_set_call (info, call); } static void -nm_supplicant_interface_start (NMSupplicantInterface * self) +interface_add_cb (DBusGProxy *proxy, + DBusGProxyCall *call_id, + gpointer user_data) +{ + NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface); + GError *error = NULL; + char *path = NULL; + + if (dbus_g_proxy_end_call (proxy, call_id, &error, + DBUS_TYPE_G_OBJECT_PATH, &path, + G_TYPE_INVALID)) { + interface_add_done (info->interface, path); + } else { + if (dbus_g_error_has_name (error, WPAS_ERROR_EXISTS_ERROR)) { + /* Interface already added, just get its object path */ + interface_get (info->interface); + } else { + nm_log_err (LOGD_SUPPLICANT, "(%s): error adding interface: %s", + priv->dev, error->message); + } + g_clear_error (&error); + } +} + +static void +interface_add (NMSupplicantInterface * self, gboolean is_wireless) { NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - guint32 state; + DBusGProxyCall *call; + NMSupplicantInfo *info; + GHashTable *hash; + GValue *driver; /* Can only start the interface from INIT state */ g_return_if_fail (priv->state == NM_SUPPLICANT_INTERFACE_STATE_INIT); nm_log_dbg (LOGD_SUPPLICANT, "(%s): adding interface to supplicant", priv->dev); - state = nm_supplicant_manager_get_state (priv->smgr); - if (state == NM_SUPPLICANT_MANAGER_STATE_IDLE) { - nm_supplicant_interface_set_state (self, NM_SUPPLICANT_INTERFACE_STATE_STARTING); - nm_supplicant_interface_add_to_supplicant (self, FALSE); - } else if (state == NM_SUPPLICANT_MANAGER_STATE_DOWN) { - /* Don't do anything; wait for signal from supplicant manager - * that its state has changed. + /* Try to add the interface to the supplicant. If the supplicant isn't + * running, this will start it via D-Bus activation and return the response + * when the supplicant has started. + */ + + info = nm_supplicant_info_new (self, priv->wpas_proxy, priv->other_pcalls); + + driver = g_new0 (GValue, 1); + g_value_init (driver, G_TYPE_STRING); + g_value_set_string (driver, is_wireless ? "wext" : "wired"); + + hash = g_hash_table_new (g_str_hash, g_str_equal); + g_hash_table_insert (hash, "driver", driver); + + call = dbus_g_proxy_begin_call (priv->wpas_proxy, "addInterface", + interface_add_cb, + info, + nm_supplicant_info_destroy, + G_TYPE_STRING, priv->dev, + DBUS_TYPE_G_MAP_OF_VARIANT, hash, + G_TYPE_INVALID); + + g_hash_table_destroy (hash); + g_value_unset (driver); + g_free (driver); + + nm_supplicant_info_set_call (info, call); +} + +static void +smgr_running_cb (NMSupplicantManager *smgr, + GParamSpec *pspec, + gpointer user_data) +{ + NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (user_data); + + if (nm_supplicant_manager_running (smgr)) { + /* This can happen if the supplicant couldn't be activated but + * for some reason was started after the activation failure. */ - } else - nm_log_warn (LOGD_SUPPLICANT, "Unknown supplicant manager state!"); -} - -static void -nm_supplicant_interface_handle_supplicant_manager_idle_state (NMSupplicantInterface * self) -{ - switch (NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->state) { - case NM_SUPPLICANT_INTERFACE_STATE_INIT: - /* Move to STARTING state when supplicant is ready */ - nm_supplicant_interface_start (self); - break; - case NM_SUPPLICANT_INTERFACE_STATE_STARTING: - /* Don't do anything here, though we should never hit this */ - break; - case NM_SUPPLICANT_INTERFACE_STATE_READY: - /* Don't do anything here, though we should never hit this */ - break; - case NM_SUPPLICANT_INTERFACE_STATE_DOWN: - /* Don't do anything here; interface can't get out of DOWN state */ - break; - default: - nm_log_warn (LOGD_SUPPLICANT, "Unknown supplicant interface state!"); - break; + if (priv->state == NM_SUPPLICANT_INTERFACE_STATE_INIT) + interface_add (self, priv->is_wireless); + } else { + /* The supplicant stopped; so we must tear down the interface */ + set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN); } } - -static void -nm_supplicant_interface_set_state (NMSupplicantInterface * self, - guint32 new_state) -{ - NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - guint32 old_state; - - g_return_if_fail (new_state < NM_SUPPLICANT_INTERFACE_STATE_LAST); - - if (new_state == priv->state) - return; - - old_state = priv->state; - if (new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) { - /* If the interface is transitioning to DOWN and there's are - * in-progress pending calls, cancel them. - */ - cancel_all_callbacks (priv->other_pcalls); - cancel_all_callbacks (priv->assoc_pcalls); - } - - priv->state = new_state; - g_signal_emit (self, signals[STATE], 0, priv->state, old_state); -} - -static void -smgr_state_changed (NMSupplicantManager *smgr, - guint32 new_state, - guint32 old_state, - gpointer user_data) -{ - NMSupplicantInterface * self = NM_SUPPLICANT_INTERFACE (user_data); - - switch (new_state) { - case NM_SUPPLICANT_MANAGER_STATE_DOWN: - /* The supplicant went away, likely the connection to it is also - * gone. Therefore, this interface must move to the DOWN state - * and be disposed of. - */ - nm_supplicant_interface_set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN); - break; - case NM_SUPPLICANT_MANAGER_STATE_IDLE: - /* Handle the supplicant now being available. */ - nm_supplicant_interface_handle_supplicant_manager_idle_state (self); - break; - default: - nm_log_warn (LOGD_SUPPLICANT, "Unknown supplicant manager state!"); - break; - } -} - - static void remove_network_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { @@ -742,16 +690,13 @@ nm_supplicant_interface_disconnect (NMSupplicantInterface * self) if (!priv->iface_proxy) return; - /* Don't try to disconnect if the supplicant interface is already - * disconnected. - */ - if (priv->con_state == NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED - || priv->con_state == NM_SUPPLICANT_INTERFACE_CON_STATE_INACTIVE) { + /* Don't try to disconnect if the supplicant interface is already disconnected */ + if ( priv->state == NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED + || priv->state == NM_SUPPLICANT_INTERFACE_STATE_INACTIVE) { if (priv->net_proxy) { g_object_unref (priv->net_proxy); priv->net_proxy = NULL; } - return; } @@ -1011,14 +956,6 @@ nm_supplicant_interface_set_config (NMSupplicantInterface * self, return call != NULL; } -const char * -nm_supplicant_interface_get_device (NMSupplicantInterface * self) -{ - g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NULL); - - return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->dev; -} - static void scan_request_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { @@ -1067,24 +1004,30 @@ nm_supplicant_interface_get_state (NMSupplicantInterface * self) return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->state; } -guint32 -nm_supplicant_interface_get_connection_state (NMSupplicantInterface * self) -{ - g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED); - - return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->con_state; -} - const char * nm_supplicant_interface_state_to_string (guint32 state) { switch (state) { case NM_SUPPLICANT_INTERFACE_STATE_INIT: return "init"; - case NM_SUPPLICANT_INTERFACE_STATE_STARTING: - return "starting"; case NM_SUPPLICANT_INTERFACE_STATE_READY: return "ready"; + case NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED: + return "disconnected"; + case NM_SUPPLICANT_INTERFACE_STATE_INACTIVE: + return "inactive"; + case NM_SUPPLICANT_INTERFACE_STATE_SCANNING: + return "scanning"; + case NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING: + return "associating"; + case NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED: + return "associated"; + case NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE: + return "4-way handshake"; + case NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE: + return "group handshake"; + case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED: + return "completed"; case NM_SUPPLICANT_INTERFACE_STATE_DOWN: return "down"; default: @@ -1094,35 +1037,28 @@ nm_supplicant_interface_state_to_string (guint32 state) } const char * -nm_supplicant_interface_connection_state_to_string (guint32 state) +nm_supplicant_interface_get_device (NMSupplicantInterface * self) { - switch (state) { - case NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED: - return "disconnected"; - case NM_SUPPLICANT_INTERFACE_CON_STATE_INACTIVE: - return "inactive"; - case NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING: - return "scanning"; - case NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATING: - return "associating"; - case NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATED: - return "associated"; - case NM_SUPPLICANT_INTERFACE_CON_STATE_4WAY_HANDSHAKE: - return "4-way handshake"; - case NM_SUPPLICANT_INTERFACE_CON_STATE_GROUP_HANDSHAKE: - return "group handshake"; - case NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED: - return "completed"; - default: - break; - } - return "unknown"; + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NULL); + + return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->dev; +} + +const char * +nm_supplicant_interface_get_object_path (NMSupplicantInterface *self) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NULL); + + return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->object_path; } const char * nm_supplicant_interface_get_ifname (NMSupplicantInterface *self) { g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), FALSE); return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->dev; } @@ -1147,14 +1083,15 @@ nm_supplicant_interface_new (NMSupplicantManager *smgr, priv->smgr = g_object_ref (smgr); id = g_signal_connect (priv->smgr, - "state", - G_CALLBACK (smgr_state_changed), + "notify::" NM_SUPPLICANT_MANAGER_RUNNING, + G_CALLBACK (smgr_running_cb), self); - priv->smgr_state_sig_handler = id; + priv->smgr_running_id = id; priv->dev = g_strdup (ifname); priv->is_wireless = is_wireless; - nm_supplicant_interface_start (self); + + interface_add (self, priv->is_wireless); } return self; @@ -1164,12 +1101,18 @@ static void nm_supplicant_interface_init (NMSupplicantInterface * self) { NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + DBusGConnection *bus; priv->state = NM_SUPPLICANT_INTERFACE_STATE_INIT; - priv->con_state = NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED; priv->assoc_pcalls = nm_call_store_new (); priv->other_pcalls = nm_call_store_new (); priv->dbus_mgr = nm_dbus_manager_get (); + + bus = nm_dbus_manager_get_connection (priv->dbus_mgr); + priv->wpas_proxy = dbus_g_proxy_new_for_name (bus, + WPAS_DBUS_SERVICE, + WPAS_DBUS_PATH, + WPAS_DBUS_INTERFACE); } static void @@ -1195,9 +1138,6 @@ get_property (GObject *object, case PROP_STATE: g_value_set_uint (value, NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object)->state); break; - case PROP_CONNECTION_STATE: - g_value_set_uint (value, NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object)->con_state); - break; case PROP_SCANNING: g_value_set_boolean (value, NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object)->scanning); break; @@ -1211,7 +1151,6 @@ static void dispose (GObject *object) { NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object); - guint32 sm_state; if (priv->disposed) { G_OBJECT_CLASS (nm_supplicant_interface_parent_class)->dispose (object); @@ -1219,27 +1158,21 @@ dispose (GObject *object) } priv->disposed = TRUE; - /* Ask wpa_supplicant to remove this interface */ - sm_state = nm_supplicant_manager_get_state (priv->smgr); - if (sm_state == NM_SUPPLICANT_MANAGER_STATE_IDLE) { - if (priv->object_path) { - try_remove_iface (nm_dbus_manager_get_connection (priv->dbus_mgr), - priv->object_path); - } - } - if (priv->iface_proxy) g_object_unref (priv->iface_proxy); if (priv->net_proxy) g_object_unref (priv->net_proxy); + if (priv->wpas_proxy) + g_object_unref (priv->wpas_proxy); + if (priv->scan_results_timeout) g_source_remove (priv->scan_results_timeout); if (priv->smgr) { - g_signal_handler_disconnect (priv->smgr, - priv->smgr_state_sig_handler); + if (priv->smgr_running_id) + g_signal_handler_disconnect (priv->smgr, priv->smgr_running_id); g_object_unref (priv->smgr); } @@ -1338,15 +1271,6 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass) g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); - signals[CONNECTION_STATE] = - g_signal_new ("connection-state", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantInterfaceClass, connection_state), - NULL, NULL, - _nm_marshal_VOID__UINT_UINT, - G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); - signals[CONNECTION_ERROR] = g_signal_new ("connection-error", G_OBJECT_CLASS_TYPE (object_class), diff --git a/src/supplicant-manager/nm-supplicant-interface.h b/src/supplicant-manager/nm-supplicant-interface.h index 3e56f4efaf..d6e4a55969 100644 --- a/src/supplicant-manager/nm-supplicant-interface.h +++ b/src/supplicant-manager/nm-supplicant-interface.h @@ -26,47 +26,25 @@ #include #include "nm-supplicant-types.h" -G_BEGIN_DECLS - /* * Supplicant interface states - * The states are linear, ie INIT -> READY -> DOWN and state may only be - * changed in one direction. If an interface reaches the DOWN state, it - * cannot be re-initialized; it must be torn down and a new one created. - * - * INIT: interface has been created, but cannot be used yet; it is waiting - * for pending requests of the supplicant to complete. - * READY: interface is ready for use - * DOWN: interface has been removed or has otherwise been made invalid; it - * must be torn down. - * - * Note: LAST is an invalid state and only used for boundary checking. + * A mix of wpa_supplicant interface states and internal states. */ enum { NM_SUPPLICANT_INTERFACE_STATE_INIT = 0, - NM_SUPPLICANT_INTERFACE_STATE_STARTING, NM_SUPPLICANT_INTERFACE_STATE_READY, + NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED, + NM_SUPPLICANT_INTERFACE_STATE_INACTIVE, + NM_SUPPLICANT_INTERFACE_STATE_SCANNING, + NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING, + NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED, + NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE, + NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE, + NM_SUPPLICANT_INTERFACE_STATE_COMPLETED, NM_SUPPLICANT_INTERFACE_STATE_DOWN, NM_SUPPLICANT_INTERFACE_STATE_LAST }; - -/* - * Supplicant interface connection states - * The wpa_supplicant state for the connection. - */ -enum { - NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED = 0, - NM_SUPPLICANT_INTERFACE_CON_STATE_INACTIVE, - NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING, - NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATING, - NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATED, - NM_SUPPLICANT_INTERFACE_CON_STATE_4WAY_HANDSHAKE, - NM_SUPPLICANT_INTERFACE_CON_STATE_GROUP_HANDSHAKE, - NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED, - NM_SUPPLICANT_INTERFACE_CON_STATE_LAST -}; - #define NM_TYPE_SUPPLICANT_INTERFACE (nm_supplicant_interface_get_type ()) #define NM_SUPPLICANT_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SUPPLICANT_INTERFACE, NMSupplicantInterface)) #define NM_SUPPLICANT_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SUPPLICANT_INTERFACE, NMSupplicantInterfaceClass)) @@ -103,11 +81,6 @@ typedef struct { void (*scan_results) (NMSupplicantInterface * iface, guint num_bssids); - /* link state of the device's connection */ - void (*connection_state) (NMSupplicantInterface * iface, - guint32 new_state, - guint32 old_state); - /* an error occurred during a connection request */ void (*connection_error) (NMSupplicantInterface * iface, const char * name, @@ -128,20 +101,16 @@ void nm_supplicant_interface_disconnect (NMSupplicantInterface * iface); const char * nm_supplicant_interface_get_device (NMSupplicantInterface * iface); +const char *nm_supplicant_interface_get_object_path (NMSupplicantInterface * iface); + gboolean nm_supplicant_interface_request_scan (NMSupplicantInterface * self); guint32 nm_supplicant_interface_get_state (NMSupplicantInterface * self); -guint32 nm_supplicant_interface_get_connection_state (NMSupplicantInterface * self); - const char *nm_supplicant_interface_state_to_string (guint32 state); -const char *nm_supplicant_interface_connection_state_to_string (guint32 state); - gboolean nm_supplicant_interface_get_scanning (NMSupplicantInterface *self); const char *nm_supplicant_interface_get_ifname (NMSupplicantInterface *self); -G_END_DECLS - #endif /* NM_SUPPLICANT_INTERFACE_H */ diff --git a/src/supplicant-manager/nm-supplicant-manager.c b/src/supplicant-manager/nm-supplicant-manager.c index 56a5e58d63..c139ec6fef 100644 --- a/src/supplicant-manager/nm-supplicant-manager.c +++ b/src/supplicant-manager/nm-supplicant-manager.c @@ -26,19 +26,7 @@ #include "nm-supplicant-manager.h" #include "nm-supplicant-interface.h" #include "nm-dbus-manager.h" -#include "nm-marshal.h" #include "nm-logging.h" -#include "nm-glib-compat.h" - -#define SUPPLICANT_POKE_INTERVAL 120 - -typedef struct { - NMDBusManager * dbus_mgr; - guint32 state; - GHashTable * ifaces; - gboolean disposed; - guint poke_id; -} NMSupplicantManagerPrivate; #define NM_SUPPLICANT_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ NM_TYPE_SUPPLICANT_MANAGER, \ @@ -46,84 +34,26 @@ typedef struct { G_DEFINE_TYPE (NMSupplicantManager, nm_supplicant_manager, G_TYPE_OBJECT) -/* Signals */ +/* Properties */ enum { - STATE, /* change in the manager's state */ - LAST_SIGNAL + PROP_0 = 0, + PROP_RUNNING, + LAST_PROP }; -static guint signals[LAST_SIGNAL] = { 0 }; + +typedef struct { + NMDBusManager * dbus_mgr; + guint name_owner_id; + DBusGProxy * proxy; + gboolean running; + GHashTable * ifaces; + gboolean disposed; +} NMSupplicantManagerPrivate; /********************************************************************/ -static gboolean -poke_supplicant_cb (gpointer user_data) -{ - NMSupplicantManager *self = NM_SUPPLICANT_MANAGER (user_data); - NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self); - DBusGConnection *g_connection; - DBusGProxy *proxy; - const char *tmp = "ignoreme"; - - g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr); - proxy = dbus_g_proxy_new_for_name (g_connection, - WPAS_DBUS_SERVICE, - WPAS_DBUS_PATH, - WPAS_DBUS_INTERFACE); - if (!proxy) { - nm_log_warn (LOGD_SUPPLICANT, "Error: could not init wpa_supplicant proxy"); - goto out; - } - - nm_log_info (LOGD_SUPPLICANT, "Trying to start the supplicant..."); - dbus_g_proxy_call_no_reply (proxy, "getInterface", G_TYPE_STRING, tmp, G_TYPE_INVALID); - g_object_unref (proxy); - -out: - /* Reschedule the poke */ - priv->poke_id = g_timeout_add_seconds (SUPPLICANT_POKE_INTERVAL, - poke_supplicant_cb, - (gpointer) self); - - return FALSE; -} - -guint32 -nm_supplicant_manager_get_state (NMSupplicantManager * self) -{ - g_return_val_if_fail (NM_IS_SUPPLICANT_MANAGER (self), FALSE); - - return NM_SUPPLICANT_MANAGER_GET_PRIVATE (self)->state; -} - -static void -set_state (NMSupplicantManager *self, guint32 new_state) -{ - NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self); - guint32 old_state; - - if (new_state != priv->state) { - old_state = priv->state; - priv->state = new_state; - g_signal_emit (self, signals[STATE], 0, priv->state, old_state); - } -} - -static gboolean -startup (NMSupplicantManager * self) -{ - gboolean running; - - /* FIXME: convert to pending call */ - running = nm_dbus_manager_name_has_owner (NM_SUPPLICANT_MANAGER_GET_PRIVATE (self)->dbus_mgr, - WPAS_DBUS_SERVICE); - if (running) - set_state (self, NM_SUPPLICANT_MANAGER_STATE_IDLE); - - return running; -} - NMSupplicantInterface * -nm_supplicant_manager_get_iface (NMSupplicantManager * self, +nm_supplicant_manager_iface_get (NMSupplicantManager * self, const char *ifname, gboolean is_wireless) { @@ -149,34 +79,37 @@ nm_supplicant_manager_get_iface (NMSupplicantManager * self, } void -nm_supplicant_manager_release_iface (NMSupplicantManager *self, +nm_supplicant_manager_iface_release (NMSupplicantManager *self, NMSupplicantInterface *iface) { NMSupplicantManagerPrivate *priv; - const char *ifname; + const char *ifname, *op; g_return_if_fail (NM_IS_SUPPLICANT_MANAGER (self)); g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (iface)); priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self); + /* Ask wpa_supplicant to remove this interface */ + op = nm_supplicant_interface_get_object_path (iface); + if (priv->running && priv->proxy && op) { + dbus_g_proxy_call_no_reply (priv->proxy, "removeInterface", + DBUS_TYPE_G_OBJECT_PATH, op, + G_TYPE_INVALID); + } + ifname = nm_supplicant_interface_get_ifname (iface); g_assert (ifname); g_hash_table_remove (priv->ifaces, ifname); } -const char * -nm_supplicant_manager_state_to_string (guint32 state) +gboolean +nm_supplicant_manager_running (NMSupplicantManager *self) { - switch (state) { - case NM_SUPPLICANT_MANAGER_STATE_DOWN: - return "down"; - case NM_SUPPLICANT_MANAGER_STATE_IDLE: - return "idle"; - default: - break; - } - return "unknown"; + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (NM_IS_SUPPLICANT_MANAGER (self), FALSE); + + return NM_SUPPLICANT_MANAGER_GET_PRIVATE (self)->running; } static void @@ -186,34 +119,23 @@ name_owner_changed (NMDBusManager *dbus_mgr, const char *new_owner, gpointer user_data) { - NMSupplicantManager * self = (NMSupplicantManager *) user_data; + NMSupplicantManager *self = NM_SUPPLICANT_MANAGER (user_data); NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self); gboolean old_owner_good = (old_owner && strlen (old_owner)); gboolean new_owner_good = (new_owner && strlen (new_owner)); - /* Can't handle the signal if its not from the supplicant service */ + /* We only care about the supplicant here */ if (strcmp (WPAS_DBUS_SERVICE, name) != 0) return; if (!old_owner_good && new_owner_good) { - gboolean running; - - running = startup (self); - - if (running && priv->poke_id) { - g_source_remove (priv->poke_id); - priv->poke_id = 0; - } + nm_log_info (LOGD_SUPPLICANT, "wpa_supplicant started"); + priv->running = TRUE; + g_object_notify (G_OBJECT (self), NM_SUPPLICANT_MANAGER_RUNNING); } else if (old_owner_good && !new_owner_good) { - set_state (self, NM_SUPPLICANT_MANAGER_STATE_DOWN); - - if (priv->poke_id) - g_source_remove (priv->poke_id); - - /* Poke the supplicant so that it gets activated by dbus system bus - * activation. - */ - priv->poke_id = g_idle_add (poke_supplicant_cb, (gpointer) self); + nm_log_info (LOGD_SUPPLICANT, "wpa_supplicant stopped"); + priv->running = FALSE; + g_object_notify (G_OBJECT (self), NM_SUPPLICANT_MANAGER_RUNNING); } } @@ -237,24 +159,40 @@ static void nm_supplicant_manager_init (NMSupplicantManager * self) { NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self); - gboolean running; + DBusGConnection *bus; - priv->state = NM_SUPPLICANT_MANAGER_STATE_DOWN; priv->dbus_mgr = nm_dbus_manager_get (); - priv->poke_id = 0; + priv->name_owner_id = g_signal_connect (priv->dbus_mgr, + "name-owner-changed", + G_CALLBACK (name_owner_changed), + self); + priv->running = nm_dbus_manager_name_has_owner (priv->dbus_mgr, WPAS_DBUS_SERVICE); + + bus = nm_dbus_manager_get_connection (priv->dbus_mgr); + priv->proxy = dbus_g_proxy_new_for_name (bus, + WPAS_DBUS_SERVICE, + WPAS_DBUS_PATH, + WPAS_DBUS_INTERFACE); priv->ifaces = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); +} - running = startup (self); +static void +set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); +} - g_signal_connect (priv->dbus_mgr, - "name-owner-changed", - G_CALLBACK (name_owner_changed), - self); - - if (!running) { - /* Try to activate the supplicant */ - priv->poke_id = g_idle_add (poke_supplicant_cb, (gpointer) self); +static void +get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_RUNNING: + g_value_set_boolean (value, NM_SUPPLICANT_MANAGER_GET_PRIVATE (object)->running); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; } } @@ -263,22 +201,22 @@ dispose (GObject *object) { NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (object); - if (priv->disposed) { - G_OBJECT_CLASS (nm_supplicant_manager_parent_class)->dispose (object); - return; - } + if (priv->disposed) + goto out; priv->disposed = TRUE; - if (priv->poke_id) { - g_source_remove (priv->poke_id); - priv->poke_id = 0; - } - if (priv->dbus_mgr) { + if (priv->name_owner_id) + g_signal_handler_disconnect (priv->dbus_mgr, priv->name_owner_id); g_object_unref (G_OBJECT (priv->dbus_mgr)); - priv->dbus_mgr = NULL; } + g_hash_table_destroy (priv->ifaces); + + if (priv->proxy) + g_object_unref (priv->proxy); + +out: /* Chain up to the parent class */ G_OBJECT_CLASS (nm_supplicant_manager_parent_class)->dispose (object); } @@ -286,19 +224,19 @@ dispose (GObject *object) static void nm_supplicant_manager_class_init (NMSupplicantManagerClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (object_class, sizeof (NMSupplicantManagerPrivate)); + object_class->get_property = get_property; + object_class->set_property = set_property; object_class->dispose = dispose; - /* Signals */ - signals[STATE] = g_signal_new ("state", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMSupplicantManagerClass, state), - NULL, NULL, - _nm_marshal_VOID__UINT_UINT, - G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); + g_object_class_install_property (object_class, PROP_RUNNING, + g_param_spec_boolean (NM_SUPPLICANT_MANAGER_RUNNING, + "Running", + "Running", + FALSE, + G_PARAM_READABLE)); } diff --git a/src/supplicant-manager/nm-supplicant-manager.h b/src/supplicant-manager/nm-supplicant-manager.h index fef2a77444..ca3b643f57 100644 --- a/src/supplicant-manager/nm-supplicant-manager.h +++ b/src/supplicant-manager/nm-supplicant-manager.h @@ -33,23 +33,6 @@ G_BEGIN_DECLS -/* - * Supplicant manager states - * Either state may transition to the other state at any time. - * - * DOWN: supplicant manager has been created, but cannot be used; the supplicant - * is either not running or has not yet been fully initialized. - * IDLE: supplicant manager is ready for use - * - * Note: LAST is an invalid state and only used for boundary checking. - */ -enum { - NM_SUPPLICANT_MANAGER_STATE_DOWN = 0, - NM_SUPPLICANT_MANAGER_STATE_IDLE, - NM_SUPPLICANT_MANAGER_STATE_LAST -}; - - #define NM_TYPE_SUPPLICANT_MANAGER (nm_supplicant_manager_get_type ()) #define NM_SUPPLICANT_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SUPPLICANT_MANAGER, NMSupplicantManager)) #define NM_SUPPLICANT_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SUPPLICANT_MANAGER, NMSupplicantManagerClass)) @@ -57,6 +40,8 @@ enum { #define NM_IS_SUPPLICANT_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SUPPLICANT_MANAGER)) #define NM_SUPPLICANT_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SUPPLICANT_MANAGER, NMSupplicantManagerClass)) +#define NM_SUPPLICANT_MANAGER_RUNNING "running" + struct _NMSupplicantManager { GObject parent; @@ -65,24 +50,19 @@ struct _NMSupplicantManager typedef struct { GObjectClass parent; - - /* class members */ - void (* state) (NMSupplicantManager * mgr, guint32 new_state, guint32 old_state); } NMSupplicantManagerClass; GType nm_supplicant_manager_get_type (void); -NMSupplicantManager * nm_supplicant_manager_get (void); +NMSupplicantManager *nm_supplicant_manager_get (void); -guint32 nm_supplicant_manager_get_state (NMSupplicantManager * mgr); +NMSupplicantInterface *nm_supplicant_manager_iface_get (NMSupplicantManager *mgr, + const char *ifname, + gboolean is_wireless); -NMSupplicantInterface * nm_supplicant_manager_get_iface (NMSupplicantManager * mgr, - const char *ifname, - gboolean is_wireless); +void nm_supplicant_manager_iface_release (NMSupplicantManager *mgr, + NMSupplicantInterface *iface); -void nm_supplicant_manager_release_iface (NMSupplicantManager * mgr, - NMSupplicantInterface * iface); - -const char *nm_supplicant_manager_state_to_string (guint32 state); +gboolean nm_supplicant_manager_running (NMSupplicantManager *mgr); #endif /* NM_SUPPLICANT_MANAGER_H */ From 516ea8bf12a60db58ce7fe20bfae9b5b70af4172 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 6 Oct 2010 15:43:41 -0500 Subject: [PATCH 5/9] wifi: simplify supplicant interface signal handling --- src/nm-device-wifi.c | 52 +++++++++++++++----------------------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c index 44d5a12754..49529708b2 100644 --- a/src/nm-device-wifi.c +++ b/src/nm-device-wifi.c @@ -113,17 +113,14 @@ typedef enum { #define NM_WIFI_ERROR (nm_wifi_error_quark ()) #define NM_TYPE_WIFI_ERROR (nm_wifi_error_get_type ()) +#define SUP_SIG_ID_LEN 5 + typedef struct Supplicant { NMSupplicantManager *mgr; NMSupplicantInterface *iface; - /* signal handler ids */ + guint sig_ids[SUP_SIG_ID_LEN]; guint iface_error_id; - guint iface_state_id; - guint iface_scanned_ap_id; - guint iface_scan_request_result_id; - guint iface_scan_results_id; - guint iface_notify_scanning_id; /* Timeouts and idles */ guint iface_con_error_cb_id; @@ -631,7 +628,7 @@ static gboolean supplicant_interface_acquire (NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - guint id; + guint id, i = 0; g_return_val_if_fail (self != NULL, FALSE); /* interface already acquired? */ @@ -646,35 +643,37 @@ supplicant_interface_acquire (NMDeviceWifi *self) return FALSE; } + memset (priv->supplicant.sig_ids, 0, sizeof (priv->supplicant.sig_ids)); + id = g_signal_connect (priv->supplicant.iface, "state", G_CALLBACK (supplicant_iface_state_cb), self); - priv->supplicant.iface_state_id = id; + priv->supplicant.sig_ids[i++] = id; id = g_signal_connect (priv->supplicant.iface, "scanned-ap", G_CALLBACK (supplicant_iface_scanned_ap_cb), self); - priv->supplicant.iface_scanned_ap_id = id; + priv->supplicant.sig_ids[i++] = id; id = g_signal_connect (priv->supplicant.iface, "scan-req-result", G_CALLBACK (supplicant_iface_scan_request_result_cb), self); - priv->supplicant.iface_scan_request_result_id = id; + priv->supplicant.sig_ids[i++] = id; id = g_signal_connect (priv->supplicant.iface, "scan-results", G_CALLBACK (supplicant_iface_scan_results_cb), self); - priv->supplicant.iface_scan_results_id = id; + priv->supplicant.sig_ids[i++] = id; id = g_signal_connect (priv->supplicant.iface, "notify::scanning", G_CALLBACK (supplicant_iface_notify_scanning_cb), self); - priv->supplicant.iface_notify_scanning_id = id; + priv->supplicant.sig_ids[i++] = id; return TRUE; } @@ -702,6 +701,7 @@ static void supplicant_interface_release (NMDeviceWifi *self) { NMDeviceWifiPrivate *priv; + guint i; g_return_if_fail (self != NULL); @@ -716,30 +716,12 @@ supplicant_interface_release (NMDeviceWifi *self) remove_supplicant_interface_error_handler (self); - if (priv->supplicant.iface_state_id > 0) { - g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_state_id); - priv->supplicant.iface_state_id = 0; - } - - if (priv->supplicant.iface_scanned_ap_id > 0) { - g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_scanned_ap_id); - priv->supplicant.iface_scanned_ap_id = 0; - } - - if (priv->supplicant.iface_scan_request_result_id > 0) { - g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_scan_request_result_id); - priv->supplicant.iface_scan_request_result_id = 0; - } - - if (priv->supplicant.iface_scan_results_id > 0) { - g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_scan_results_id); - priv->supplicant.iface_scan_results_id = 0; - } - - if (priv->supplicant.iface_notify_scanning_id > 0) { - g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_notify_scanning_id); - priv->supplicant.iface_notify_scanning_id = 0; + /* Clear supplicant interface signal handlers */ + for (i = 0; i < SUP_SIG_ID_LEN; i++) { + if (priv->supplicant.sig_ids[i] > 0) + g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.sig_ids[i]); } + memset (priv->supplicant.sig_ids, 0, sizeof (priv->supplicant.sig_ids)); if (priv->supplicant.iface) { /* Tell the supplicant to disconnect from the current AP */ From 5858c6103e2d79e864f3cbb43601ec3dff7c0a74 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 11 Oct 2010 20:27:51 -0500 Subject: [PATCH 6/9] supplicant: make sure we remove the right interface It shouldn't ever happen that two interface objects for the same network interface are active at the same time, but make sure we yell if it does. --- src/supplicant-manager/nm-supplicant-manager.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/supplicant-manager/nm-supplicant-manager.c b/src/supplicant-manager/nm-supplicant-manager.c index c139ec6fef..35fbdb340d 100644 --- a/src/supplicant-manager/nm-supplicant-manager.c +++ b/src/supplicant-manager/nm-supplicant-manager.c @@ -88,8 +88,13 @@ nm_supplicant_manager_iface_release (NMSupplicantManager *self, g_return_if_fail (NM_IS_SUPPLICANT_MANAGER (self)); g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (iface)); + ifname = nm_supplicant_interface_get_ifname (iface); + g_assert (ifname); + priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self); + g_return_if_fail (g_hash_table_lookup (priv->ifaces, ifname) == iface); + /* Ask wpa_supplicant to remove this interface */ op = nm_supplicant_interface_get_object_path (iface); if (priv->running && priv->proxy && op) { @@ -98,8 +103,6 @@ nm_supplicant_manager_iface_release (NMSupplicantManager *self, G_TYPE_INVALID); } - ifname = nm_supplicant_interface_get_ifname (iface); - g_assert (ifname); g_hash_table_remove (priv->ifaces, ifname); } From 48e37de3a4de76a4146d4a716c315031de658e4a Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 11 Oct 2010 20:30:40 -0500 Subject: [PATCH 7/9] supplicant: prevent a race condition due to D-Bus activation interface_add() could get called from two places: by the wifi/eth device class when activating (which if the supplicant isn't yet running will D-Bus activate it) and from the NameOwnerChanged handler for the wpa_supplicant dbus service smgr_running_cb(). So if the supplicant wasn't running, nm_supplicant_interface_new() would call interface_add() to bring the supplicant to life via activation, then go on and create priv->iface_proxy. When the supplicant appeared and D-Bus sent the NameOwnerChanged, smgr_running_cb() would also call interface_add(), creating a second priv->iface_proxy. The first one got lost and lived after its parent NMSupplicantInterface was killed, and could still respond to signals over the bus. Prevent that by adding another state, STARTING, that indicates that we've already started talking to the supplicant. Also be extra paranoid about disconnecting signal handlers on the proxy. --- .../nm-supplicant-interface.c | 51 +++++++++++++++---- .../nm-supplicant-interface.h | 1 + 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c index 20cce6de5c..415c46d6a3 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -40,8 +40,17 @@ #define WPAS_ERROR_EXISTS_ERROR WPAS_DBUS_INTERFACE ".ExistsError" -G_DEFINE_TYPE (NMSupplicantInterface, nm_supplicant_interface, G_TYPE_OBJECT) +static void wpas_iface_handle_state_change (DBusGProxy *proxy, + const char *str_new_state, + const char *str_old_state, + gpointer user_data); +static void wpas_iface_handle_scanning (DBusGProxy *proxy, + gboolean scanning, + gpointer user_data); + + +G_DEFINE_TYPE (NMSupplicantInterface, nm_supplicant_interface, G_TYPE_OBJECT) #define NM_SUPPLICANT_INTERFACE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ NM_TYPE_SUPPLICANT_INTERFACE, \ @@ -362,6 +371,23 @@ set_state (NMSupplicantInterface *self, guint32 new_state) g_signal_handler_disconnect (priv->smgr, priv->smgr_running_id); priv->smgr_running_id = 0; } + + if (priv->iface_proxy) { + dbus_g_proxy_disconnect_signal (priv->iface_proxy, + "StateChange", + G_CALLBACK (wpas_iface_handle_state_change), + self); + + dbus_g_proxy_disconnect_signal (priv->iface_proxy, + "ScanResultsAvailable", + G_CALLBACK (wpas_iface_query_scan_results), + self); + + dbus_g_proxy_disconnect_signal (priv->iface_proxy, + "Scanning", + G_CALLBACK (wpas_iface_handle_scanning), + self); + } } priv->state = new_state; @@ -584,7 +610,7 @@ interface_add_cb (DBusGProxy *proxy, } static void -interface_add (NMSupplicantInterface * self, gboolean is_wireless) +interface_add (NMSupplicantInterface *self, gboolean is_wireless) { NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); DBusGProxyCall *call; @@ -597,6 +623,9 @@ interface_add (NMSupplicantInterface * self, gboolean is_wireless) nm_log_dbg (LOGD_SUPPLICANT, "(%s): adding interface to supplicant", priv->dev); + /* Move to starting to prevent double-calls of interface_add() */ + set_state (self, NM_SUPPLICANT_INTERFACE_STATE_STARTING); + /* Try to add the interface to the supplicant. If the supplicant isn't * running, this will start it via D-Bus activation and return the response * when the supplicant has started. @@ -1010,6 +1039,8 @@ nm_supplicant_interface_state_to_string (guint32 state) switch (state) { case NM_SUPPLICANT_INTERFACE_STATE_INIT: return "init"; + case NM_SUPPLICANT_INTERFACE_STATE_STARTING: + return "starting"; case NM_SUPPLICANT_INTERFACE_STATE_READY: return "ready"; case NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED: @@ -1158,6 +1189,13 @@ dispose (GObject *object) } priv->disposed = TRUE; + /* Cancel pending calls before unrefing the dbus manager */ + cancel_all_callbacks (priv->other_pcalls); + nm_call_store_destroy (priv->other_pcalls); + + cancel_all_callbacks (priv->assoc_pcalls); + nm_call_store_destroy (priv->assoc_pcalls); + if (priv->iface_proxy) g_object_unref (priv->iface_proxy); @@ -1178,13 +1216,6 @@ dispose (GObject *object) g_free (priv->dev); - /* Cancel pending calls before unrefing the dbus manager */ - cancel_all_callbacks (priv->other_pcalls); - nm_call_store_destroy (priv->other_pcalls); - - cancel_all_callbacks (priv->assoc_pcalls); - nm_call_store_destroy (priv->assoc_pcalls); - if (priv->dbus_mgr) g_object_unref (priv->dbus_mgr); @@ -1212,7 +1243,7 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass) g_object_class_install_property (object_class, PROP_STATE, g_param_spec_uint ("state", "State", - "State of the supplicant interface; INIT, READY, or DOWN", + "State of the supplicant interface", NM_SUPPLICANT_INTERFACE_STATE_INIT, NM_SUPPLICANT_INTERFACE_STATE_LAST - 1, NM_SUPPLICANT_INTERFACE_STATE_INIT, diff --git a/src/supplicant-manager/nm-supplicant-interface.h b/src/supplicant-manager/nm-supplicant-interface.h index d6e4a55969..8c51caa1d9 100644 --- a/src/supplicant-manager/nm-supplicant-interface.h +++ b/src/supplicant-manager/nm-supplicant-interface.h @@ -32,6 +32,7 @@ */ enum { NM_SUPPLICANT_INTERFACE_STATE_INIT = 0, + NM_SUPPLICANT_INTERFACE_STATE_STARTING, NM_SUPPLICANT_INTERFACE_STATE_READY, NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED, NM_SUPPLICANT_INTERFACE_STATE_INACTIVE, From 39e111e5ebbd3f70c41e8d901bab4a68ca171788 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 11 Oct 2010 20:35:54 -0500 Subject: [PATCH 8/9] supplicant: ignore unknown wpa_supplicant states Don't treat them as DISCONNECTED. --- .../nm-supplicant-interface.c | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c index 415c46d6a3..91da8c6a14 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -318,29 +318,27 @@ wpas_iface_query_scan_results (DBusGProxy *proxy, gpointer user_data) } } -static guint32 +static int wpas_state_string_to_enum (const char *str_state) { - guint32 enum_state = NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED; - if (!strcmp (str_state, "DISCONNECTED")) - enum_state = NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED; + return NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED; else if (!strcmp (str_state, "INACTIVE")) - enum_state = NM_SUPPLICANT_INTERFACE_STATE_INACTIVE; + return NM_SUPPLICANT_INTERFACE_STATE_INACTIVE; else if (!strcmp (str_state, "SCANNING")) - enum_state = NM_SUPPLICANT_INTERFACE_STATE_SCANNING; + return NM_SUPPLICANT_INTERFACE_STATE_SCANNING; else if (!strcmp (str_state, "ASSOCIATING")) - enum_state = NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING; + return NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING; else if (!strcmp (str_state, "ASSOCIATED")) - enum_state = NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED; + return NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED; else if (!strcmp (str_state, "4WAY_HANDSHAKE")) - enum_state = NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE; + return NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE; else if (!strcmp (str_state, "GROUP_HANDSHAKE")) - enum_state = NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE; + return NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE; else if (!strcmp (str_state, "COMPLETED")) - enum_state = NM_SUPPLICANT_INTERFACE_STATE_COMPLETED; + return NM_SUPPLICANT_INTERFACE_STATE_COMPLETED; - return enum_state; + return -1; } static void @@ -401,8 +399,11 @@ wpas_iface_handle_state_change (DBusGProxy *proxy, const char *str_old_state, gpointer user_data) { - set_state (NM_SUPPLICANT_INTERFACE (user_data), - wpas_state_string_to_enum (str_new_state)); + int enum_state = wpas_state_string_to_enum (str_new_state); + + g_return_if_fail (enum_state > 0); + + set_state (NM_SUPPLICANT_INTERFACE (user_data), (guint32) enum_state); } /* Explicit state request reply handler */ @@ -412,6 +413,7 @@ iface_state_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) NMSupplicantInfo *info = (NMSupplicantInfo *) user_data; GError *err = NULL; char *state_str = NULL; + int enum_state; if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_STRING, &state_str, @@ -419,7 +421,11 @@ iface_state_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) nm_log_warn (LOGD_SUPPLICANT, "could not get interface state: %s.", err->message); g_error_free (err); } else { - set_state (info->interface, wpas_state_string_to_enum (state_str)); + enum_state = wpas_state_string_to_enum (state_str); + g_warn_if_fail (enum_state > 0); + + if (enum_state > 0) + set_state (info->interface, (guint32) enum_state); g_free (state_str); } } From f532f41c022857768464e335865863c39caf5c7c Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 12 Oct 2010 14:18:42 -0500 Subject: [PATCH 9/9] supplicant: ratelimit supplicant activation If the supplicant dies a number of times within a short period of time, make it go sit in the corner for a bit instead of continuously trying to start it and have it die again. Instead of just exposing a "running" value, instead make a meta "available" value that's a combination of whether the supplicant is actually running plus whether we want to talk to it right now or not. --- .../nm-supplicant-interface.c | 32 +++--- .../nm-supplicant-interface.h | 3 +- .../nm-supplicant-manager.c | 99 ++++++++++++++++--- .../nm-supplicant-manager.h | 4 +- 4 files changed, 106 insertions(+), 32 deletions(-) diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c index 91da8c6a14..bad8f26634 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -80,7 +80,7 @@ enum { typedef struct { NMSupplicantManager * smgr; - gulong smgr_running_id; + gulong smgr_avail_id; NMDBusManager * dbus_mgr; char * dev; gboolean is_wireless; @@ -365,9 +365,9 @@ set_state (NMSupplicantInterface *self, guint32 new_state) cancel_all_callbacks (priv->assoc_pcalls); /* Disconnect supplicant manager state listeners since we're done */ - if (priv->smgr_running_id) { - g_signal_handler_disconnect (priv->smgr, priv->smgr_running_id); - priv->smgr_running_id = 0; + if (priv->smgr_avail_id) { + g_signal_handler_disconnect (priv->smgr, priv->smgr_avail_id); + priv->smgr_avail_id = 0; } if (priv->iface_proxy) { @@ -662,14 +662,14 @@ interface_add (NMSupplicantInterface *self, gboolean is_wireless) } static void -smgr_running_cb (NMSupplicantManager *smgr, - GParamSpec *pspec, - gpointer user_data) +smgr_avail_cb (NMSupplicantManager *smgr, + GParamSpec *pspec, + gpointer user_data) { NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (user_data); - if (nm_supplicant_manager_running (smgr)) { + if (nm_supplicant_manager_available (smgr)) { /* This can happen if the supplicant couldn't be activated but * for some reason was started after the activation failure. */ @@ -1105,7 +1105,8 @@ nm_supplicant_interface_get_ifname (NMSupplicantInterface *self) NMSupplicantInterface * nm_supplicant_interface_new (NMSupplicantManager *smgr, const char *ifname, - gboolean is_wireless) + gboolean is_wireless, + gboolean start_now) { NMSupplicantInterface *self; NMSupplicantInterfacePrivate *priv; @@ -1120,15 +1121,16 @@ nm_supplicant_interface_new (NMSupplicantManager *smgr, priv->smgr = g_object_ref (smgr); id = g_signal_connect (priv->smgr, - "notify::" NM_SUPPLICANT_MANAGER_RUNNING, - G_CALLBACK (smgr_running_cb), + "notify::" NM_SUPPLICANT_MANAGER_AVAILABLE, + G_CALLBACK (smgr_avail_cb), self); - priv->smgr_running_id = id; + priv->smgr_avail_id = id; priv->dev = g_strdup (ifname); priv->is_wireless = is_wireless; - interface_add (self, priv->is_wireless); + if (start_now) + interface_add (self, priv->is_wireless); } return self; @@ -1215,8 +1217,8 @@ dispose (GObject *object) g_source_remove (priv->scan_results_timeout); if (priv->smgr) { - if (priv->smgr_running_id) - g_signal_handler_disconnect (priv->smgr, priv->smgr_running_id); + if (priv->smgr_avail_id) + g_signal_handler_disconnect (priv->smgr, priv->smgr_avail_id); g_object_unref (priv->smgr); } diff --git a/src/supplicant-manager/nm-supplicant-interface.h b/src/supplicant-manager/nm-supplicant-interface.h index 8c51caa1d9..9471bd771b 100644 --- a/src/supplicant-manager/nm-supplicant-interface.h +++ b/src/supplicant-manager/nm-supplicant-interface.h @@ -93,7 +93,8 @@ GType nm_supplicant_interface_get_type (void); NMSupplicantInterface * nm_supplicant_interface_new (NMSupplicantManager * smgr, const char *ifname, - gboolean is_wireless); + gboolean is_wireless, + gboolean start_now); gboolean nm_supplicant_interface_set_config (NMSupplicantInterface * iface, NMSupplicantConfig * cfg); diff --git a/src/supplicant-manager/nm-supplicant-manager.c b/src/supplicant-manager/nm-supplicant-manager.c index 35fbdb340d..35ef749cb6 100644 --- a/src/supplicant-manager/nm-supplicant-manager.c +++ b/src/supplicant-manager/nm-supplicant-manager.c @@ -37,7 +37,7 @@ G_DEFINE_TYPE (NMSupplicantManager, nm_supplicant_manager, G_TYPE_OBJECT) /* Properties */ enum { PROP_0 = 0, - PROP_RUNNING, + PROP_AVAILABLE, LAST_PROP }; @@ -47,18 +47,27 @@ typedef struct { DBusGProxy * proxy; gboolean running; GHashTable * ifaces; + guint die_count_reset_id; + guint die_count; gboolean disposed; } NMSupplicantManagerPrivate; /********************************************************************/ +static inline gboolean +die_count_exceeded (guint32 count) +{ + return count > 2; +} + NMSupplicantInterface * nm_supplicant_manager_iface_get (NMSupplicantManager * self, const char *ifname, gboolean is_wireless) { NMSupplicantManagerPrivate *priv; - NMSupplicantInterface * iface = NULL; + NMSupplicantInterface *iface = NULL; + gboolean start_now; g_return_val_if_fail (NM_IS_SUPPLICANT_MANAGER (self), NULL); g_return_val_if_fail (ifname != NULL, NULL); @@ -67,8 +76,15 @@ nm_supplicant_manager_iface_get (NMSupplicantManager * self, iface = g_hash_table_lookup (priv->ifaces, ifname); if (!iface) { + /* If we're making the supplicant take a time out for a bit, don't + * let the supplicant interface start immediately, just let it hang + * around in INIT state until we're ready to talk to the supplicant + * again. + */ + start_now = !die_count_exceeded (priv->die_count); + nm_log_dbg (LOGD_SUPPLICANT, "(%s): creating new supplicant interface", ifname); - iface = nm_supplicant_interface_new (self, ifname, is_wireless); + iface = nm_supplicant_interface_new (self, ifname, is_wireless, start_now); if (iface) g_hash_table_insert (priv->ifaces, g_strdup (ifname), iface); } else { @@ -107,14 +123,51 @@ nm_supplicant_manager_iface_release (NMSupplicantManager *self, } gboolean -nm_supplicant_manager_running (NMSupplicantManager *self) +nm_supplicant_manager_available (NMSupplicantManager *self) { g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (NM_IS_SUPPLICANT_MANAGER (self), FALSE); + if (die_count_exceeded (NM_SUPPLICANT_MANAGER_GET_PRIVATE (self)->die_count)) + return FALSE; return NM_SUPPLICANT_MANAGER_GET_PRIVATE (self)->running; } +static void +set_running (NMSupplicantManager *self, gboolean now_running) +{ + NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self); + gboolean old_available = nm_supplicant_manager_available (self); + + priv->running = now_running; + if (old_available != nm_supplicant_manager_available (self)) + g_object_notify (G_OBJECT (self), NM_SUPPLICANT_MANAGER_AVAILABLE); +} + +static void +set_die_count (NMSupplicantManager *self, guint new_die_count) +{ + NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self); + gboolean old_available = nm_supplicant_manager_available (self); + + priv->die_count = new_die_count; + if (old_available != nm_supplicant_manager_available (self)) + g_object_notify (G_OBJECT (self), NM_SUPPLICANT_MANAGER_AVAILABLE); +} + +static gboolean +wpas_die_count_reset_cb (gpointer user_data) +{ + NMSupplicantManager *self = NM_SUPPLICANT_MANAGER (user_data); + NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self); + + /* Reset the die count back to zero, which allows use of the supplicant again */ + priv->die_count_reset_id = 0; + set_die_count (self, 0); + nm_log_info (LOGD_SUPPLICANT, "wpa_supplicant die count reset"); + return FALSE; +} + static void name_owner_changed (NMDBusManager *dbus_mgr, const char *name, @@ -133,12 +186,27 @@ name_owner_changed (NMDBusManager *dbus_mgr, if (!old_owner_good && new_owner_good) { nm_log_info (LOGD_SUPPLICANT, "wpa_supplicant started"); - priv->running = TRUE; - g_object_notify (G_OBJECT (self), NM_SUPPLICANT_MANAGER_RUNNING); + set_running (self, TRUE); } else if (old_owner_good && !new_owner_good) { nm_log_info (LOGD_SUPPLICANT, "wpa_supplicant stopped"); - priv->running = FALSE; - g_object_notify (G_OBJECT (self), NM_SUPPLICANT_MANAGER_RUNNING); + + /* Reschedule the die count reset timeout. Every time the supplicant + * dies we wait 10 seconds before resetting the counter. If the + * supplicant died more than twice before the timer is reset, then + * we don't try to talk to the supplicant for a while. + */ + if (priv->die_count_reset_id) + g_source_remove (priv->die_count_reset_id); + priv->die_count_reset_id = g_timeout_add_seconds (10, wpas_die_count_reset_cb, self); + set_die_count (self, priv->die_count + 1); + + if (die_count_exceeded (priv->die_count)) { + nm_log_info (LOGD_SUPPLICANT, + "wpa_supplicant die count %d; ignoring for 10 seconds", + priv->die_count); + } + + set_running (self, FALSE); } } @@ -190,8 +258,8 @@ static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { switch (prop_id) { - case PROP_RUNNING: - g_value_set_boolean (value, NM_SUPPLICANT_MANAGER_GET_PRIVATE (object)->running); + case PROP_AVAILABLE: + g_value_set_boolean (value, nm_supplicant_manager_available (NM_SUPPLICANT_MANAGER (object))); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -208,6 +276,9 @@ dispose (GObject *object) goto out; priv->disposed = TRUE; + if (priv->die_count_reset_id) + g_source_remove (priv->die_count_reset_id); + if (priv->dbus_mgr) { if (priv->name_owner_id) g_signal_handler_disconnect (priv->dbus_mgr, priv->name_owner_id); @@ -235,10 +306,10 @@ nm_supplicant_manager_class_init (NMSupplicantManagerClass *klass) object_class->set_property = set_property; object_class->dispose = dispose; - g_object_class_install_property (object_class, PROP_RUNNING, - g_param_spec_boolean (NM_SUPPLICANT_MANAGER_RUNNING, - "Running", - "Running", + g_object_class_install_property (object_class, PROP_AVAILABLE, + g_param_spec_boolean (NM_SUPPLICANT_MANAGER_AVAILABLE, + "Available", + "Available", FALSE, G_PARAM_READABLE)); } diff --git a/src/supplicant-manager/nm-supplicant-manager.h b/src/supplicant-manager/nm-supplicant-manager.h index ca3b643f57..e9c31a997b 100644 --- a/src/supplicant-manager/nm-supplicant-manager.h +++ b/src/supplicant-manager/nm-supplicant-manager.h @@ -40,7 +40,7 @@ G_BEGIN_DECLS #define NM_IS_SUPPLICANT_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SUPPLICANT_MANAGER)) #define NM_SUPPLICANT_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SUPPLICANT_MANAGER, NMSupplicantManagerClass)) -#define NM_SUPPLICANT_MANAGER_RUNNING "running" +#define NM_SUPPLICANT_MANAGER_AVAILABLE "available" struct _NMSupplicantManager { @@ -63,6 +63,6 @@ NMSupplicantInterface *nm_supplicant_manager_iface_get (NMSupplicantManager *mgr void nm_supplicant_manager_iface_release (NMSupplicantManager *mgr, NMSupplicantInterface *iface); -gboolean nm_supplicant_manager_running (NMSupplicantManager *mgr); +gboolean nm_supplicant_manager_available (NMSupplicantManager *mgr); #endif /* NM_SUPPLICANT_MANAGER_H */