[PATCH 4/8] 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.
---
 daemon/gvfsbackendftp.c |  119 ++++++++++++++++++++++++++++++-----------------
 1 files changed, 76 insertions(+), 43 deletions(-)

diff --git a/daemon/gvfsbackendftp.c b/daemon/gvfsbackendftp.c
index 109b776..b05e164 100644
--- a/daemon/gvfsbackendftp.c
+++ b/daemon/gvfsbackendftp.c
@@ -779,42 +779,78 @@ ftp_connection_use (FtpConnection *conn)
 }
 
 static gboolean
-ftp_connection_ensure_data_connection (FtpConnection *conn)
+_ftp_connection_ensure_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_ensure_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++)
     {
@@ -829,30 +865,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_ensure_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
-- 
1.5.6.5



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