[PATCH 5/8] Add workarounds for EPSV/PASV data connection failures.
- From: Andreas Henriksson <andreas fatal se>
- To: gvfs-list gnome org
- Cc: Andreas Henriksson <andreas fatal se>, Oliver <oliver joos schweiz org>, Benjamin Otte <otte gnome org>
- Subject: [PATCH 5/8] Add workarounds for EPSV/PASV data connection failures.
- Date: Sat, 15 Nov 2008 18:03:46 +0100
- don't use EPSV if we get successful return codes but fails to connect.
- don't use address in PASV response if we fail to connect to it
(use the same address as the command connection is established to).
---
daemon/gvfsbackendftp.c | 51 ++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/daemon/gvfsbackendftp.c b/daemon/gvfsbackendftp.c
index b05e164..bddab49 100644
--- a/daemon/gvfsbackendftp.c
+++ b/daemon/gvfsbackendftp.c
@@ -107,6 +107,11 @@ typedef enum {
FTP_SYSTEM_WINDOWS
} FtpSystem;
+typedef enum {
+ FTP_WORKAROUND_BROKEN_EPSV = (1 << 0),
+ FTP_WORKAROUND_PASV_ADDR = (1 << 1),
+} FtpWorkarounds;
+
struct _GVfsBackendFtp
{
GVfsBackend backend;
@@ -147,6 +152,7 @@ struct _FtpConnection
FtpFeatures features;
FtpSystem system;
+ FtpWorkarounds workarounds;
SoupSocket * commands;
gchar * read_buffer;
@@ -811,10 +817,14 @@ ftp_connection_ensure_data_connection_epsv (FtpConnection *conn)
guint port;
SoupAddress *addr;
guint status;
+ gboolean connected;
if ((conn->features & FTP_FEATURE_EPSV) == 0)
return FALSE;
+ if (conn->workarounds & FTP_WORKAROUND_BROKEN_EPSV)
+ return FALSE;
+
status = ftp_connection_send (conn, RESPONSE_PASS_500, "EPSV");
if (STATUS_GROUP (status) != 2)
return FALSE;
@@ -832,7 +842,14 @@ ftp_connection_ensure_data_connection_epsv (FtpConnection *conn)
soup_address_get_name (soup_socket_get_remote_address (conn->commands)),
port);
- return _ftp_connection_ensure_data_connection (conn, addr);
+ connected = _ftp_connection_ensure_data_connection (conn, addr);
+ if (!connected)
+ {
+ DEBUG("Successful EPSV response code, but data connection failed. Enabling FTP_WORKAROUND_BROKEN_EPSV.\n");
+ conn->workarounds |= FTP_WORKAROUND_BROKEN_EPSV;
+ g_clear_error(&conn->error);
+ }
+ return connected;
}
static gboolean
@@ -866,11 +883,35 @@ ftp_connection_ensure_data_connection_pasv (FtpConnection *conn)
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);
+ if (conn->workarounds & FTP_WORKAROUND_PASV_ADDR)
+ {
+ SoupAddress *raddr;
+
+ raddr = soup_socket_get_remote_address (conn->commands);
+ addr = soup_address_new (soup_address_get_name (raddr),
+ port1 << 8 | port2);
+ return _ftp_connection_ensure_data_connection (conn, addr);
+ }
+ else
+ {
+ gboolean connected;
+
+ ip = g_strdup_printf ("%u.%u.%u.%u", ip1, ip2, ip3, ip4);
+ addr = soup_address_new (ip, port1 << 8 | port2);
+ g_free (ip);
+
+ connected = _ftp_connection_ensure_data_connection (conn, addr);
+ if (!connected)
+ {
+ /* enable workaround and try again */
+ DEBUG("Successfull PASV response but data connection failed. Enabling FTP_WORKAROUND_PASV_ADDR.\n");
+ conn->workarounds |= FTP_WORKAROUND_PASV_ADDR;
+ g_clear_error(&conn->error);
+ return ftp_connection_ensure_data_connection_pasv (conn);
+ }
+ return connected;
+ }
- return _ftp_connection_ensure_data_connection (conn, addr);
}
static gboolean
--
1.5.6.5
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]