summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndrej Holy <oholy@redhat.com>2022-04-21 08:41:46 +0200
committerOndrej Holy <oholy@redhat.com>2022-04-21 08:41:46 +0200
commit4c92b244dee619abbc827d05ee098259515890b1 (patch)
tree648b225bdb0b65f50ac8c94c7366f956897f8234
parent747c7f6ea6c8b6a7ccd008bb47996ba7eb169bcc (diff)
downloadgvfs-4c92b244dee619abbc827d05ee098259515890b1.tar.gz
dav: Port DNS-SD resolver to async API to fix hangs when mounting
The mount operation hangs for DNS-SD style URIs (i.e. with `dav+sd` and `davs+sd` schemes) after the recent commit 9203fad5. This is because the backend now uses the asynchronous APIs, but the `GVfsDnsSdResolver` is still used synchronously. Let's use asynchronous API for the resolver as well to fix the hangs. Fixes: https://gitlab.gnome.org/GNOME/gvfs/-/issues/618
-rw-r--r--daemon/gvfsbackenddav.c113
1 files changed, 68 insertions, 45 deletions
diff --git a/daemon/gvfsbackenddav.c b/daemon/gvfsbackenddav.c
index fd58b2c9..913c4524 100644
--- a/daemon/gvfsbackenddav.c
+++ b/daemon/gvfsbackenddav.c
@@ -2338,6 +2338,68 @@ clear_msgs:
g_object_unref (msg_opts);
}
+static void
+try_mount_send_opts (GVfsJobMount *job)
+{
+ GVfsBackendDav *dav_backend = G_VFS_BACKEND_DAV (job->backend);
+ GVfsBackendHttp *http_backend = G_VFS_BACKEND_HTTP (job->backend);
+ SoupMessage *msg_opts;
+
+ if (http_backend->mount_base == NULL)
+ {
+ g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ _("Invalid mount spec"));
+ return;
+ }
+
+ soup_session_add_feature_by_type (http_backend->session,
+ SOUP_TYPE_AUTH_NEGOTIATE);
+ soup_session_add_feature_by_type (http_backend->session,
+ SOUP_TYPE_AUTH_NTLM);
+
+ dav_backend->auth_info.mount_source = g_object_ref (job->mount_source);
+ dav_backend->auth_info.server_auth.username = g_strdup (g_uri_get_user (http_backend->mount_base));
+ dav_backend->auth_info.server_auth.password = NULL;
+ dav_backend->auth_info.server_auth.pw_save = G_PASSWORD_SAVE_NEVER;
+ dav_backend->auth_info.proxy_auth.pw_save = G_PASSWORD_SAVE_NEVER;
+ dav_backend->auth_info.interactive = TRUE;
+
+ dav_backend->last_good_path = NULL;
+
+ msg_opts = soup_message_new_from_uri (SOUP_METHOD_OPTIONS, http_backend->mount_base);
+ dav_message_connect_signals (msg_opts, job->backend);
+
+ g_vfs_backend_dav_send_async (job->backend, msg_opts, try_mount_opts_cb, job);
+}
+
+static void
+try_mount_resolve_cb (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ GVfsJobMount *job = user_data;
+ GVfsBackendDav *dav_backend = G_VFS_BACKEND_DAV (job->backend);
+ GVfsBackendHttp *http_backend = G_VFS_BACKEND_HTTP (job->backend);
+ GError *error = NULL;
+
+ if (!g_vfs_dns_sd_resolver_resolve_finish (dav_backend->resolver,
+ result,
+ &error))
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+
+ g_signal_connect (dav_backend->resolver,
+ "changed",
+ (GCallback) dns_sd_resolver_changed,
+ dav_backend);
+
+ http_backend->mount_base = dav_uri_from_dns_sd_resolver (dav_backend);
+
+ try_mount_send_opts (job);
+}
+
static gboolean
try_mount (GVfsBackend *backend,
GVfsJobMount *job,
@@ -2347,8 +2409,6 @@ try_mount (GVfsBackend *backend,
{
GVfsBackendDav *dav_backend = G_VFS_BACKEND_DAV (backend);
GVfsBackendHttp *http_backend = G_VFS_BACKEND_HTTP (backend);
- SoupMessage *msg_opts;
- GUri *mount_base;
const char *host;
const char *type;
@@ -2361,57 +2421,20 @@ try_mount (GVfsBackend *backend,
/* resolve DNS-SD style URIs */
if ((strcmp (type, "dav+sd") == 0 || strcmp (type, "davs+sd") == 0) && host != NULL)
{
- GError *error = NULL;
dav_backend->resolver = g_vfs_dns_sd_resolver_new_for_encoded_triple (host, "u");
- if (!g_vfs_dns_sd_resolver_resolve_sync (dav_backend->resolver,
- NULL,
- &error))
- {
- g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
- g_error_free (error);
- return TRUE;
- }
- g_signal_connect (dav_backend->resolver,
- "changed",
- (GCallback) dns_sd_resolver_changed,
- dav_backend);
-
- mount_base = dav_uri_from_dns_sd_resolver (dav_backend);
+ g_vfs_dns_sd_resolver_resolve (dav_backend->resolver,
+ G_VFS_JOB (job)->cancellable,
+ try_mount_resolve_cb,
+ job);
}
else
#endif
{
- mount_base = g_mount_spec_to_dav_uri (mount_spec);
+ http_backend->mount_base = g_mount_spec_to_dav_uri (mount_spec);
+ try_mount_send_opts (job);
}
- if (mount_base == NULL)
- {
- g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
- G_IO_ERROR_INVALID_ARGUMENT,
- _("Invalid mount spec"));
- return TRUE;
- }
-
- http_backend->mount_base = mount_base;
-
- soup_session_add_feature_by_type (http_backend->session,
- SOUP_TYPE_AUTH_NEGOTIATE);
- soup_session_add_feature_by_type (http_backend->session,
- SOUP_TYPE_AUTH_NTLM);
-
- dav_backend->auth_info.mount_source = g_object_ref (mount_source);
- dav_backend->auth_info.server_auth.username = g_strdup (g_uri_get_user (mount_base));
- dav_backend->auth_info.server_auth.pw_save = G_PASSWORD_SAVE_NEVER;
- dav_backend->auth_info.proxy_auth.pw_save = G_PASSWORD_SAVE_NEVER;
- dav_backend->auth_info.interactive = TRUE;
-
- dav_backend->last_good_path = NULL;
-
- msg_opts = soup_message_new_from_uri (SOUP_METHOD_OPTIONS, mount_base);
- dav_message_connect_signals (msg_opts, backend);
-
- g_vfs_backend_dav_send_async (backend, msg_opts, try_mount_opts_cb, job);
return TRUE;
}