X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgnetworkmonitorbase.c;h=ead9e6436e1474ab470422c1a2049f8e540309bf;hb=fd643b87ab7bc232274c5cd6f9c175d5f6f9ecb9;hp=2494ca3da1eab5f8458de53616ac1a3ec9a45530;hpb=d85b722734a6fcfe94032f6113de9e5c190fd7c3;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gnetworkmonitorbase.c b/gio/gnetworkmonitorbase.c index 2494ca3..ead9e64 100644 --- a/gio/gnetworkmonitorbase.c +++ b/gio/gnetworkmonitorbase.c @@ -13,9 +13,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. + * Public License along with this library; if not, see . */ #include "config.h" @@ -30,22 +28,12 @@ #include "gnetworkmonitor.h" #include "gsocketaddressenumerator.h" #include "gsocketconnectable.h" +#include "gtask.h" #include "glibintl.h" static void g_network_monitor_base_iface_init (GNetworkMonitorInterface *iface); static void g_network_monitor_base_initable_iface_init (GInitableIface *iface); -G_DEFINE_TYPE_WITH_CODE (GNetworkMonitorBase, g_network_monitor_base, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - g_network_monitor_base_initable_iface_init) - G_IMPLEMENT_INTERFACE (G_TYPE_NETWORK_MONITOR, - g_network_monitor_base_iface_init) - _g_io_modules_ensure_extension_points_registered (); - g_io_extension_point_implement (G_NETWORK_MONITOR_EXTENSION_POINT_NAME, - g_define_type_id, - "base", - 0)) - enum { PROP_0, @@ -69,13 +57,22 @@ static guint network_changed_signal = 0; static void queue_network_changed (GNetworkMonitorBase *monitor); +G_DEFINE_TYPE_WITH_CODE (GNetworkMonitorBase, g_network_monitor_base, G_TYPE_OBJECT, + G_ADD_PRIVATE (GNetworkMonitorBase) + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + g_network_monitor_base_initable_iface_init) + G_IMPLEMENT_INTERFACE (G_TYPE_NETWORK_MONITOR, + g_network_monitor_base_iface_init) + _g_io_modules_ensure_extension_points_registered (); + g_io_extension_point_implement (G_NETWORK_MONITOR_EXTENSION_POINT_NAME, + g_define_type_id, + "base", + 0)) + static void g_network_monitor_base_init (GNetworkMonitorBase *monitor) { - monitor->priv = G_TYPE_INSTANCE_GET_PRIVATE (monitor, - G_TYPE_NETWORK_MONITOR_BASE, - GNetworkMonitorBasePrivate); - + monitor->priv = g_network_monitor_base_get_instance_private (monitor); monitor->priv->networks = g_ptr_array_new_with_free_func (g_object_unref); monitor->priv->context = g_main_context_get_thread_default (); if (monitor->priv->context) @@ -149,8 +146,6 @@ g_network_monitor_base_class_init (GNetworkMonitorBaseClass *monitor_class) { GObjectClass *gobject_class = G_OBJECT_CLASS (monitor_class); - g_type_class_add_private (monitor_class, sizeof (GNetworkMonitorBasePrivate)); - gobject_class->constructed = g_network_monitor_base_constructed; gobject_class->get_property = g_network_monitor_base_get_property; gobject_class->finalize = g_network_monitor_base_finalize; @@ -159,20 +154,36 @@ g_network_monitor_base_class_init (GNetworkMonitorBaseClass *monitor_class) } static gboolean +g_network_monitor_base_can_reach_sockaddr (GNetworkMonitorBase *base, + GSocketAddress *sockaddr) +{ + GInetAddress *iaddr; + int i; + + if (!G_IS_INET_SOCKET_ADDRESS (sockaddr)) + return FALSE; + + iaddr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (sockaddr)); + for (i = 0; i < base->priv->networks->len; i++) + { + if (g_inet_address_mask_matches (base->priv->networks->pdata[i], iaddr)) + return TRUE; + } + + return FALSE; +} + +static gboolean g_network_monitor_base_can_reach (GNetworkMonitor *monitor, GSocketConnectable *connectable, GCancellable *cancellable, GError **error) { - GNetworkMonitorBasePrivate *priv = G_NETWORK_MONITOR_BASE (monitor)->priv; + GNetworkMonitorBase *base = G_NETWORK_MONITOR_BASE (monitor); GSocketAddressEnumerator *enumerator; GSocketAddress *addr; - if (priv->have_ipv4_default_route && - priv->have_ipv6_default_route) - return TRUE; - - if (priv->networks->len == 0) + if (base->priv->networks->len == 0) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NETWORK_UNREACHABLE, _("Network unreachable")); @@ -188,23 +199,21 @@ g_network_monitor_base_can_reach (GNetworkMonitor *monitor, return FALSE; } + if (base->priv->have_ipv4_default_route && + base->priv->have_ipv6_default_route) + { + g_object_unref (enumerator); + g_object_unref (addr); + return TRUE; + } + while (addr) { - if (G_IS_INET_SOCKET_ADDRESS (addr)) + if (g_network_monitor_base_can_reach_sockaddr (base, addr)) { - GInetAddress *iaddr; - int i; - - iaddr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (addr)); - for (i = 0; i < priv->networks->len; i++) - { - if (g_inet_address_mask_matches (priv->networks->pdata[i], iaddr)) - { - g_object_unref (addr); - g_object_unref (enumerator); - return TRUE; - } - } + g_object_unref (addr); + g_object_unref (enumerator); + return TRUE; } g_object_unref (addr); @@ -221,9 +230,92 @@ g_network_monitor_base_can_reach (GNetworkMonitor *monitor, } static void +can_reach_async_got_address (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GSocketAddressEnumerator *enumerator = G_SOCKET_ADDRESS_ENUMERATOR (object); + GTask *task = user_data; + GNetworkMonitorBase *base = g_task_get_source_object (task); + GSocketAddress *addr; + GError *error = NULL; + + addr = g_socket_address_enumerator_next_finish (enumerator, result, &error); + if (!addr) + { + if (error) + { + /* Either the user cancelled, or DNS resolution failed */ + g_task_return_error (task, error); + g_object_unref (task); + return; + } + else + { + /* Resolved all addresses, none matched */ + g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_HOST_UNREACHABLE, + _("Host unreachable")); + g_object_unref (task); + return; + } + } + + if (g_network_monitor_base_can_reach_sockaddr (base, addr)) + { + g_object_unref (addr); + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + } + g_object_unref (addr); + + g_socket_address_enumerator_next_async (enumerator, + g_task_get_cancellable (task), + can_reach_async_got_address, task); +} + +static void +g_network_monitor_base_can_reach_async (GNetworkMonitor *monitor, + GSocketConnectable *connectable, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + GSocketAddressEnumerator *enumerator; + + task = g_task_new (monitor, cancellable, callback, user_data); + + if (G_NETWORK_MONITOR_BASE (monitor)->priv->networks->len == 0) + { + g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NETWORK_UNREACHABLE, + _("Network unreachable")); + g_object_unref (task); + return; + } + + enumerator = g_socket_connectable_proxy_enumerate (connectable); + g_socket_address_enumerator_next_async (enumerator, cancellable, + can_reach_async_got_address, task); + g_object_unref (enumerator); +} + +static gboolean +g_network_monitor_base_can_reach_finish (GNetworkMonitor *monitor, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (g_task_is_valid (result, monitor), FALSE); + + return g_task_propagate_boolean (G_TASK (result), error); +} + +static void g_network_monitor_base_iface_init (GNetworkMonitorInterface *monitor_iface) { monitor_iface->can_reach = g_network_monitor_base_can_reach; + monitor_iface->can_reach_async = g_network_monitor_base_can_reach_async; + monitor_iface->can_reach_finish = g_network_monitor_base_can_reach_finish; network_changed_signal = g_signal_lookup ("network-changed", G_TYPE_NETWORK_MONITOR); } @@ -287,6 +379,7 @@ queue_network_changed (GNetworkMonitorBase *monitor) */ g_source_set_priority (source, G_PRIORITY_HIGH_IDLE); g_source_set_callback (source, emit_network_changed, monitor, NULL); + g_source_set_name (source, "[gio] emit_network_changed"); g_source_attach (source, monitor->priv->context); monitor->priv->network_changed_source = source; }