core: connectivity check cleanups; check response headers too

Clean up some memleaks and fix some possible lifecycle issues
for strings.  Also add a short-circuit check using the HTTP
headers.
This commit is contained in:
Dan Williams 2011-12-05 14:48:47 -06:00
parent 854c2894c4
commit 7703170673

View file

@ -16,6 +16,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* *
* Copyright (C) 2011 Thomas Bechtold <thomasbechtold@jpberlin.de> * Copyright (C) 2011 Thomas Bechtold <thomasbechtold@jpberlin.de>
* Copyright (C) 2011 Dan Williams <dcbw@redhat.com>
*/ */
#include <config.h> #include <config.h>
@ -34,11 +35,11 @@ typedef struct {
/* indicates if a connectivity check is currently running */ /* indicates if a connectivity check is currently running */
gboolean check_running; gboolean check_running;
/* the uri to check */ /* the uri to check */
const gchar *check_uri; char *check_uri;
/* seconds when a check will be repeated */ /* seconds when a check will be repeated */
guint check_interval; guint check_interval;
/* the expected response for the connectivity check */ /* the expected response for the connectivity check */
const gchar *check_response; char *check_response;
/* indicates if the last connection check was successful */ /* indicates if the last connection check was successful */
gboolean connected; gboolean connected;
/* the source id for the periodic check */ /* the source id for the periodic check */
@ -90,26 +91,34 @@ nm_connectivity_check_cb (SoupSession *session, SoupMessage *msg, gpointer user_
NMConnectivity *connectivity; NMConnectivity *connectivity;
NMConnectivityPrivate *priv; NMConnectivityPrivate *priv;
SoupURI *soup_uri; SoupURI *soup_uri;
gboolean connected_new; gboolean connected_new = FALSE;
const char *nm_header;
char *uri_string;
g_return_if_fail (NM_IS_CONNECTIVITY (user_data)); g_return_if_fail (NM_IS_CONNECTIVITY (user_data));
connectivity = NM_CONNECTIVITY (user_data); connectivity = NM_CONNECTIVITY (user_data);
priv = NM_CONNECTIVITY_GET_PRIVATE (connectivity); priv = NM_CONNECTIVITY_GET_PRIVATE (connectivity);
soup_uri = soup_message_get_uri (msg); soup_uri = soup_message_get_uri (msg);
uri_string = soup_uri_to_string (soup_uri, FALSE);
/* check response */ /* Check headers; if we find the NM-specific one we're done */
if (msg->response_body->data && (g_str_has_prefix (msg->response_body->data, priv->check_response))) { nm_header = soup_message_headers_get_one (msg->response_headers, "X-NetworkManager-Status");
nm_log_dbg (LOGD_CORE, "Connectivity check for uri '%s' with expected response '%s' successful.", if (g_strcmp0 (nm_header, "online") == 0) {
soup_uri_to_string (soup_uri, FALSE), nm_log_dbg (LOGD_CORE, "Connectivity check for uri '%s' with Status header successful.", uri_string);
priv->check_response);
connected_new = TRUE; connected_new = TRUE;
} else { } else {
nm_log_dbg (LOGD_CORE, "Connectivity check for uri '%s' with expected response '%s' failed.", /* check response */
soup_uri_to_string (soup_uri, FALSE), if (msg->response_body->data && (g_str_has_prefix (msg->response_body->data, priv->check_response))) {
priv->check_response); nm_log_dbg (LOGD_CORE, "Connectivity check for uri '%s' with expected response '%s' successful.",
connected_new = FALSE; uri_string, priv->check_response);
connected_new = TRUE;
} else {
nm_log_dbg (LOGD_CORE, "Connectivity check for uri '%s' with expected response '%s' failed.",
uri_string, priv->check_response);
}
} }
g_free (uri_string);
/* update connectivity and emit signal */ /* update connectivity and emit signal */
if (priv->connected != connected_new) { if (priv->connected != connected_new) {
@ -128,34 +137,35 @@ nm_connectivity_check (NMConnectivity *connectivity)
{ {
NMConnectivityPrivate *priv; NMConnectivityPrivate *priv;
SoupURI *soup_uri; SoupURI *soup_uri;
SoupMessage *connectivity_check_msg; SoupMessage *msg;
g_return_if_fail (NM_IS_CONNECTIVITY (connectivity)); g_return_if_fail (NM_IS_CONNECTIVITY (connectivity));
priv = NM_CONNECTIVITY_GET_PRIVATE (connectivity); priv = NM_CONNECTIVITY_GET_PRIVATE (connectivity);
if (priv->check_running) return; if (priv->check_running)
return;
if (priv->check_uri if (priv->check_uri && priv->check_uri[0]) {
&& strlen (priv->check_uri)
&& priv->check_response
&& strlen (priv->check_response)) {
/* check given url async */ /* check given url async */
soup_uri = soup_uri_new (priv->check_uri); soup_uri = soup_uri_new (priv->check_uri);
if (soup_uri && SOUP_URI_VALID_FOR_HTTP (soup_uri)) { if (soup_uri && SOUP_URI_VALID_FOR_HTTP (soup_uri)) {
connectivity_check_msg = soup_message_new_from_uri ("GET", 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, soup_session_queue_message (priv->soup_session,
connectivity_check_msg, msg,
nm_connectivity_check_cb, nm_connectivity_check_cb,
connectivity); connectivity);
priv->check_running = TRUE; priv->check_running = TRUE;
g_object_notify (G_OBJECT (connectivity), NM_CONNECTIVITY_CHECK_RUNNING); g_object_notify (G_OBJECT (connectivity), NM_CONNECTIVITY_CHECK_RUNNING);
nm_log_dbg (LOGD_CORE, "connectivity check with uri '%s' started.", priv->check_uri); nm_log_dbg (LOGD_CORE, "Connectivity check with uri '%s' started.", priv->check_uri);
soup_uri_free (soup_uri);
} else } else
nm_log_err (LOGD_CORE, "Invalid uri '%s' for connectivity check.", priv->check_uri); nm_log_err (LOGD_CORE, "Invalid uri '%s' for connectivity check.", priv->check_uri);
if (soup_uri)
soup_uri_free (soup_uri);
} else { } else {
/* no uri/response given - default is connected so nm-manager can set NMState to GLOBAL */ /* no uri given - default is connected so nm-manager can set NMState to GLOBAL */
if (!priv->connected) { if (!priv->connected) {
priv->connected = TRUE; priv->connected = TRUE;
g_object_notify (G_OBJECT (connectivity), NM_CONNECTIVITY_CONNECTED); g_object_notify (G_OBJECT (connectivity), NM_CONNECTIVITY_CONNECTED);
@ -173,9 +183,12 @@ nm_connectivity_new (const gchar *check_uri,
NMConnectivity *connectivity = g_object_new (NM_TYPE_CONNECTIVITY, NULL); NMConnectivity *connectivity = g_object_new (NM_TYPE_CONNECTIVITY, NULL);
NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (connectivity); NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (connectivity);
priv->check_uri = check_uri; priv->check_uri = g_strdup (check_uri);
priv->check_interval = check_interval; priv->check_interval = check_interval;
priv->check_response = check_response; if (check_response)
priv->check_response = g_strdup (check_response);
else
priv->check_response = g_strdup ("NetworkManager is online"); /* NOT LOCALIZED */
if (check_uri && strlen (check_uri) && (check_interval > 0)) { if (check_uri && strlen (check_uri) && (check_interval > 0)) {
priv->check_interval_source_id = g_timeout_add_seconds (check_interval, priv->check_interval_source_id = g_timeout_add_seconds (check_interval,
@ -189,8 +202,8 @@ nm_connectivity_new (const gchar *check_uri,
static void static void
nm_connectivity_set_property (GObject *object, guint property_id, set_property (GObject *object, guint property_id,
const GValue *value, GParamSpec *pspec) const GValue *value, GParamSpec *pspec)
{ {
NMConnectivity *self = NM_CONNECTIVITY (object); NMConnectivity *self = NM_CONNECTIVITY (object);
NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self); NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
@ -200,13 +213,15 @@ nm_connectivity_set_property (GObject *object, guint property_id,
priv->check_running = g_value_get_boolean (value); priv->check_running = g_value_get_boolean (value);
break; break;
case PROP_CHECK_URI: case PROP_CHECK_URI:
priv->check_uri = g_value_get_string (value); g_free (priv->check_uri);
priv->check_uri = g_value_dup_string (value);
break; break;
case PROP_CHECK_INTERVAL: case PROP_CHECK_INTERVAL:
priv->check_interval = g_value_get_uint (value); priv->check_interval = g_value_get_uint (value);
break; break;
case PROP_CHECK_RESPONSE: case PROP_CHECK_RESPONSE:
priv->check_response = g_value_get_string (value); g_free (priv->check_response);
priv->check_response = g_value_dup_string (value);
break; break;
case PROP_CONNECTED: case PROP_CONNECTED:
priv->connected = g_value_get_boolean (value); priv->connected = g_value_get_boolean (value);
@ -218,8 +233,8 @@ nm_connectivity_set_property (GObject *object, guint property_id,
} }
static void static void
nm_connectivity_get_property (GObject *object, guint property_id, get_property (GObject *object, guint property_id,
GValue *value, GParamSpec *pspec) GValue *value, GParamSpec *pspec)
{ {
NMConnectivity *self = NM_CONNECTIVITY (object); NMConnectivity *self = NM_CONNECTIVITY (object);
NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self); NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
@ -229,13 +244,13 @@ nm_connectivity_get_property (GObject *object, guint property_id,
g_value_set_boolean (value, priv->check_running); g_value_set_boolean (value, priv->check_running);
break; break;
case PROP_CHECK_URI: case PROP_CHECK_URI:
g_value_set_static_string (value, priv->check_uri); g_value_set_string (value, priv->check_uri);
break; break;
case PROP_CHECK_INTERVAL: case PROP_CHECK_INTERVAL:
g_value_set_uint (value, priv->check_interval); g_value_set_uint (value, priv->check_interval);
break; break;
case PROP_CHECK_RESPONSE: case PROP_CHECK_RESPONSE:
g_value_set_static_string (value, priv->check_response); g_value_set_string (value, priv->check_response);
break; break;
case PROP_CONNECTED: case PROP_CONNECTED:
g_value_set_boolean (value, priv->connected); g_value_set_boolean (value, priv->connected);
@ -257,7 +272,7 @@ nm_connectivity_init (NMConnectivity *self)
static void static void
nm_connectivity_dispose (GObject *object) dispose (GObject *object)
{ {
NMConnectivity *connectivity = NM_CONNECTIVITY (object); NMConnectivity *connectivity = NM_CONNECTIVITY (object);
NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (connectivity); NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (connectivity);
@ -268,12 +283,8 @@ nm_connectivity_dispose (GObject *object)
priv->soup_session = NULL; priv->soup_session = NULL;
} }
priv->check_running = FALSE; g_free (priv->check_uri);
priv->connected = FALSE; g_free (priv->check_response);
priv->check_uri = NULL;
priv->check_interval = 0;
priv->check_response = NULL;
if (priv->check_interval_source_id > 0) { if (priv->check_interval_source_id > 0) {
g_warn_if_fail (g_source_remove (priv->check_interval_source_id) == TRUE); g_warn_if_fail (g_source_remove (priv->check_interval_source_id) == TRUE);
@ -289,9 +300,9 @@ nm_connectivity_class_init (NMConnectivityClass *klass)
g_type_class_add_private (klass, sizeof (NMConnectivityPrivate)); g_type_class_add_private (klass, sizeof (NMConnectivityPrivate));
/* virtual methods */ /* virtual methods */
object_class->set_property = nm_connectivity_set_property; object_class->set_property = set_property;
object_class->get_property = nm_connectivity_get_property; object_class->get_property = get_property;
object_class->dispose = nm_connectivity_dispose; object_class->dispose = dispose;
/* properties */ /* properties */
g_object_class_install_property g_object_class_install_property