[evolution-data-server] Add camel_network_service_can_reach_sync().
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Add camel_network_service_can_reach_sync().
- Date: Fri, 22 Nov 2013 22:16:31 +0000 (UTC)
commit c2f18ec8201d4ef001766094f333f7c0d4ff22cc
Author: Matthew Barnes <mbarnes redhat com>
Date: Fri Nov 22 16:16:32 2013 -0500
Add camel_network_service_can_reach_sync().
Just wrappers g_network_monitor_can_reach() using the service's own
GSocketConnectable, but also updates the "host-reachable" property.
External callers can use this to synchronously update the property,
in case they need an up-to-date result to make a decision.
Also adds equivalent asynchronous functions:
camel_network_service_can_reach()
camel_network_service_can_reach_finish()
camel/camel-network-service.c | 250 +++++++++++++++++++++++--------
camel/camel-network-service.h | 13 ++
docs/reference/camel/camel-sections.txt | 3 +
3 files changed, 202 insertions(+), 64 deletions(-)
---
diff --git a/camel/camel-network-service.c b/camel/camel-network-service.c
index 03855c0..f2a0e4c 100644
--- a/camel/camel-network-service.c
+++ b/camel/camel-network-service.c
@@ -395,6 +395,30 @@ network_service_client_event_cb (GSocketClient *client,
}
}
+static gboolean
+network_service_notify_host_reachable_cb (gpointer user_data)
+{
+ g_object_notify (G_OBJECT (user_data), "host-reachable");
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+network_service_notify_host_reachable (CamelNetworkService *service)
+{
+ CamelSession *session;
+
+ session = camel_service_ref_session (CAMEL_SERVICE (service));
+
+ camel_session_idle_add (
+ session, G_PRIORITY_DEFAULT_IDLE,
+ network_service_notify_host_reachable_cb,
+ g_object_ref (service),
+ (GDestroyNotify) g_object_unref);
+
+ g_object_unref (session);
+}
+
static void
network_service_set_host_reachable (CamelNetworkService *service,
gboolean host_reachable)
@@ -420,7 +444,7 @@ network_service_set_host_reachable (CamelNetworkService *service,
g_mutex_unlock (&priv->property_lock);
- g_object_notify (G_OBJECT (service), "host-reachable");
+ network_service_notify_host_reachable (service);
/* Disconnect immediately if the host is not reachable.
* Then connect lazily when the host becomes reachable. */
@@ -438,48 +462,13 @@ network_service_set_host_reachable (CamelNetworkService *service,
}
}
-static void
-network_service_can_reach_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- CamelNetworkService *service;
- GError *error = NULL;
-
- service = CAMEL_NETWORK_SERVICE (user_data);
-
- g_network_monitor_can_reach_finish (
- G_NETWORK_MONITOR (source_object), result, &error);
-
- if (error == NULL) {
- network_service_set_host_reachable (service, TRUE);
-
- } else if (G_IS_IO_ERROR (error, G_IO_ERROR_CANCELLED)) {
- /* Ignore cancellations. */
-
- } else if (G_IS_IO_ERROR (error, G_IO_ERROR_HOST_UNREACHABLE)) {
- network_service_set_host_reachable (service, FALSE);
-
- } else if (G_IS_RESOLVER_ERROR (error, G_RESOLVER_ERROR_NOT_FOUND)) {
- network_service_set_host_reachable (service, FALSE);
-
- } else {
- g_warning ("%s: %s", G_STRFUNC, error->message);
- }
-
- if (error != NULL)
- g_error_free (error);
-
- g_object_unref (service);
-}
-
static gboolean
network_service_update_host_reachable_idle_cb (gpointer user_data)
{
CamelNetworkService *service;
CamelNetworkServicePrivate *priv;
- GSocketConnectable *connectable;
- GCancellable *cancellable;
+ GCancellable *old_cancellable;
+ GCancellable *new_cancellable;
service = CAMEL_NETWORK_SERVICE (user_data);
priv = CAMEL_NETWORK_SERVICE_GET_PRIVATE (service);
@@ -490,37 +479,22 @@ network_service_update_host_reachable_idle_cb (gpointer user_data)
priv->update_host_reachable = NULL;
g_mutex_unlock (&priv->update_host_reachable_lock);
- connectable = camel_network_service_ref_connectable (service);
+ new_cancellable = g_cancellable_new ();
g_mutex_lock (&priv->network_monitor_cancellable_lock);
+ old_cancellable = priv->network_monitor_cancellable;
+ priv->network_monitor_cancellable = g_object_ref (new_cancellable);
+ g_mutex_unlock (&priv->network_monitor_cancellable_lock);
- cancellable = priv->network_monitor_cancellable;
- priv->network_monitor_cancellable = NULL;
-
- if (cancellable != NULL) {
- g_cancellable_cancel (cancellable);
- g_object_unref (cancellable);
- cancellable = NULL;
- }
-
- if (connectable == NULL) {
- network_service_set_host_reachable (service, FALSE);
- } else {
- cancellable = g_cancellable_new ();
-
- g_network_monitor_can_reach_async (
- priv->network_monitor,
- connectable, cancellable,
- network_service_can_reach_cb,
- g_object_ref (service));
- }
-
- priv->network_monitor_cancellable = cancellable;
+ g_cancellable_cancel (old_cancellable);
- g_mutex_unlock (&priv->network_monitor_cancellable_lock);
+ /* XXX This updates the "host-reachable" property on its own.
+ * There's nothing else to do with the result so omit the
+ * GAsyncReadyCallback; just needs to run asynchronously. */
+ camel_network_service_can_reach (service, new_cancellable, NULL, NULL);
- if (connectable != NULL)
- g_object_unref (connectable);
+ g_clear_object (&old_cancellable);
+ g_clear_object (&new_cancellable);
return FALSE;
}
@@ -982,3 +956,151 @@ camel_network_service_starttls (CamelNetworkService *service,
return tls_client_connection;
}
+/**
+ * camel_network_service_can_reach_sync:
+ * @service: a #CamelNetworkService
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Attempts to determine whether or not the host described by @service's
+ * #CamelNetworkService:connectable property can be reached, without actually
+ * trying to connect to it.
+ *
+ * If @service believes an attempt to connect will succeed, the function
+ * returns %TRUE. Otherwise the function returns %FALSE and sets @error
+ * to an appropriate error (such as %G_IO_ERROR_HOST_UNREACHABLE).
+ *
+ * The function will also update the @service's
+ * #CamelNetworkService:host-reachable property based on the result.
+ *
+ * Returns: whether the host for @service can be reached
+ *
+ * Since: 3.12
+ **/
+gboolean
+camel_network_service_can_reach_sync (CamelNetworkService *service,
+ GCancellable *cancellable,
+ GError **error)
+{
+ CamelNetworkServicePrivate *priv;
+ GSocketConnectable *connectable;
+ gboolean can_reach = FALSE;
+ gboolean update_property;
+ GError *local_error = NULL;
+
+ g_return_val_if_fail (CAMEL_IS_NETWORK_SERVICE (service), FALSE);
+
+ priv = CAMEL_NETWORK_SERVICE_GET_PRIVATE (service);
+ g_return_val_if_fail (priv != NULL, FALSE);
+
+ connectable = camel_network_service_ref_connectable (service);
+
+ if (connectable != NULL) {
+ can_reach = g_network_monitor_can_reach (
+ priv->network_monitor, connectable,
+ cancellable, &local_error);
+ } else {
+ local_error = g_error_new_literal (
+ G_IO_ERROR,
+ G_IO_ERROR_HOST_UNREACHABLE,
+ _("No host information available"));
+ }
+
+ update_property =
+ can_reach ||
+ G_IS_IO_ERROR (local_error, G_IO_ERROR_HOST_UNREACHABLE) ||
+ G_IS_RESOLVER_ERROR (local_error, G_RESOLVER_ERROR_NOT_FOUND);
+
+ if (update_property)
+ network_service_set_host_reachable (service, can_reach);
+
+ g_clear_object (&connectable);
+
+ return can_reach;
+}
+
+/* Helper for camel_network_service_can_reach() */
+static void
+network_service_can_reach_thread (GSimpleAsyncResult *simple,
+ GObject *object,
+ GCancellable *cancellable)
+{
+ GError *local_error = NULL;
+
+ camel_network_service_can_reach_sync (
+ CAMEL_NETWORK_SERVICE (object), cancellable, &local_error);
+
+ if (local_error != NULL)
+ g_simple_async_result_take_error (simple, local_error);
+}
+
+/**
+ * camel_network_service_can_reach:
+ * @service: a #CamelNetworkService
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously attempts to determine whether or not the host described by
+ * @service's #CamelNetworkService:connectable property can be reached, without
+ * actually trying to connect to it.
+ *
+ * For more details, see camel_network_service_can_reach_sync().
+ *
+ * When the operation is finished, @callback will be called. You can then
+ * call camel_network_service_can_reach_finish() to get the result of the
+ * operation.
+ *
+ * Since: 3.12
+ **/
+void
+camel_network_service_can_reach (CamelNetworkService *service,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (service), callback, user_data,
+ camel_network_service_can_reach);
+
+ g_simple_async_result_set_check_cancellable (simple, cancellable);
+
+ g_simple_async_result_run_in_thread (
+ simple, network_service_can_reach_thread,
+ G_PRIORITY_DEFAULT, cancellable);
+
+ g_object_unref (simple);
+}
+
+/**
+ * camel_network_service_can_reach_finish:
+ * @service: a #CamelNetworkService
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_network_service_can_reach().
+ *
+ * Returns: whether the host for @service can be reached
+ *
+ * Since: 3.12
+ **/
+gboolean
+camel_network_service_can_reach_finish (CamelNetworkService *service,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (service),
+ camel_network_service_can_reach), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ /* Assume success unless a GError is set. */
+ return !g_simple_async_result_propagate_error (simple, error);
+}
+
diff --git a/camel/camel-network-service.h b/camel/camel-network-service.h
index dd819a5..6f5da59 100644
--- a/camel/camel-network-service.h
+++ b/camel/camel-network-service.h
@@ -100,6 +100,19 @@ GIOStream * camel_network_service_starttls
(CamelNetworkService *service,
GIOStream *base_stream,
GError **error);
+gboolean camel_network_service_can_reach_sync
+ (CamelNetworkService *service,
+ GCancellable *cancellable,
+ GError **error);
+void camel_network_service_can_reach
+ (CamelNetworkService *service,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean camel_network_service_can_reach_finish
+ (CamelNetworkService *service,
+ GAsyncResult *result,
+ GError **error);
G_END_DECLS
diff --git a/docs/reference/camel/camel-sections.txt b/docs/reference/camel/camel-sections.txt
index 4f7f024..111e576 100644
--- a/docs/reference/camel/camel-sections.txt
+++ b/docs/reference/camel/camel-sections.txt
@@ -1391,6 +1391,9 @@ camel_network_service_set_connectable
camel_network_service_get_host_reachable
camel_network_service_connect_sync
camel_network_service_starttls
+camel_network_service_can_reach_sync
+camel_network_service_can_reach
+camel_network_service_can_reach_finish
<SUBSECTION Standard>
CAMEL_NETWORK_SERVICE
CAMEL_IS_NETWORK_SERVICE
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]