summaryrefslogtreecommitdiff
path: root/daemon
diff options
context:
space:
mode:
authorBenjamin Otte <otte@src.gnome.org>2008-11-17 10:51:17 +0000
committerBenjamin Otte <otte@src.gnome.org>2008-11-17 10:51:17 +0000
commit6dd854f24ece67004496f882c5ffe93ddea8377e (patch)
treeeb8fc4840209937c37ee7d2dab74f7f1d05eb1e4 /daemon
parent2ccc2a298abc5ae3d07b50607d733b2437491f96 (diff)
downloadgvfs-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.c119
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