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 */