/* util-connectivity-manager.c generated by valac 0.56.3, the Vala compiler
 * generated from util-connectivity-manager.vala, do not modify */

/*
 * Copyright 2017-2018 Michael Gratton <mike@vee.net>
 *
 * This software is licensed under the GNU Lesser General Public License
 * (version 2.1 or later). See the COPYING file in this distribution.
 */

#include "geary-engine.h"
#include <gio/gio.h>
#include <glib.h>
#include <stdlib.h>
#include <string.h>
#include <glib-object.h>

#define GEARY_CONNECTIVITY_MANAGER_CHECK_QUIESCENCE_MS ((guint) (60 * 1000))

enum  {
	GEARY_CONNECTIVITY_MANAGER_0_PROPERTY,
	GEARY_CONNECTIVITY_MANAGER_REMOTE_PROPERTY,
	GEARY_CONNECTIVITY_MANAGER_IS_REACHABLE_PROPERTY,
	GEARY_CONNECTIVITY_MANAGER_IS_VALID_PROPERTY,
	GEARY_CONNECTIVITY_MANAGER_NUM_PROPERTIES
};
static GParamSpec* geary_connectivity_manager_properties[GEARY_CONNECTIVITY_MANAGER_NUM_PROPERTIES];
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL)))
#define _g_free0(var) (var = (g_free (var), NULL))
typedef struct _GearyConnectivityManagerCheckReachableData GearyConnectivityManagerCheckReachableData;
enum  {
	GEARY_CONNECTIVITY_MANAGER_REMOTE_ERROR_REPORTED_SIGNAL,
	GEARY_CONNECTIVITY_MANAGER_NUM_SIGNALS
};
static guint geary_connectivity_manager_signals[GEARY_CONNECTIVITY_MANAGER_NUM_SIGNALS] = {0};

struct _GearyConnectivityManagerPrivate {
	GSocketConnectable* _remote;
	GearyTrillian _is_reachable;
	GearyTrillian _is_valid;
	GNetworkMonitor* monitor;
	GCancellable* existing_check;
	gint64 next_check;
	GearyTimeoutManager* delayed_check;
};

struct _GearyConnectivityManagerCheckReachableData {
	int _state_;
	GObject* _source_object_;
	GAsyncResult* _res_;
	GTask* _async_result;
	GearyConnectivityManager* self;
	GCancellable* cancellable;
	GCancellable* _tmp0_;
	GCancellable* _tmp1_;
	GCancellable* _tmp2_;
	gchar* endpoint;
	GSocketConnectable* _tmp3_;
	gchar* _tmp4_;
	gboolean is_reachable;
	const gchar* _tmp5_;
	gboolean _tmp6_;
	GNetworkMonitor* _tmp7_;
	GSocketConnectable* _tmp8_;
	GCancellable* _tmp9_;
	GNetworkMonitor* _tmp10_;
	gboolean _tmp11_;
	gboolean _tmp12_;
	const gchar* _tmp13_;
	GError* err;
	const gchar* _tmp14_;
	GError* _tmp15_;
	const gchar* _tmp16_;
	GError* _vala1_err;
	const gchar* _tmp17_;
	GError* _tmp18_;
	const gchar* _tmp19_;
	GError* _vala2_err;
	gboolean _tmp20_;
	GError* _tmp21_;
	GNetworkMonitor* _tmp22_;
	gboolean _tmp23_;
	gboolean _tmp24_;
	const gchar* _tmp25_;
	GNetworkConnectivity connectivity;
	GNetworkMonitor* _tmp26_;
	GNetworkConnectivity _tmp27_;
	GNetworkConnectivity _tmp28_;
	gboolean _tmp29_;
	gboolean _tmp30_;
	GNetworkMonitor* _tmp31_;
	gboolean _tmp32_;
	gboolean _tmp33_;
	gboolean _tmp34_;
	const gchar* _tmp35_;
	gchar* _tmp36_;
	GError* _tmp37_;
	const gchar* _tmp38_;
	GError* _tmp39_;
	const gchar* _tmp40_;
	gchar* _tmp41_;
	GError* _tmp42_;
	const gchar* _tmp43_;
	GError* _inner_error1_;
	GCancellable* _tmp44_;
	GearyTimeoutManager* _tmp45_;
	GError* _inner_error0_;
};

static gint GearyConnectivityManager_private_offset;
static gpointer geary_connectivity_manager_parent_class = NULL;

static void geary_connectivity_manager_on_network_changed (GearyConnectivityManager* self,
                                                    gboolean some_available);
static void _geary_connectivity_manager_on_network_changed_g_network_monitor_network_changed (GNetworkMonitor* _sender,
                                                                                       gboolean network_available,
                                                                                       gpointer self);
static void geary_connectivity_manager_set_remote (GearyConnectivityManager* self,
                                            GSocketConnectable* value);
static void geary_connectivity_manager_set_is_reachable (GearyConnectivityManager* self,
                                                  GearyTrillian value);
static void geary_connectivity_manager_set_is_valid (GearyConnectivityManager* self,
                                              GearyTrillian value);
static void __lambda46_ (GearyConnectivityManager* self);
static void ___lambda46__geary_timeout_manager_timeout_func (GearyTimeoutManager* manager,
                                                      gpointer self);
static void geary_connectivity_manager_check_reachable_data_free (gpointer _data);
static gboolean geary_connectivity_manager_check_reachable_co (GearyConnectivityManagerCheckReachableData* _data_);
static void geary_connectivity_manager_check_reachable_ready (GObject* source_object,
                                                       GAsyncResult* _res_,
                                                       gpointer _user_data_);
static gboolean geary_connectivity_manager_is_local_address (GearyConnectivityManager* self);
static inline void geary_connectivity_manager_set_invalid (GearyConnectivityManager* self);
static inline void geary_connectivity_manager_set_reachable (GearyConnectivityManager* self,
                                               gboolean reachable);
static void geary_connectivity_manager_finalize (GObject * obj);
static GType geary_connectivity_manager_get_type_once (void);
static void _vala_geary_connectivity_manager_get_property (GObject * object,
                                                    guint property_id,
                                                    GValue * value,
                                                    GParamSpec * pspec);
static void _vala_geary_connectivity_manager_set_property (GObject * object,
                                                    guint property_id,
                                                    const GValue * value,
                                                    GParamSpec * pspec);

static inline gpointer
geary_connectivity_manager_get_instance_private (GearyConnectivityManager* self)
{
	return G_STRUCT_MEMBER_P (self, GearyConnectivityManager_private_offset);
}

static void
_geary_connectivity_manager_on_network_changed_g_network_monitor_network_changed (GNetworkMonitor* _sender,
                                                                                  gboolean network_available,
                                                                                  gpointer self)
{
	geary_connectivity_manager_on_network_changed ((GearyConnectivityManager*) self, network_available);
}

GSocketConnectable*
geary_connectivity_manager_get_remote (GearyConnectivityManager* self)
{
	GSocketConnectable* result;
	GSocketConnectable* _tmp0_;
	g_return_val_if_fail (GEARY_IS_CONNECTIVITY_MANAGER (self), NULL);
	_tmp0_ = self->priv->_remote;
	result = _tmp0_;
	return result;
}

static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

static void
geary_connectivity_manager_set_remote (GearyConnectivityManager* self,
                                       GSocketConnectable* value)
{
	GSocketConnectable* old_value;
	g_return_if_fail (GEARY_IS_CONNECTIVITY_MANAGER (self));
	old_value = geary_connectivity_manager_get_remote (self);
	if (old_value != value) {
		GSocketConnectable* _tmp0_;
		_tmp0_ = _g_object_ref0 (value);
		_g_object_unref0 (self->priv->_remote);
		self->priv->_remote = _tmp0_;
		g_object_notify_by_pspec ((GObject *) self, geary_connectivity_manager_properties[GEARY_CONNECTIVITY_MANAGER_REMOTE_PROPERTY]);
	}
}

GearyTrillian
geary_connectivity_manager_get_is_reachable (GearyConnectivityManager* self)
{
	GearyTrillian result;
	g_return_val_if_fail (GEARY_IS_CONNECTIVITY_MANAGER (self), 0);
	result = self->priv->_is_reachable;
	return result;
}

static void
geary_connectivity_manager_set_is_reachable (GearyConnectivityManager* self,
                                             GearyTrillian value)
{
	GearyTrillian old_value;
	g_return_if_fail (GEARY_IS_CONNECTIVITY_MANAGER (self));
	old_value = geary_connectivity_manager_get_is_reachable (self);
	if (old_value != value) {
		self->priv->_is_reachable = value;
		g_object_notify_by_pspec ((GObject *) self, geary_connectivity_manager_properties[GEARY_CONNECTIVITY_MANAGER_IS_REACHABLE_PROPERTY]);
	}
}

GearyTrillian
geary_connectivity_manager_get_is_valid (GearyConnectivityManager* self)
{
	GearyTrillian result;
	g_return_val_if_fail (GEARY_IS_CONNECTIVITY_MANAGER (self), 0);
	result = self->priv->_is_valid;
	return result;
}

static void
geary_connectivity_manager_set_is_valid (GearyConnectivityManager* self,
                                         GearyTrillian value)
{
	GearyTrillian old_value;
	g_return_if_fail (GEARY_IS_CONNECTIVITY_MANAGER (self));
	old_value = geary_connectivity_manager_get_is_valid (self);
	if (old_value != value) {
		self->priv->_is_valid = value;
		g_object_notify_by_pspec ((GObject *) self, geary_connectivity_manager_properties[GEARY_CONNECTIVITY_MANAGER_IS_VALID_PROPERTY]);
	}
}

/**
     * Constructs a new manager for a specific remote.
     */
static void
__lambda46_ (GearyConnectivityManager* self)
{
	geary_connectivity_manager_check_reachable (self, NULL, NULL);
}

static void
___lambda46__geary_timeout_manager_timeout_func (GearyTimeoutManager* manager,
                                                 gpointer self)
{
	__lambda46_ ((GearyConnectivityManager*) self);
}

GearyConnectivityManager*
geary_connectivity_manager_construct (GType object_type,
                                      GSocketConnectable* remote)
{
	GearyConnectivityManager * self = NULL;
	GNetworkMonitor* _tmp0_;
	GNetworkMonitor* _tmp1_;
	GNetworkMonitor* _tmp2_;
	GearyTimeoutManager* _tmp3_;
	g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (remote, g_socket_connectable_get_type ()), NULL);
	self = (GearyConnectivityManager*) geary_base_object_construct (object_type);
	geary_connectivity_manager_set_remote (self, remote);
	_tmp0_ = g_network_monitor_get_default ();
	_tmp1_ = _g_object_ref0 (_tmp0_);
	_g_object_unref0 (self->priv->monitor);
	self->priv->monitor = _tmp1_;
	_tmp2_ = self->priv->monitor;
	g_signal_connect_object (_tmp2_, "network-changed", (GCallback) _geary_connectivity_manager_on_network_changed_g_network_monitor_network_changed, self, 0);
	_tmp3_ = geary_timeout_manager_new_seconds (GEARY_CONNECTIVITY_MANAGER_CHECK_QUIESCENCE_MS / 1000, ___lambda46__geary_timeout_manager_timeout_func, self);
	_g_object_unref0 (self->priv->delayed_check);
	self->priv->delayed_check = _tmp3_;
	return self;
}

GearyConnectivityManager*
geary_connectivity_manager_new (GSocketConnectable* remote)
{
	return geary_connectivity_manager_construct (GEARY_TYPE_CONNECTIVITY_MANAGER, remote);
}

static void
geary_connectivity_manager_check_reachable_data_free (gpointer _data)
{
	GearyConnectivityManagerCheckReachableData* _data_;
	_data_ = _data;
	_g_object_unref0 (_data_->self);
	g_slice_free (GearyConnectivityManagerCheckReachableData, _data_);
}

void
geary_connectivity_manager_check_reachable (GearyConnectivityManager* self,
                                            GAsyncReadyCallback _callback_,
                                            gpointer _user_data_)
{
	GearyConnectivityManagerCheckReachableData* _data_;
	GearyConnectivityManager* _tmp0_;
	g_return_if_fail (GEARY_IS_CONNECTIVITY_MANAGER (self));
	_data_ = g_slice_new0 (GearyConnectivityManagerCheckReachableData);
	_data_->_async_result = g_task_new (G_OBJECT (self), NULL, _callback_, _user_data_);
	g_task_set_task_data (_data_->_async_result, _data_, geary_connectivity_manager_check_reachable_data_free);
	_tmp0_ = _g_object_ref0 (self);
	_data_->self = _tmp0_;
	geary_connectivity_manager_check_reachable_co (_data_);
}

void
geary_connectivity_manager_check_reachable_finish (GearyConnectivityManager* self,
                                                   GAsyncResult* _res_)
{
	GearyConnectivityManagerCheckReachableData* _data_;
	_data_ = g_task_propagate_pointer (G_TASK (_res_), NULL);
}

/**
     * Starts checking if the manager's remote is reachable.
     *
     * This will cancel any existing check, and start a new one
     * running, updating the `is_reachable` property on completion.
     */
static void
geary_connectivity_manager_check_reachable_ready (GObject* source_object,
                                                  GAsyncResult* _res_,
                                                  gpointer _user_data_)
{
	GearyConnectivityManagerCheckReachableData* _data_;
	_data_ = _user_data_;
	_data_->_source_object_ = source_object;
	_data_->_res_ = _res_;
	geary_connectivity_manager_check_reachable_co (_data_);
}

static gboolean
geary_connectivity_manager_check_reachable_co (GearyConnectivityManagerCheckReachableData* _data_)
{
	switch (_data_->_state_) {
		case 0:
		goto _state_0;
		case 1:
		goto _state_1;
		default:
		g_assert_not_reached ();
	}
	_state_0:
	geary_connectivity_manager_cancel_check (_data_->self);
	_data_->_tmp0_ = g_cancellable_new ();
	_data_->cancellable = _data_->_tmp0_;
	_data_->_tmp1_ = _data_->cancellable;
	_data_->_tmp2_ = _g_object_ref0 (_data_->_tmp1_);
	_g_object_unref0 (_data_->self->priv->existing_check);
	_data_->self->priv->existing_check = _data_->_tmp2_;
	_data_->_tmp3_ = _data_->self->priv->_remote;
	_data_->_tmp4_ = g_socket_connectable_to_string (_data_->_tmp3_);
	_data_->endpoint = _data_->_tmp4_;
	_data_->is_reachable = FALSE;
	{
		_data_->_tmp5_ = _data_->endpoint;
		g_debug ("util-connectivity-manager.vala:109: Checking if %s reachable...", _data_->_tmp5_);
		_data_->_tmp7_ = _data_->self->priv->monitor;
		_data_->_tmp8_ = _data_->self->priv->_remote;
		_data_->_tmp9_ = _data_->cancellable;
		_data_->_state_ = 1;
		g_network_monitor_can_reach_async (_data_->_tmp7_, _data_->_tmp8_, _data_->_tmp9_, geary_connectivity_manager_check_reachable_ready, _data_);
		return FALSE;
		_state_1:
		_data_->_tmp6_ = g_network_monitor_can_reach_finish (_data_->_tmp7_, _data_->_res_, &_data_->_inner_error0_);
		if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
			if (g_error_matches (_data_->_inner_error0_, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
				goto __catch0_g_io_error_cancelled;
			}
			if (g_error_matches (_data_->_inner_error0_, G_IO_ERROR, G_IO_ERROR_HOST_UNREACHABLE)) {
				goto __catch0_g_io_error_host_unreachable;
			}
			if (_data_->_inner_error0_->domain == G_DBUS_ERROR) {
				goto __catch0_g_dbus_error;
			}
			if (g_error_matches (_data_->_inner_error0_, G_RESOLVER_ERROR, G_RESOLVER_ERROR_TEMPORARY_FAILURE)) {
				goto __catch0_g_resolver_error_temporary_failure;
			}
			goto __catch0_g_error;
		}
		_data_->is_reachable = _data_->_tmp6_;
		_data_->self->priv->next_check = g_get_real_time () + (GEARY_CONNECTIVITY_MANAGER_CHECK_QUIESCENCE_MS * 1000);
	}
	goto __finally0;
	__catch0_g_io_error_cancelled:
	{
		g_clear_error (&_data_->_inner_error0_);
	}
	goto __finally0;
	__catch0_g_io_error_host_unreachable:
	{
		g_clear_error (&_data_->_inner_error0_);
		_data_->_tmp10_ = _data_->self->priv->monitor;
		_data_->_tmp11_ = g_network_monitor_get_network_available (_data_->_tmp10_);
		_data_->_tmp12_ = _data_->_tmp11_;
		if (_data_->_tmp12_) {
			_data_->_tmp13_ = _data_->endpoint;
			g_debug ("util-connectivity-manager.vala:132: Assuming %s is unreachable, despit" \
"e network availability", _data_->_tmp13_);
		}
	}
	goto __finally0;
	__catch0_g_dbus_error:
	{
		_data_->err = _data_->_inner_error0_;
		_data_->_inner_error0_ = NULL;
		_data_->_tmp14_ = _data_->endpoint;
		_data_->_tmp15_ = _data_->err;
		_data_->_tmp16_ = _data_->_tmp15_->message;
		g_debug ("util-connectivity-manager.vala:141: DBus error checking %s reachable, " \
"treating as reachable: %s", _data_->_tmp14_, _data_->_tmp16_);
		_data_->is_reachable = TRUE;
		_g_error_free0 (_data_->err);
	}
	goto __finally0;
	__catch0_g_resolver_error_temporary_failure:
	{
		_data_->_vala1_err = _data_->_inner_error0_;
		_data_->_inner_error0_ = NULL;
		_data_->_tmp17_ = _data_->endpoint;
		_data_->_tmp18_ = _data_->_vala1_err;
		_data_->_tmp19_ = _data_->_tmp18_->message;
		g_debug ("util-connectivity-manager.vala:147: Transient error checking %s reacha" \
"ble, treating offline: %s", _data_->_tmp17_, _data_->_tmp19_);
		_g_error_free0 (_data_->_vala1_err);
	}
	goto __finally0;
	__catch0_g_error:
	{
		_data_->_vala2_err = _data_->_inner_error0_;
		_data_->_inner_error0_ = NULL;
		_data_->_tmp21_ = _data_->_vala2_err;
		if (g_error_matches (_data_->_tmp21_, G_IO_ERROR, G_IO_ERROR_NETWORK_UNREACHABLE)) {
			_data_->_tmp22_ = _data_->self->priv->monitor;
			_data_->_tmp23_ = g_network_monitor_get_network_available (_data_->_tmp22_);
			_data_->_tmp24_ = _data_->_tmp23_;
			_data_->_tmp20_ = _data_->_tmp24_;
		} else {
			_data_->_tmp20_ = FALSE;
		}
		if (_data_->_tmp20_) {
			_data_->_tmp25_ = _data_->endpoint;
			g_debug ("util-connectivity-manager.vala:158: Assuming %s is reachable, despite " \
"network unavailability", _data_->_tmp25_);
			_data_->is_reachable = TRUE;
		} else {
			_data_->_tmp26_ = _data_->self->priv->monitor;
			_data_->_tmp27_ = g_network_monitor_get_connectivity (_data_->_tmp26_);
			_data_->_tmp28_ = _data_->_tmp27_;
			_data_->connectivity = _data_->_tmp28_;
			_data_->_tmp31_ = _data_->self->priv->monitor;
			_data_->_tmp32_ = g_network_monitor_get_network_available (_data_->_tmp31_);
			_data_->_tmp33_ = _data_->_tmp32_;
			if (_data_->_tmp33_) {
				_data_->_tmp30_ = _data_->connectivity == G_NETWORK_CONNECTIVITY_FULL;
			} else {
				_data_->_tmp30_ = FALSE;
			}
			if (_data_->_tmp30_) {
				_data_->_tmp29_ = TRUE;
			} else {
				if (_data_->connectivity == G_NETWORK_CONNECTIVITY_LOCAL) {
					_data_->_tmp34_ = geary_connectivity_manager_is_local_address (_data_->self);
				} else {
					_data_->_tmp34_ = FALSE;
				}
				_data_->_tmp29_ = _data_->_tmp34_;
			}
			if (_data_->_tmp29_) {
				_data_->_tmp35_ = _data_->endpoint;
				_data_->_tmp36_ = g_enum_to_string (g_network_connectivity_get_type (), _data_->connectivity);
				_data_->_tmp37_ = _data_->_vala2_err;
				_data_->_tmp38_ = _data_->_tmp37_->message;
				g_debug ("util-connectivity-manager.vala:171: Error checking %s [%s] reachable, " \
"treating unreachable: %s", _data_->_tmp35_, _data_->_tmp36_, _data_->_tmp38_);
				_g_free0 (_data_->_tmp36_);
				geary_connectivity_manager_set_invalid (_data_->self);
				_data_->_tmp39_ = _data_->_vala2_err;
				g_signal_emit (_data_->self, geary_connectivity_manager_signals[GEARY_CONNECTIVITY_MANAGER_REMOTE_ERROR_REPORTED_SIGNAL], 0, _data_->_tmp39_);
			} else {
				_data_->_tmp40_ = _data_->endpoint;
				_data_->_tmp41_ = g_enum_to_string (g_network_connectivity_get_type (), _data_->connectivity);
				_data_->_tmp42_ = _data_->_vala2_err;
				_data_->_tmp43_ = _data_->_tmp42_->message;
				g_debug ("util-connectivity-manager.vala:176: Error checking %s [%s] reachable, " \
"treating offline: %s", _data_->_tmp40_, _data_->_tmp41_, _data_->_tmp43_);
				_g_free0 (_data_->_tmp41_);
			}
		}
		_g_error_free0 (_data_->_vala2_err);
	}
	__finally0:
	{
		_data_->_tmp44_ = _data_->cancellable;
		if (!g_cancellable_is_cancelled (_data_->_tmp44_)) {
			geary_connectivity_manager_set_reachable (_data_->self, _data_->is_reachable);
			_data_->_tmp45_ = _data_->self->priv->delayed_check;
			geary_timeout_manager_start (_data_->_tmp45_);
		}
		_g_object_unref0 (_data_->self->priv->existing_check);
		_data_->self->priv->existing_check = NULL;
	}
	if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
		_g_free0 (_data_->endpoint);
		_g_object_unref0 (_data_->cancellable);
		g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _data_->_inner_error0_->message, g_quark_to_string (_data_->_inner_error0_->domain), _data_->_inner_error0_->code);
		g_clear_error (&_data_->_inner_error0_);
		g_object_unref (_data_->_async_result);
		return FALSE;
	}
	_g_free0 (_data_->endpoint);
	_g_object_unref0 (_data_->cancellable);
	g_task_return_pointer (_data_->_async_result, _data_, NULL);
	if (_data_->_state_ != 0) {
		while (!g_task_get_completed (_data_->_async_result)) {
			g_main_context_iteration (g_task_get_context (_data_->_async_result), TRUE);
		}
	}
	g_object_unref (_data_->_async_result);
	return FALSE;
}

/**
     * Cancels any running or future reachability check, if any.
     */
void
geary_connectivity_manager_cancel_check (GearyConnectivityManager* self)
{
	GCancellable* _tmp0_;
	GearyTimeoutManager* _tmp2_;
	g_return_if_fail (GEARY_IS_CONNECTIVITY_MANAGER (self));
	_tmp0_ = self->priv->existing_check;
	if (_tmp0_ != NULL) {
		GCancellable* _tmp1_;
		_tmp1_ = self->priv->existing_check;
		g_cancellable_cancel (_tmp1_);
		_g_object_unref0 (self->priv->existing_check);
		self->priv->existing_check = NULL;
	}
	_tmp2_ = self->priv->delayed_check;
	geary_timeout_manager_reset (_tmp2_);
}

static void
geary_connectivity_manager_on_network_changed (GearyConnectivityManager* self,
                                               gboolean some_available)
{
	const gchar* _tmp0_ = NULL;
	g_return_if_fail (GEARY_IS_CONNECTIVITY_MANAGER (self));
	if (some_available) {
		_tmp0_ = "some available";
	} else {
		_tmp0_ = "none available";
	}
	g_debug ("util-connectivity-manager.vala:206: Network changed: %s", _tmp0_);
	if (some_available) {
		gboolean _tmp1_ = FALSE;
		gboolean _tmp2_ = FALSE;
		GearyTrillian _tmp3_;
		_tmp3_ = self->priv->_is_reachable;
		if (geary_trillian_is_uncertain (_tmp3_)) {
			_tmp2_ = TRUE;
		} else {
			GCancellable* _tmp4_;
			_tmp4_ = self->priv->existing_check;
			_tmp2_ = _tmp4_ != NULL;
		}
		if (_tmp2_) {
			_tmp1_ = TRUE;
		} else {
			_tmp1_ = self->priv->next_check <= g_get_real_time ();
		}
		if (_tmp1_) {
			geary_connectivity_manager_check_reachable (self, NULL, NULL);
		} else {
			GearyTimeoutManager* _tmp5_;
			gboolean _tmp6_;
			gboolean _tmp7_;
			_tmp5_ = self->priv->delayed_check;
			_tmp6_ = geary_timeout_manager_get_is_running (_tmp5_);
			_tmp7_ = _tmp6_;
			if (!_tmp7_) {
				GearyTimeoutManager* _tmp8_;
				_tmp8_ = self->priv->delayed_check;
				geary_timeout_manager_start (_tmp8_);
			}
		}
	} else {
		geary_connectivity_manager_set_reachable (self, FALSE);
	}
}

static inline void
geary_connectivity_manager_set_reachable (GearyConnectivityManager* self,
                                          gboolean reachable)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gboolean _tmp10_ = FALSE;
	g_return_if_fail (GEARY_IS_CONNECTIVITY_MANAGER (self));
	if (reachable) {
		GearyTrillian _tmp2_;
		_tmp2_ = self->priv->_is_reachable;
		_tmp1_ = !geary_trillian_is_certain (_tmp2_);
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		_tmp0_ = TRUE;
	} else {
		gboolean _tmp3_ = FALSE;
		if (!reachable) {
			GearyTrillian _tmp4_;
			_tmp4_ = self->priv->_is_reachable;
			_tmp3_ = !geary_trillian_is_impossible (_tmp4_);
		} else {
			_tmp3_ = FALSE;
		}
		_tmp0_ = _tmp3_;
	}
	if (_tmp0_) {
		const gchar* _tmp5_ = NULL;
		GSocketConnectable* _tmp6_;
		gchar* _tmp7_;
		gchar* _tmp8_;
		GearyTrillian _tmp9_ = 0;
		if (reachable) {
			_tmp5_ = "reachable";
		} else {
			_tmp5_ = "unreachable";
		}
		_tmp6_ = self->priv->_remote;
		_tmp7_ = g_socket_connectable_to_string (_tmp6_);
		_tmp8_ = _tmp7_;
		g_debug ("util-connectivity-manager.vala:240: Remote %s became %s", _tmp8_, _tmp5_);
		_g_free0 (_tmp8_);
		if (reachable) {
			_tmp9_ = GEARY_TRILLIAN_TRUE;
		} else {
			_tmp9_ = GEARY_TRILLIAN_FALSE;
		}
		geary_connectivity_manager_set_is_reachable (self, _tmp9_);
	}
	if (reachable) {
		GearyTrillian _tmp11_;
		_tmp11_ = self->priv->_is_valid;
		_tmp10_ = geary_trillian_is_uncertain (_tmp11_);
	} else {
		_tmp10_ = FALSE;
	}
	if (_tmp10_) {
		geary_connectivity_manager_set_is_valid (self, GEARY_TRILLIAN_TRUE);
	}
}

static inline void
geary_connectivity_manager_set_invalid (GearyConnectivityManager* self)
{
	GearyTrillian _tmp0_;
	g_return_if_fail (GEARY_IS_CONNECTIVITY_MANAGER (self));
	_tmp0_ = self->priv->_is_valid;
	if (_tmp0_ != GEARY_TRILLIAN_FALSE) {
		geary_connectivity_manager_set_is_valid (self, GEARY_TRILLIAN_FALSE);
	}
}

static gboolean
geary_connectivity_manager_is_local_address (GearyConnectivityManager* self)
{
	GNetworkAddress* name = NULL;
	GSocketConnectable* _tmp0_;
	GNetworkAddress* _tmp1_;
	GNetworkAddress* _tmp2_;
	GInetSocketAddress* inet = NULL;
	GSocketConnectable* _tmp18_;
	GInetSocketAddress* _tmp19_;
	GInetSocketAddress* _tmp20_;
	gboolean result;
	g_return_val_if_fail (GEARY_IS_CONNECTIVITY_MANAGER (self), FALSE);
	_tmp0_ = self->priv->_remote;
	_tmp1_ = _g_object_ref0 (G_TYPE_CHECK_INSTANCE_TYPE (_tmp0_, g_network_address_get_type ()) ? ((GNetworkAddress*) _tmp0_) : NULL);
	name = _tmp1_;
	_tmp2_ = name;
	if (_tmp2_ != NULL) {
		gboolean _tmp3_ = FALSE;
		gboolean _tmp4_ = FALSE;
		gboolean _tmp5_ = FALSE;
		GNetworkAddress* _tmp6_;
		const gchar* _tmp7_;
		const gchar* _tmp8_;
		_tmp6_ = name;
		_tmp7_ = g_network_address_get_hostname (_tmp6_);
		_tmp8_ = _tmp7_;
		if (g_strcmp0 (_tmp8_, "localhost") == 0) {
			_tmp5_ = TRUE;
		} else {
			GNetworkAddress* _tmp9_;
			const gchar* _tmp10_;
			const gchar* _tmp11_;
			_tmp9_ = name;
			_tmp10_ = g_network_address_get_hostname (_tmp9_);
			_tmp11_ = _tmp10_;
			_tmp5_ = g_str_has_prefix (_tmp11_, "localhost.");
		}
		if (_tmp5_) {
			_tmp4_ = TRUE;
		} else {
			GNetworkAddress* _tmp12_;
			const gchar* _tmp13_;
			const gchar* _tmp14_;
			_tmp12_ = name;
			_tmp13_ = g_network_address_get_hostname (_tmp12_);
			_tmp14_ = _tmp13_;
			_tmp4_ = g_strcmp0 (_tmp14_, "127.0.0.1") == 0;
		}
		if (_tmp4_) {
			_tmp3_ = TRUE;
		} else {
			GNetworkAddress* _tmp15_;
			const gchar* _tmp16_;
			const gchar* _tmp17_;
			_tmp15_ = name;
			_tmp16_ = g_network_address_get_hostname (_tmp15_);
			_tmp17_ = _tmp16_;
			_tmp3_ = g_strcmp0 (_tmp17_, "::1") == 0;
		}
		result = _tmp3_;
		_g_object_unref0 (name);
		return result;
	}
	_tmp18_ = self->priv->_remote;
	_tmp19_ = _g_object_ref0 (G_TYPE_CHECK_INSTANCE_TYPE (_tmp18_, g_inet_socket_address_get_type ()) ? ((GInetSocketAddress*) _tmp18_) : NULL);
	inet = _tmp19_;
	_tmp20_ = inet;
	if (_tmp20_ != NULL) {
		gboolean _tmp21_ = FALSE;
		GInetSocketAddress* _tmp22_;
		GInetAddress* _tmp23_;
		GInetAddress* _tmp24_;
		gboolean _tmp25_;
		gboolean _tmp26_;
		_tmp22_ = inet;
		_tmp23_ = g_inet_socket_address_get_address (_tmp22_);
		_tmp24_ = _tmp23_;
		_tmp25_ = g_inet_address_get_is_loopback (_tmp24_);
		_tmp26_ = _tmp25_;
		if (_tmp26_) {
			_tmp21_ = TRUE;
		} else {
			GInetSocketAddress* _tmp27_;
			GInetAddress* _tmp28_;
			GInetAddress* _tmp29_;
			gboolean _tmp30_;
			gboolean _tmp31_;
			_tmp27_ = inet;
			_tmp28_ = g_inet_socket_address_get_address (_tmp27_);
			_tmp29_ = _tmp28_;
			_tmp30_ = g_inet_address_get_is_link_local (_tmp29_);
			_tmp31_ = _tmp30_;
			_tmp21_ = _tmp31_;
		}
		result = _tmp21_;
		_g_object_unref0 (inet);
		_g_object_unref0 (name);
		return result;
	}
	result = FALSE;
	_g_object_unref0 (inet);
	_g_object_unref0 (name);
	return result;
}

static void
geary_connectivity_manager_class_init (GearyConnectivityManagerClass * klass,
                                       gpointer klass_data)
{
	geary_connectivity_manager_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &GearyConnectivityManager_private_offset);
	G_OBJECT_CLASS (klass)->get_property = _vala_geary_connectivity_manager_get_property;
	G_OBJECT_CLASS (klass)->set_property = _vala_geary_connectivity_manager_set_property;
	G_OBJECT_CLASS (klass)->finalize = geary_connectivity_manager_finalize;
	/** The endpoint being monitored. */
	g_object_class_install_property (G_OBJECT_CLASS (klass), GEARY_CONNECTIVITY_MANAGER_REMOTE_PROPERTY, geary_connectivity_manager_properties[GEARY_CONNECTIVITY_MANAGER_REMOTE_PROPERTY] = g_param_spec_object ("remote", "remote", "remote", g_socket_connectable_get_type (), G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	/** Determines if the managed endpoint is currently reachable. */
	g_object_class_install_property (G_OBJECT_CLASS (klass), GEARY_CONNECTIVITY_MANAGER_IS_REACHABLE_PROPERTY, geary_connectivity_manager_properties[GEARY_CONNECTIVITY_MANAGER_IS_REACHABLE_PROPERTY] = g_param_spec_enum ("is-reachable", "is-reachable", "is-reachable", GEARY_TYPE_TRILLIAN, GEARY_TRILLIAN_UNKNOWN, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	/**
	     * Determines if the remote endpoint could be resolved.
	     *
	     * This will become certain if the remote becomes reachable, and
	     * will become impossible if a fatal error is reported.
	     */
	g_object_class_install_property (G_OBJECT_CLASS (klass), GEARY_CONNECTIVITY_MANAGER_IS_VALID_PROPERTY, geary_connectivity_manager_properties[GEARY_CONNECTIVITY_MANAGER_IS_VALID_PROPERTY] = g_param_spec_enum ("is-valid", "is-valid", "is-valid", GEARY_TYPE_TRILLIAN, GEARY_TRILLIAN_UNKNOWN, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
	/**
	     * Fired when a fatal error was reported checking the remote.
	     *
	     * This is typically caused by an an authoritative DNS name not
	     * found error, but may be anything else that indicates that the
	     * remote will be unusable as-is without some kind of user or
	     * server administrator intervention.
	     */
	geary_connectivity_manager_signals[GEARY_CONNECTIVITY_MANAGER_REMOTE_ERROR_REPORTED_SIGNAL] = g_signal_new ("remote-error-reported", GEARY_TYPE_CONNECTIVITY_MANAGER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
}

static void
geary_connectivity_manager_instance_init (GearyConnectivityManager * self,
                                          gpointer klass)
{
	self->priv = geary_connectivity_manager_get_instance_private (self);
	self->priv->_remote = NULL;
	self->priv->_is_reachable = GEARY_TRILLIAN_UNKNOWN;
	self->priv->_is_valid = GEARY_TRILLIAN_UNKNOWN;
	self->priv->existing_check = NULL;
	self->priv->next_check = (gint64) 0;
}

static void
geary_connectivity_manager_finalize (GObject * obj)
{
	GearyConnectivityManager * self;
	GNetworkMonitor* _tmp0_;
	guint _tmp1_;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, GEARY_TYPE_CONNECTIVITY_MANAGER, GearyConnectivityManager);
	_tmp0_ = self->priv->monitor;
	g_signal_parse_name ("network-changed", g_network_monitor_get_type (), &_tmp1_, NULL, FALSE);
	g_signal_handlers_disconnect_matched (_tmp0_, G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, _tmp1_, 0, NULL, (GCallback) _geary_connectivity_manager_on_network_changed_g_network_monitor_network_changed, self);
	_g_object_unref0 (self->priv->_remote);
	_g_object_unref0 (self->priv->monitor);
	_g_object_unref0 (self->priv->existing_check);
	_g_object_unref0 (self->priv->delayed_check);
	G_OBJECT_CLASS (geary_connectivity_manager_parent_class)->finalize (obj);
}

/**
 * Keeps track of network connectivity changes for a network endpoint.
 *
 * This class is a convenience API for the GIO NetworkMonitor. Since
 * when connecting and disconnecting from a network, multiple
 * network-changed signals may be sent, this class coalesces these as
 * best as possible so the rest of the engine is only notified once
 * when a remote becomes reachable, and once when it becomes
 * unreachable.
 *
 * Note this class is not thread safe and should only be invoked from
 * the main loop.
 */
 G_GNUC_NO_INLINE static GType
geary_connectivity_manager_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (GearyConnectivityManagerClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) geary_connectivity_manager_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (GearyConnectivityManager), 0, (GInstanceInitFunc) geary_connectivity_manager_instance_init, NULL };
	GType geary_connectivity_manager_type_id;
	geary_connectivity_manager_type_id = g_type_register_static (GEARY_TYPE_BASE_OBJECT, "GearyConnectivityManager", &g_define_type_info, 0);
	GearyConnectivityManager_private_offset = g_type_add_instance_private (geary_connectivity_manager_type_id, sizeof (GearyConnectivityManagerPrivate));
	return geary_connectivity_manager_type_id;
}

GType
geary_connectivity_manager_get_type (void)
{
	static gsize geary_connectivity_manager_type_id__once = 0;
	if (g_once_init_enter (&geary_connectivity_manager_type_id__once)) {
		GType geary_connectivity_manager_type_id;
		geary_connectivity_manager_type_id = geary_connectivity_manager_get_type_once ();
		g_once_init_leave (&geary_connectivity_manager_type_id__once, geary_connectivity_manager_type_id);
	}
	return geary_connectivity_manager_type_id__once;
}

static void
_vala_geary_connectivity_manager_get_property (GObject * object,
                                               guint property_id,
                                               GValue * value,
                                               GParamSpec * pspec)
{
	GearyConnectivityManager * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, GEARY_TYPE_CONNECTIVITY_MANAGER, GearyConnectivityManager);
	switch (property_id) {
		case GEARY_CONNECTIVITY_MANAGER_REMOTE_PROPERTY:
		g_value_set_object (value, geary_connectivity_manager_get_remote (self));
		break;
		case GEARY_CONNECTIVITY_MANAGER_IS_REACHABLE_PROPERTY:
		g_value_set_enum (value, geary_connectivity_manager_get_is_reachable (self));
		break;
		case GEARY_CONNECTIVITY_MANAGER_IS_VALID_PROPERTY:
		g_value_set_enum (value, geary_connectivity_manager_get_is_valid (self));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
_vala_geary_connectivity_manager_set_property (GObject * object,
                                               guint property_id,
                                               const GValue * value,
                                               GParamSpec * pspec)
{
	GearyConnectivityManager * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, GEARY_TYPE_CONNECTIVITY_MANAGER, GearyConnectivityManager);
	switch (property_id) {
		case GEARY_CONNECTIVITY_MANAGER_REMOTE_PROPERTY:
		geary_connectivity_manager_set_remote (self, g_value_get_object (value));
		break;
		case GEARY_CONNECTIVITY_MANAGER_IS_REACHABLE_PROPERTY:
		geary_connectivity_manager_set_is_reachable (self, g_value_get_enum (value));
		break;
		case GEARY_CONNECTIVITY_MANAGER_IS_VALID_PROPERTY:
		geary_connectivity_manager_set_is_valid (self, g_value_get_enum (value));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

