summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeemu Ikonen <tpikonen@mailbox.org>2022-10-09 22:18:46 +0300
committerTeemu Ikonen <tpikonen@mailbox.org>2022-10-31 08:06:42 +0000
commitc8a316fd85a0a7f9b91f5953627ba7c5b9a53d04 (patch)
tree46cc48bf0d1f918b37aff22ea226950f326f629f
parenta0e7368f8d518785c7b8e18e33c0d86515a3f870 (diff)
downloadgeoclue-c8a316fd85a0a7f9b91f5953627ba7c5b9a53d04.tar.gz
web-source: Check connectivity with g_network_monitor_can_reach
Add instance variables locate_url and submit_url and setter functions for them. Set these URLs in the initializers of child classes GClue3G and GClueWifi. Do separate connectivity checks for submit_url and locate_url using g_network_monitor_can_reach_async(). This allows location and submission servers running on localhost to be reached when there is no outside connectivity. Add a GCancellable priv->cancellable and use it in g_network_monitor_can_reach_async() calls.
-rw-r--r--src/gclue-3g.c5
-rw-r--r--src/gclue-web-source.c151
-rw-r--r--src/gclue-web-source.h4
-rw-r--r--src/gclue-wifi.c7
4 files changed, 141 insertions, 26 deletions
diff --git a/src/gclue-3g.c b/src/gclue-3g.c
index 3166a7b..7521551 100644
--- a/src/gclue-3g.c
+++ b/src/gclue-3g.c
@@ -170,6 +170,7 @@ static void
gclue_3g_init (GClue3G *source)
{
GClue3GPrivate *priv;
+ GClueWebSource *web_source = GCLUE_WEB_SOURCE (source);
source->priv = gclue_3g_get_instance_private (source);
priv = source->priv;
@@ -177,6 +178,10 @@ gclue_3g_init (GClue3G *source)
priv->cancellable = g_cancellable_new ();
priv->mozilla = gclue_mozilla_get_singleton ();
+ gclue_web_source_set_locate_url (web_source,
+ gclue_mozilla_get_locate_url (priv->mozilla));
+ gclue_web_source_set_submit_url (web_source,
+ gclue_mozilla_get_submit_url (priv->mozilla));
priv->modem = gclue_modem_manager_get_singleton ();
priv->threeg_notify_id =
diff --git a/src/gclue-web-source.c b/src/gclue-web-source.c
index 372bd5f..56e3a0c 100644
--- a/src/gclue-web-source.c
+++ b/src/gclue-web-source.c
@@ -37,12 +37,12 @@
* Baseclass for all sources that solely use a web resource for geolocation.
**/
-static gboolean
-get_internet_available (void);
static void
refresh_accuracy_level (GClueWebSource *web);
struct _GClueWebSourcePrivate {
+ GCancellable *cancellable;
+
GClueAccuracyLevel accuracy_level;
SoupSession *soup_session;
@@ -55,7 +55,10 @@ struct _GClueWebSourcePrivate {
guint64 last_submitted;
- gboolean internet_available;
+ const char *locate_url;
+ const char *submit_url;
+ gboolean locate_url_reachable;
+ gboolean submit_url_reachable;
};
enum
@@ -95,9 +98,9 @@ gclue_web_source_real_refresh_async (GClueWebSource *source,
return;
}
- if (!get_internet_available ()) {
+ if (!source->priv->locate_url_reachable) {
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NETWORK_UNREACHABLE,
- "Network unavailable");
+ "Cannot reach locate URL");
return;
}
@@ -203,18 +206,6 @@ query_callback (GObject *source_object,
}
}
-static gboolean
-get_internet_available (void)
-{
- GNetworkMonitor *monitor = g_network_monitor_get_default ();
- gboolean available;
-
- available = (g_network_monitor_get_connectivity (monitor) ==
- G_NETWORK_CONNECTIVITY_FULL);
-
- return available;
-}
-
static void
refresh_accuracy_level (GClueWebSource *web)
{
@@ -223,7 +214,7 @@ refresh_accuracy_level (GClueWebSource *web)
existing = gclue_location_source_get_available_accuracy_level
(GCLUE_LOCATION_SOURCE (web));
new = GCLUE_WEB_SOURCE_GET_CLASS (web)->get_available_accuracy_level
- (web, web->priv->internet_available);
+ (web, web->priv->locate_url_reachable);
if (new != existing) {
g_debug ("Available accuracy level from %s: %u",
G_OBJECT_TYPE_NAME (web), new);
@@ -234,18 +225,108 @@ refresh_accuracy_level (GClueWebSource *web)
}
static void
-on_network_changed (GNetworkMonitor *monitor G_GNUC_UNUSED,
+locate_url_checked_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GNetworkMonitor *mon = G_NETWORK_MONITOR (source_object);
+ GClueWebSource *web;
+ gboolean reachable, last_reachable;
+ g_autoptr(GError) error = NULL;
+
+ reachable = g_network_monitor_can_reach_finish (mon, result, &error);
+ if (error && g_error_matches (error, G_IO_ERROR,
+ G_IO_ERROR_CANCELLED)) {
+ return; /* WebSource instance is finalized */
+ }
+
+ web = GCLUE_WEB_SOURCE (user_data);
+ last_reachable = web->priv->locate_url_reachable;
+ web->priv->locate_url_reachable = reachable;
+ if (last_reachable == reachable)
+ return; /* We already reacted to network change */
+
+ g_debug ("Network changed: %s",
+ reachable ? "Enabling locate URL queries" :
+ "Disabling locate URL queries");
+ if (reachable) {
+ GCLUE_WEB_SOURCE_GET_CLASS (web)->refresh_async
+ (web, NULL, query_callback, NULL);
+ }
+}
+
+static void
+submit_url_checked_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GNetworkMonitor *mon = G_NETWORK_MONITOR (source_object);
+ GClueWebSource *web;
+ gboolean reachable, last_reachable;
+ g_autoptr(GError) error = NULL;
+
+ reachable = g_network_monitor_can_reach_finish (mon, result, &error);
+ if (error && g_error_matches (error, G_IO_ERROR,
+ G_IO_ERROR_CANCELLED)) {
+ return; /* WebSource instance is finalized */
+ }
+
+ web = GCLUE_WEB_SOURCE (user_data);
+ last_reachable = web->priv->submit_url_reachable;
+ web->priv->submit_url_reachable = reachable;
+ if (last_reachable == reachable) {
+ return;
+ }
+ g_debug ("Network changed: %s",
+ reachable ? "Enabling submit URL queries" :
+ "Disabling submit URL queries");
+}
+
+static void
+on_network_changed (GNetworkMonitor *unused_monitor G_GNUC_UNUSED,
gboolean available G_GNUC_UNUSED,
gpointer user_data)
{
+ GNetworkMonitor *monitor = g_network_monitor_get_default ();
GClueWebSource *web = GCLUE_WEB_SOURCE (user_data);
- gboolean last_available = web->priv->internet_available;
-
- web->priv->internet_available = get_internet_available ();
- if (last_available == web->priv->internet_available)
- return; /* We already reacted to network change */
+ g_autoptr(GSocketConnectable) submit_addr = NULL;
+ g_autoptr(GSocketConnectable) locate_addr = NULL;
+
+ if (web->priv->submit_url) {
+ submit_addr = g_network_address_parse_uri (web->priv->submit_url,
+ 80, NULL);
+ if (submit_addr) {
+ g_network_monitor_can_reach_async (monitor,
+ submit_addr,
+ web->priv->cancellable,
+ submit_url_checked_cb,
+ web);
+ } else {
+ g_warning ("Could not parse submit URL '%s'",
+ web->priv->submit_url);
+ web->priv->submit_url_reachable = FALSE;
+ }
+ } else {
+ web->priv->submit_url_reachable = FALSE;
+ }
- GCLUE_WEB_SOURCE_GET_CLASS (web)->refresh_async (web, NULL, query_callback, NULL);
+ if (web->priv->locate_url) {
+ locate_addr = g_network_address_parse_uri (web->priv->locate_url,
+ 80, NULL);
+ if (locate_addr) {
+ g_network_monitor_can_reach_async (monitor,
+ locate_addr,
+ web->priv->cancellable,
+ locate_url_checked_cb,
+ web);
+ } else {
+ g_warning ("Could not parse locate URL '%s'",
+ web->priv->locate_url);
+ web->priv->locate_url_reachable = FALSE;
+ }
+ } else {
+ web->priv->locate_url_reachable = FALSE;
+ }
}
static void
@@ -261,6 +342,8 @@ gclue_web_source_finalize (GObject *gsource)
{
GClueWebSourcePrivate *priv = GCLUE_WEB_SOURCE (gsource)->priv;
+ g_cancellable_cancel (priv->cancellable);
+
if (priv->network_changed_id) {
g_signal_handler_disconnect (g_network_monitor_get_default (),
priv->network_changed_id);
@@ -282,6 +365,7 @@ gclue_web_source_finalize (GObject *gsource)
}
g_clear_object (&priv->soup_session);
+ g_clear_object (&priv->cancellable);
G_OBJECT_CLASS (gclue_web_source_parent_class)->finalize (gsource);
}
@@ -380,6 +464,7 @@ static void
gclue_web_source_init (GClueWebSource *web)
{
web->priv = gclue_web_source_get_instance_private (web);
+ web->priv->cancellable = g_cancellable_new ();
}
/**
@@ -444,7 +529,7 @@ on_submit_source_location_notify (GObject *source_object,
web->priv->last_submitted = gclue_location_get_timestamp (location);
- if (!get_internet_available ())
+ if (!web->priv->submit_url_reachable)
return;
query = GCLUE_WEB_SOURCE_GET_CLASS (web)->create_submit_query
@@ -492,3 +577,17 @@ gclue_web_source_set_submit_source (GClueWebSource *web,
on_submit_source_location_notify (G_OBJECT (submit_source), NULL, web);
}
+
+void
+gclue_web_source_set_locate_url (GClueWebSource *source,
+ const char *url)
+{
+ source->priv->locate_url = url;
+}
+
+void
+gclue_web_source_set_submit_url (GClueWebSource *source,
+ const char *url)
+{
+ source->priv->submit_url = url;
+}
diff --git a/src/gclue-web-source.h b/src/gclue-web-source.h
index 59f2b16..05068c6 100644
--- a/src/gclue-web-source.h
+++ b/src/gclue-web-source.h
@@ -84,6 +84,10 @@ struct _GClueWebSourceClass {
void gclue_web_source_refresh (GClueWebSource *source);
void gclue_web_source_set_submit_source (GClueWebSource *source,
GClueLocationSource *submit_source);
+void gclue_web_source_set_locate_url (GClueWebSource *source,
+ const char *url);
+void gclue_web_source_set_submit_url (GClueWebSource *source,
+ const char *url);
G_END_DECLS
diff --git a/src/gclue-wifi.c b/src/gclue-wifi.c
index 97ab12c..cd20b0d 100644
--- a/src/gclue-wifi.c
+++ b/src/gclue-wifi.c
@@ -970,10 +970,17 @@ on_interface_removed (WPASupplicant *supplicant,
static void
gclue_wifi_init (GClueWifi *wifi)
{
+ GClueWebSource *web_source = GCLUE_WEB_SOURCE (wifi);
+
wifi->priv = gclue_wifi_get_instance_private (wifi);
wifi->priv->intf_cancellable = g_cancellable_new ();
wifi->priv->mozilla = gclue_mozilla_get_singleton ();
+ gclue_web_source_set_locate_url (web_source,
+ gclue_mozilla_get_locate_url (wifi->priv->mozilla));
+ gclue_web_source_set_submit_url (web_source,
+ gclue_mozilla_get_submit_url (wifi->priv->mozilla));
+
wifi->priv->bss_proxies = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,