diff options
author | Benjamin Otte <otte@src.gnome.org> | 2008-11-17 10:51:17 +0000 |
---|---|---|
committer | Benjamin Otte <otte@src.gnome.org> | 2008-11-17 10:51:17 +0000 |
commit | 6dd854f24ece67004496f882c5ffe93ddea8377e (patch) | |
tree | eb8fc4840209937c37ee7d2dab74f7f1d05eb1e4 /daemon | |
parent | 2ccc2a298abc5ae3d07b50607d733b2437491f96 (diff) | |
download | gvfs-6dd854f24ece67004496f882c5ffe93ddea8377e.tar.gz |
Restructure ..._ensure_data_connection and fall back on PASV when EPSV
* daemon/gvfsbackendftp.c:
(_ftp_connection_ensure_data_connection),
(ftp_connection_ensure_data_connection_epsv),
(ftp_connection_ensure_data_connection_pasv),
(ftp_connection_ensure_data_connection):
Restructure ..._ensure_data_connection and fall back on PASV when EPSV
fails.
- split up ..._ensure_data_connection in subroutines
- make a full attempt to connect instead of relying on response
code from EPSV command.
- when EPSV data connection fails, try PASV.
svn path=/trunk/; revision=2090
Diffstat (limited to 'daemon')
-rw-r--r-- | daemon/gvfsbackendftp.c | 119 |
1 files changed, 76 insertions, 43 deletions
diff --git a/daemon/gvfsbackendftp.c b/daemon/gvfsbackendftp.c index 2800fb56..e517ae76 100644 --- a/daemon/gvfsbackendftp.c +++ b/daemon/gvfsbackendftp.c @@ -784,42 +784,78 @@ ftp_connection_use (FtpConnection *conn) } static gboolean -ftp_connection_ensure_data_connection (FtpConnection *conn) +ftp_connection_open_data_connection (FtpConnection *conn, SoupAddress *addr) { - guint ip1, ip2, ip3, ip4, port1, port2; - SoupAddress *addr; - const char *s; - char *ip; guint status; - if (conn->features & FTP_FEATURE_EPSV) + conn->data = soup_socket_new ("non-blocking", FALSE, + "remote-address", addr, + "timeout", TIMEOUT_IN_SECONDS, + NULL); + g_object_unref (addr); + status = soup_socket_connect_sync (conn->data, conn->job->cancellable); + if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { - status = ftp_connection_send (conn, RESPONSE_PASS_500, "EPSV"); - if (STATUS_GROUP (status) == 2) - { - s = strrchr (conn->read_buffer, '('); - if (s) - { - guint port; - s += 4; - port = strtoul (s, NULL, 10); - if (port != 0) - { - addr = soup_address_new ( + /* FIXME: better error messages depending on status please */ + g_set_error_literal (&conn->error, + G_IO_ERROR, + G_IO_ERROR_HOST_NOT_FOUND, + _("Could not connect to host")); + g_object_unref (conn->data); + conn->data = NULL; + return FALSE; + } + + return TRUE; +} + +static gboolean +ftp_connection_ensure_data_connection_epsv (FtpConnection *conn) +{ + const char *s; + guint port; + SoupAddress *addr; + guint status; + + if ((conn->features & FTP_FEATURE_EPSV) == 0) + return FALSE; + + status = ftp_connection_send (conn, RESPONSE_PASS_500, "EPSV"); + if (STATUS_GROUP (status) != 2) + return FALSE; + + s = strrchr (conn->read_buffer, '('); + if (!s) + return FALSE; + + s += 4; + port = strtoul (s, NULL, 10); + if (port == 0) + return FALSE; + + addr = soup_address_new ( soup_address_get_name (soup_socket_get_remote_address (conn->commands)), port); - goto have_address; - } - } - } - } + + return ftp_connection_open_data_connection (conn, addr); +} + +static gboolean +ftp_connection_ensure_data_connection_pasv (FtpConnection *conn) +{ + guint ip1, ip2, ip3, ip4, port1, port2; + char *ip; + const char *s; + SoupAddress *addr; + guint status; + /* only binary transfers please */ status = ftp_connection_send (conn, 0, "PASV"); if (status == 0) return FALSE; /* parse response and try to find the address to connect to. - * This code does the sameas curl. + * This code does the same as curl. */ for (s = conn->read_buffer; *s; s++) { @@ -834,30 +870,27 @@ ftp_connection_ensure_data_connection (FtpConnection *conn) _("Invalid reply")); return FALSE; } + ip = g_strdup_printf ("%u.%u.%u.%u", ip1, ip2, ip3, ip4); addr = soup_address_new (ip, port1 << 8 | port2); g_free (ip); -have_address: - conn->data = soup_socket_new ("non-blocking", FALSE, - "remote-address", addr, - "timeout", TIMEOUT_IN_SECONDS, - NULL); - g_object_unref (addr); - status = soup_socket_connect_sync (conn->data, conn->job->cancellable); - if (!SOUP_STATUS_IS_SUCCESSFUL (status)) - { - /* FIXME: better error messages depending on status please */ - g_set_error_literal (&conn->error, - G_IO_ERROR, - G_IO_ERROR_HOST_NOT_FOUND, - _("Could not connect to host")); - g_object_unref (conn->data); - conn->data = NULL; - return FALSE; - } + return ftp_connection_open_data_connection (conn, addr); +} - return TRUE; +static gboolean +ftp_connection_ensure_data_connection (FtpConnection *conn) +{ + if (ftp_connection_ensure_data_connection_epsv (conn)) + return TRUE; + + if (ftp_connection_in_error (conn)) + return FALSE; + + if (ftp_connection_ensure_data_connection_pasv (conn)) + return TRUE; + + return FALSE; } static void |