From 5937861ca75fd525950b3fa3c386e7fc659f74da Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 14 Dec 2011 13:41:57 -0600 Subject: [PATCH] core: fix up connectivity state checks We want to start the connectivity checks when any device gets activated, and stop them when all devices get deactivated. We also want to make sure it's running if a device gets deactivated but other devices are still active. If multiple devices are activated and if the default device gets deactivated, the other device may become the default device and we'll need a connectivity check for that device since we can't do per-device checks yet. Also, if connectivity checking is enabled at compile-time but not enabled at runtime, the connectivity bits should always report "connected" to preserve previous behavior, and this code makes it clearer how that is handled. --- src/nm-connectivity.c | 111 +++++++++++++++++++++++++----------------- src/nm-connectivity.h | 4 +- src/nm-manager.c | 21 +++++--- 3 files changed, 85 insertions(+), 51 deletions(-) diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c index ce5558b96f..67fd3a0d3b 100644 --- a/src/nm-connectivity.c +++ b/src/nm-connectivity.c @@ -71,6 +71,22 @@ nm_connectivity_get_connected (NMConnectivity *connectivity) return NM_CONNECTIVITY_GET_PRIVATE (connectivity)->connected; } +static void +update_connected (NMConnectivity *self, gboolean connected) +{ + NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self); + gboolean old_connected = priv->connected; + + if (priv->uri == NULL || priv->interval == 0) { + /* Default to connected if no checks are to be run */ + priv->connected = TRUE; + } else + priv->connected = connected; + + if (priv->connected != old_connected) + g_object_notify (G_OBJECT (self), NM_CONNECTIVITY_CONNECTED); +} + static void nm_connectivity_check_cb (SoupSession *session, SoupMessage *msg, gpointer user_data) { @@ -103,62 +119,74 @@ nm_connectivity_check_cb (SoupSession *session, SoupMessage *msg, gpointer user_ g_free (uri_string); /* update connectivity and emit signal */ - if (priv->connected != connected_new) { - priv->connected = connected_new; - g_object_notify (G_OBJECT (self), NM_CONNECTIVITY_CONNECTED); - } + update_connected (self, connected_new); priv->running = FALSE; g_object_notify (G_OBJECT (self), NM_CONNECTIVITY_RUNNING); } - -void -nm_connectivity_check (NMConnectivity *self) +static gboolean +run_check (gpointer user_data) { + NMConnectivity *self = NM_CONNECTIVITY (user_data); NMConnectivityPrivate *priv; SoupURI *soup_uri; SoupMessage *msg; - g_return_if_fail (NM_IS_CONNECTIVITY (self)); + g_return_val_if_fail (NM_IS_CONNECTIVITY (self), FALSE); priv = NM_CONNECTIVITY_GET_PRIVATE (self); - if (priv->running) - return; + /* check given url async */ + soup_uri = soup_uri_new (priv->uri); + if (soup_uri && SOUP_URI_VALID_FOR_HTTP (soup_uri)) { + msg = soup_message_new_from_uri ("GET", soup_uri); + soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT); + soup_session_queue_message (priv->soup_session, + msg, + nm_connectivity_check_cb, + self); - if (priv->uri) { - /* check given url async */ - soup_uri = soup_uri_new (priv->uri); - if (soup_uri && SOUP_URI_VALID_FOR_HTTP (soup_uri)) { - msg = soup_message_new_from_uri ("GET", soup_uri); - soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT); - soup_session_queue_message (priv->soup_session, - msg, - nm_connectivity_check_cb, - self); + priv->running = TRUE; + g_object_notify (G_OBJECT (self), NM_CONNECTIVITY_RUNNING); + nm_log_dbg (LOGD_CORE, "Connectivity check with uri '%s' started.", priv->uri); + } else + nm_log_err (LOGD_CORE, "Invalid uri '%s' for connectivity check.", priv->uri); - priv->running = TRUE; - g_object_notify (G_OBJECT (self), NM_CONNECTIVITY_RUNNING); - nm_log_dbg (LOGD_CORE, "Connectivity check with uri '%s' started.", priv->uri); - } else - nm_log_err (LOGD_CORE, "Invalid uri '%s' for connectivity check.", priv->uri); + if (soup_uri) + soup_uri_free (soup_uri); - if (soup_uri) - soup_uri_free (soup_uri); - } else { - /* No URI given - default is connected */ - if (!priv->connected) { - priv->connected = TRUE; - g_object_notify (G_OBJECT (self), NM_CONNECTIVITY_CONNECTED); - } - } + return TRUE; /* keep firing */ } -static gboolean -do_check (gpointer user_data) +void +nm_connectivity_start_check (NMConnectivity *self) { - nm_connectivity_check (NM_CONNECTIVITY (user_data)); - return TRUE; /* keep checking */ + NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self); + + if (!priv->uri || !priv->interval) { + nm_connectivity_stop_check (self); + return; + } + + if (priv->check_id == 0) + priv->check_id = g_timeout_add_seconds (priv->interval, run_check, self); + + /* Start an immediate check */ + if (priv->running == FALSE) + run_check (self); +} + +void +nm_connectivity_stop_check (NMConnectivity *self) +{ + NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self); + + if (priv->check_id) { + g_source_remove (priv->check_id); + priv->check_id = 0; + } + + update_connected (self, FALSE); } NMConnectivity * @@ -167,7 +195,6 @@ nm_connectivity_new (const gchar *check_uri, const gchar *check_response) { NMConnectivity *self; - NMConnectivityPrivate *priv; self = g_object_new (NM_TYPE_CONNECTIVITY, NM_CONNECTIVITY_URI, check_uri, @@ -175,11 +202,7 @@ nm_connectivity_new (const gchar *check_uri, NM_CONNECTIVITY_RESPONSE, check_response ? check_response : DEFAULT_RESPONSE, NULL); g_return_val_if_fail (self != NULL, NULL); - - /* Kick off a check if required */ - priv = NM_CONNECTIVITY_GET_PRIVATE (self); - if (priv->uri && priv->interval) - priv->check_id = g_timeout_add_seconds (priv->interval, do_check, self); + update_connected (self, FALSE); return self; } diff --git a/src/nm-connectivity.h b/src/nm-connectivity.h index 91854e1885..cecc66766d 100644 --- a/src/nm-connectivity.h +++ b/src/nm-connectivity.h @@ -57,7 +57,9 @@ NMConnectivity *nm_connectivity_new (const gchar *check_uri, guint check_interval, const gchar *check_response); -void nm_connectivity_check (NMConnectivity *connectivity); +void nm_connectivity_start_check (NMConnectivity *connectivity); + +void nm_connectivity_stop_check (NMConnectivity *connectivity); gboolean nm_connectivity_get_connected (NMConnectivity *connectivity); diff --git a/src/nm-manager.c b/src/nm-manager.c index 2c437e2f45..3e08cf30a6 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -470,7 +470,8 @@ manager_device_state_changed (NMDevice *device, NMDeviceStateReason reason, gpointer user_data) { - NMManager *manager = NM_MANAGER (user_data); + NMManager *self = NM_MANAGER (user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); switch (new_state) { case NM_DEVICE_STATE_UNMANAGED: @@ -478,18 +479,26 @@ manager_device_state_changed (NMDevice *device, case NM_DEVICE_STATE_DISCONNECTED: case NM_DEVICE_STATE_PREPARE: case NM_DEVICE_STATE_FAILED: - g_object_notify (G_OBJECT (manager), NM_MANAGER_ACTIVE_CONNECTIONS); + g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVE_CONNECTIONS); break; default: break; } - nm_manager_update_state (manager); + nm_manager_update_state (self); #if WITH_CONCHECK - /* trigger a connectivity check */ - if (new_state == NM_DEVICE_STATE_ACTIVATED || old_state == NM_DEVICE_STATE_ACTIVATED) - nm_connectivity_check (NM_MANAGER_GET_PRIVATE (manager)->connectivity); + if (priv->state >= NM_STATE_CONNECTED_LOCAL) { + if (old_state == NM_DEVICE_STATE_ACTIVATED || new_state == NM_DEVICE_STATE_ACTIVATED) { + /* Still connected, but a device activated or deactivated; make sure + * we still have connectivity on the other activated devices. + */ + nm_connectivity_start_check (priv->connectivity); + } + } else { + /* Cannot be connected if no devices are activated */ + nm_connectivity_stop_check (priv->connectivity); + } #endif }