about summary refs log tree commit diff
path: root/src/nm-connectivity.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nm-connectivity.c')
-rw-r--r--src/nm-connectivity.c69
1 files changed, 57 insertions, 12 deletions
diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c
index 8a324a5c..85bd70ae 100644
--- a/src/nm-connectivity.c
+++ b/src/nm-connectivity.c
@@ -44,7 +44,7 @@ typedef struct {
 
 #if WITH_CONCHECK
 	SoupSession *soup_session;
-	gboolean running;
+	guint pending_checks;
 	guint check_id;
 #endif
 
@@ -69,12 +69,33 @@ nm_connectivity_get_state (NMConnectivity *connectivity)
 	return NM_CONNECTIVITY_GET_PRIVATE (connectivity)->state;
 }
 
+static const char *
+state_name (NMConnectivityState state)
+{
+	switch (state) {
+	case NM_CONNECTIVITY_UNKNOWN:
+		return "UNKNOWN";
+	case NM_CONNECTIVITY_NONE:
+		return "NONE";
+	case NM_CONNECTIVITY_LIMITED:
+		return "LIMITED";
+	case NM_CONNECTIVITY_PORTAL:
+		return "PORTAL";
+	case NM_CONNECTIVITY_FULL:
+		return "FULL";
+	default:
+		return "???";
+	}
+}
+
 static void
 update_state (NMConnectivity *self, NMConnectivityState state)
 {
 	NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
 
 	if (priv->state != state) {
+		nm_log_dbg (LOGD_CONCHECK, "Connectivity state changed from %s to %s",
+		            state_name (priv->state), state_name (state));
 		priv->state = state;
 		g_object_notify (G_OBJECT (self), NM_CONNECTIVITY_STATE);
 	}
@@ -93,6 +114,7 @@ nm_connectivity_check_cb (SoupSession *session, SoupMessage *msg, gpointer user_
 	self = NM_CONNECTIVITY (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
 	g_object_unref (self);
 	priv = NM_CONNECTIVITY_GET_PRIVATE (self);
+	priv->pending_checks--;
 
 	if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) {
 		nm_log_info (LOGD_CONCHECK, "Connectivity check for uri '%s' failed with '%s'.",
@@ -124,10 +146,11 @@ nm_connectivity_check_cb (SoupSession *session, SoupMessage *msg, gpointer user_
 	}
 
  done:
+	update_state (self, new_state);
+
 	g_simple_async_result_set_op_res_gssize (simple, new_state);
 	g_simple_async_result_complete (simple);
-
-	update_state (self, new_state);
+	g_object_unref (simple);
 }
 
 static void
@@ -136,11 +159,9 @@ run_check_complete (GObject      *object,
                     gpointer      user_data)
 {
 	NMConnectivity *self = NM_CONNECTIVITY (object);
-	NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
 	GError *error = NULL;
 
 	nm_connectivity_check_finish (self, result, &error);
-	priv->running = FALSE;
 	if (error) {
 		nm_log_err (LOGD_CONCHECK, "Connectivity check failed: %s", error->message);
 		g_error_free (error);
@@ -151,14 +172,23 @@ static gboolean
 run_check (gpointer user_data)
 {
 	NMConnectivity *self = NM_CONNECTIVITY (user_data);
-	NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
 
 	nm_connectivity_check_async (self, run_check_complete, NULL);
-	priv->running = TRUE;
-	nm_log_dbg (LOGD_CONCHECK, "Connectivity check with uri '%s' started.", priv->uri);
-
 	return TRUE;
 }
+
+static gboolean
+idle_start_periodic_checks (gpointer user_data)
+{
+	NMConnectivity *self = user_data;
+	NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
+
+	priv->check_id = g_timeout_add_seconds (priv->interval, run_check, self);
+	if (!priv->pending_checks)
+		run_check (self);
+
+	return FALSE;
+}
 #endif
 
 void
@@ -167,12 +197,14 @@ nm_connectivity_set_online (NMConnectivity *self,
 {
 #if WITH_CONCHECK
 	NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
+#endif
 
+	nm_log_dbg (LOGD_CONCHECK, "nm_connectivity_set_online(%s)", online ? "TRUE" : "FALSE");
+
+#if WITH_CONCHECK
 	if (online && priv->uri && priv->interval) {
 		if (!priv->check_id)
-			priv->check_id = g_timeout_add_seconds (priv->interval, run_check, self);
-		if (!priv->running)
-			run_check (self);
+			priv->check_id = g_timeout_add (0, idle_start_periodic_checks, self);
 
 		return;
 	} else if (priv->check_id) {
@@ -201,6 +233,13 @@ nm_connectivity_check_async (NMConnectivity      *self,
 	g_return_if_fail (NM_IS_CONNECTIVITY (self));
 	priv = NM_CONNECTIVITY_GET_PRIVATE (self);
 
+#if WITH_CONCHECK
+	if (callback == run_check_complete)
+		nm_log_dbg (LOGD_CONCHECK, "Periodic connectivity check started with uri '%s'.", priv->uri);
+	else
+#endif
+		nm_log_dbg (LOGD_CONCHECK, "Connectivity check started with uri '%s'.", priv->uri);
+
 	simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
 	                                    nm_connectivity_check_async);
 
@@ -208,10 +247,13 @@ nm_connectivity_check_async (NMConnectivity      *self,
 	if (priv->uri && priv->interval) {
 		msg = soup_message_new ("GET", priv->uri);
 		soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT);
+		/* Disable HTTP/1.1 keepalive; the connection should not persist */
+		soup_message_headers_append (msg->request_headers, "Connection", "close");
 		soup_session_queue_message (priv->soup_session,
 		                            msg,
 		                            nm_connectivity_check_cb,
 		                            simple);
+		priv->pending_checks++;
 
 		return;
 	}
@@ -219,6 +261,7 @@ nm_connectivity_check_async (NMConnectivity      *self,
 
 	g_simple_async_result_set_op_res_gssize (simple, priv->state);
 	g_simple_async_result_complete_in_idle (simple);
+	g_object_unref (simple);
 }
 
 NMConnectivityState
@@ -291,6 +334,8 @@ set_property (GObject *object, guint property_id,
 				g_free (priv->uri);
 				priv->uri = NULL;
 			}
+			if (uri)
+				soup_uri_free (uri);
 		}
 #endif
 		break;