Browse Source

Fixed DATA connection initialization logic

Factored out error checking from ftpfs_initconn into
ftpfs_init_data_socket and fixed the logic of the initialization of DATA
connection. Now initialization of passive connection is retried if
needed after the failure to open the socket.

Got rid of goto statements and divided the code in two parts (passive &
active). Initial state is now properly restored after the function runs.

Signed-off-by: Yury V. Zaytsev <yury@shurup.com>
Yury V. Zaytsev 14 years ago
parent
commit
6586dcf78b
1 changed files with 41 additions and 28 deletions
  1. 41 28
      lib/vfs/mc-vfs/ftpfs.c

+ 41 - 28
lib/vfs/mc-vfs/ftpfs.c

@@ -1180,7 +1180,14 @@ ftpfs_init_data_socket (struct vfs_class *me, struct vfs_s_super *super,
         ERRNOR (EINVAL, -1);
     }
 
-    return socket (data_addr->ss_family, SOCK_STREAM, IPPROTO_TCP);
+    result = socket (data_addr->ss_family, SOCK_STREAM, IPPROTO_TCP);
+
+    if (result < 0)
+    {
+        print_vfs_message (_("ftpfs: could not create socket: %s"), unix_error_string (errno));
+        return -1;
+    } else
+        return result;
 }
 
 /* Initialize FTP DATA connection */
@@ -1189,49 +1196,55 @@ ftpfs_initconn (struct vfs_class *me, struct vfs_s_super *super)
 {
     struct sockaddr_storage data_addr;
     socklen_t data_addrlen;
-    int data_sock;
-
-  again:
-
-    data_sock = ftpfs_init_data_socket (me, super, &data_addr, &data_addrlen);
-
-    if (data_sock < 0)
-    {
-        if (SUP.use_passive_connection)
-        {
-            print_vfs_message (_("ftpfs: could not setup passive mode: %s"),
-                               unix_error_string (errno));
-            SUP.use_passive_connection = 0;
-            goto again;
-        }
 
-        print_vfs_message (_("ftpfs: could not create socket: %s"), unix_error_string (errno));
-        return -1;
-    }
+    /*
+     * Don't factor socket initialization out of these conditionals,
+     * because ftpfs_init_data_socket initializes it in different way
+     * depending on use_passive_connection flag.
+     */
 
+    /* Try to establish a passive connection first (if requested) */
     if (SUP.use_passive_connection)
     {
+        int data_sock;
+        data_sock = ftpfs_init_data_socket (me, super, &data_addr, &data_addrlen);
+
+        if (data_sock < 0)
+            return -1;
 
         if (ftpfs_setup_passive (me, super, data_sock, &data_addr, &data_addrlen))
             return data_sock;
 
-        SUP.use_passive_connection = 0;
         print_vfs_message (_("ftpfs: could not setup passive mode"));
+        SUP.use_passive_connection = 0;
 
         close (data_sock);
-        goto again;
     }
 
-    /* If passive setup fails, fallback to active connections */
-    if ((bind (data_sock, (struct sockaddr *) &data_addr, data_addrlen) == 0) &&
-        (getsockname (data_sock, (struct sockaddr *) &data_addr, &data_addrlen) == 0) &&
-        (listen (data_sock, 1) == 0))
+    /* If passive setup is diabled or failed, fallback to active connections */
+    if (!SUP.use_passive_connection)
     {
-        if (ftpfs_setup_active (me, super, data_addr, data_addrlen))
-            return data_sock;
+        int data_sock;
+        data_sock = ftpfs_init_data_socket (me, super, &data_addr, &data_addrlen);
+
+        if (data_sock < 0)
+            return -1;
+
+        if ((bind (data_sock, (struct sockaddr *) &data_addr, data_addrlen) == 0) &&
+            (getsockname (data_sock, (struct sockaddr *) &data_addr, &data_addrlen) == 0) &&
+            (listen (data_sock, 1) == 0))
+        {
+            if (ftpfs_setup_active (me, super, data_addr, data_addrlen))
+                return data_sock;
+        }
+
+        close (data_sock);
     }
 
-    close (data_sock);
+    /* Restore the initial value of use_passive_connection (for subsequent retries) */
+    SUP.use_passive_connection = SUP.proxy ? ftpfs_use_passive_connections_over_proxy :
+                                             ftpfs_use_passive_connections;
+
     ftpfs_errno = EIO;
     return -1;
 }