gvfs r2091 - in trunk: . daemon



Author: otte
Date: Mon Nov 17 11:11:09 2008
New Revision: 2091
URL: http://svn.gnome.org/viewvc/gvfs?rev=2091&view=rev

Log:
* daemon/gvfsbackendftp.c:
(ftp_connection_ensure_data_connection_epsv),
(ftp_connection_ensure_data_connection_pasv):
Add workarounds for EPSV/PASV data connection failures.
- 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).


Modified:
   trunk/ChangeLog
   trunk/daemon/gvfsbackendftp.c

Modified: trunk/daemon/gvfsbackendftp.c
==============================================================================
--- trunk/daemon/gvfsbackendftp.c	(original)
+++ trunk/daemon/gvfsbackendftp.c	Mon Nov 17 11:11:09 2008
@@ -107,6 +107,11 @@
   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 @@
 
   FtpFeatures		features;
   FtpSystem		system;
+  FtpWorkarounds	workarounds;
 
   SoupSocket *		commands;
   gchar *	      	read_buffer;
@@ -816,10 +822,14 @@
   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;
@@ -837,15 +847,22 @@
 		      soup_address_get_name (soup_socket_get_remote_address (conn->commands)),
 		      port);
 
-  return ftp_connection_open_data_connection (conn, addr);
+  connected = ftp_connection_open_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
 ftp_connection_ensure_data_connection_pasv (FtpConnection *conn)
 {
   guint ip1, ip2, ip3, ip4, port1, port2;
-  char *ip;
   const char *s;
+  gboolean connected;
   SoupAddress *addr;
   guint status;
 
@@ -860,8 +877,8 @@
   for (s = conn->read_buffer; *s; s++)
     {
       if (sscanf (s, "%u,%u,%u,%u,%u,%u", 
-                 &ip1, &ip2, &ip3, &ip4, 
-                 &port1, &port2) == 6)
+		 &ip1, &ip2, &ip3, &ip4, 
+		 &port1, &port2) == 6)
        break;
     }
   if (*s == 0)
@@ -871,10 +888,33 @@
       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))
+    {
+      char *ip;
+
+      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_open_data_connection (conn, addr);
+      if (!connected)
+        {
+          /* set workaround flag (see below), so we don't try this 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);
+	}
+    }
+
+  /* Workaround code:
+   * Various ftp servers aren;t setup correctly when behind a NAT. They report
+   * their own IP address (like 10.0.0.4) and not the address in front of the
+   * NAT. But this is likely the same address that we connected to with our
+   * command connetion. So if the address given by PASV fails, we fall back 
+   * to the address of the command stream.
+   */
+  addr = soup_address_new (soup_address_get_name (soup_socket_get_remote_address (conn->commands)),
+			   port1 << 8 | port2);
   return ftp_connection_open_data_connection (conn, addr);
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]