]> git.sesse.net Git - vlc/commitdiff
- Fix (?) handling of EPSV non-compliant FTP servers
authorRémi Denis-Courmont <rem@videolan.org>
Sat, 9 Jul 2005 17:19:06 +0000 (17:19 +0000)
committerRémi Denis-Courmont <rem@videolan.org>
Sat, 9 Jul 2005 17:19:06 +0000 (17:19 +0000)
with EPSV compliant NAT
- Fix socket error value check

modules/access/ftp.c

index 8e32886b93601146c086e00eb95ac48094f28804..b00c851e8e0684f3d7b184a3512e9753bd40f067 100644 (file)
@@ -99,61 +99,19 @@ static int  ftp_ReadCommand( access_t *, int *, char ** );
 static int  ftp_StartStream( access_t *, int64_t );
 static int  ftp_StopStream ( access_t *);
 
-/****************************************************************************
- * Open: connect to ftp server and ask for file
- ****************************************************************************/
-static int Open( vlc_object_t *p_this )
+static int Connect( access_t *p_access, access_sys_t *p_sys )
 {
-    access_t     *p_access = (access_t*)p_this;
-    access_sys_t *p_sys;
-    char         *psz;
-
-    int          i_answer;
-    char         *psz_arg;
-
-    /* Init p_access */
-    p_access->pf_read = Read;
-    p_access->pf_block = NULL;
-    p_access->pf_seek = Seek;
-    p_access->pf_control = Control;
-    p_access->info.i_update = 0;
-    p_access->info.i_size = 0;
-    p_access->info.i_pos = 0;
-    p_access->info.b_eof = VLC_FALSE;
-    p_access->info.i_title = 0;
-    p_access->info.i_seekpoint = 0;
-    p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) );
-    memset( p_sys, 0, sizeof( access_sys_t ) );
-    p_sys->fd_cmd = -1;
-    p_sys->fd_data = -1;
-    p_sys->psz_epsv_ip = NULL;
-
-    /* *** Parse URL and get server addr/port and path *** */
-    psz = p_access->psz_path;
-    while( *psz == '/' )
-    {
-        psz++;
-    }
-    vlc_UrlParse( &p_sys->url, psz, 0 );
-
-    if( p_sys->url.psz_host == NULL || *p_sys->url.psz_host == '\0' )
-    {
-        msg_Err( p_access, "invalid server name" );
-        goto exit_error;
-    }
-    if( p_sys->url.i_port <= 0 )
-    {
-        p_sys->url.i_port = 21; /* default port */
-    }
+    int fd, i_answer;
+    char *psz;
 
     /* *** Open a TCP connection with server *** */
     msg_Dbg( p_access, "waiting for connection..." );
-    p_sys->fd_cmd = net_OpenTCP( p_access, p_sys->url.psz_host,
-                                 p_sys->url.i_port );
-    if( p_sys->fd_cmd < 0 )
+    p_sys->fd_cmd = fd = net_OpenTCP( p_access, p_sys->url.psz_host,
+                                      p_sys->url.i_port );
+    if( fd < 0 )
     {
         msg_Err( p_access, "failed to connect with server" );
-        goto exit_error;
+        return -1;
     }
 
     for( ;; )
@@ -166,7 +124,7 @@ static int Open( vlc_object_t *p_this )
     if( i_answer / 100 != 2 )
     {
         msg_Err( p_access, "connection rejected" );
-        goto exit_error;
+        return -1;
     }
 
     msg_Dbg( p_access, "connection accepted (%d)", i_answer );
@@ -176,7 +134,7 @@ static int Open( vlc_object_t *p_this )
         ftp_ReadCommand( p_access, &i_answer, NULL ) < 0 )
     {
         free( psz );
-        goto exit_error;
+        return -1;
     }
     free( psz );
 
@@ -192,7 +150,7 @@ static int Open( vlc_object_t *p_this )
                 ftp_ReadCommand( p_access, &i_answer, NULL ) < 0 )
             {
                 free( psz );
-                goto exit_error;
+                return -1;
             }
             free( psz );
 
@@ -209,34 +167,87 @@ static int Open( vlc_object_t *p_this )
                         ftp_ReadCommand( p_access, &i_answer, NULL ) < 0 )
                     {
                         free( psz );
-                        goto exit_error;
+                        return -1;
                     }
                     free( psz );
 
                     if( i_answer / 100 != 2 )
                     {
                         msg_Err( p_access, "account rejected" );
-                        goto exit_error;
+                        return -1;
                     }
                     msg_Dbg( p_access, "account accepted" );
                     break;
 
                 default:
                     msg_Err( p_access, "password rejected" );
-                    goto exit_error;
+                    return -1;
             }
             break;
         default:
             msg_Err( p_access, "user rejected" );
-            goto exit_error;
+            return -1;
     }
 
     /* Extended passive mode */
     if( ftp_SendCommand( p_access, "EPSV ALL" ) < 0 )
     {
         msg_Err( p_access, "cannot request extended passive mode" );
+        return -1;
+    }
+
+    return 0;
+}
+
+/****************************************************************************
+ * Open: connect to ftp server and ask for file
+ ****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+    access_t     *p_access = (access_t*)p_this;
+    access_sys_t *p_sys;
+    char         *psz;
+
+    int          i_answer;
+    char         *psz_arg;
+
+    /* Init p_access */
+    p_access->pf_read = Read;
+    p_access->pf_block = NULL;
+    p_access->pf_seek = Seek;
+    p_access->pf_control = Control;
+    p_access->info.i_update = 0;
+    p_access->info.i_size = 0;
+    p_access->info.i_pos = 0;
+    p_access->info.b_eof = VLC_FALSE;
+    p_access->info.i_title = 0;
+    p_access->info.i_seekpoint = 0;
+    p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) );
+    memset( p_sys, 0, sizeof( access_sys_t ) );
+    p_sys->fd_cmd = -1;
+    p_sys->fd_data = -1;
+    p_sys->psz_epsv_ip = NULL;
+
+    /* *** Parse URL and get server addr/port and path *** */
+    psz = p_access->psz_path;
+    while( *psz == '/' )
+    {
+        psz++;
+    }
+    vlc_UrlParse( &p_sys->url, psz, 0 );
+
+    if( p_sys->url.psz_host == NULL || *p_sys->url.psz_host == '\0' )
+    {
+        msg_Err( p_access, "invalid server name" );
         goto exit_error;
     }
+    if( p_sys->url.i_port <= 0 )
+    {
+        p_sys->url.i_port = 21; /* default port */
+    }
+
+    if( Connect( p_access, p_sys ) < 0 )
+        goto exit_error;
 
     if( ftp_ReadCommand( p_access, &i_answer, NULL ) == 2 )
     {
@@ -259,10 +270,25 @@ static int Open( vlc_object_t *p_this )
             goto exit_error;
         }
         p_sys->psz_epsv_ip = strdup( hostaddr );
+        if( p_sys->psz_epsv_ip == NULL )
+            goto exit_error;
     }
-    if( p_sys->psz_epsv_ip == NULL )
-        msg_Info( p_access, "FTP Extended passive mode disabled" );
+    else
+    {
+        /* If ESPV ALL fails, we fallback to PASV.
+         * We have to restart the connection in case there is a NAT that
+         * understands EPSV ALL in the way, and hence won't allow PASV on
+         * the initial connection.
+         */
+        net_Close( p_sys->fd_cmd );
+        p_sys->fd_cmd = -1;
+
+        if( ( p_sys->fd_cmd = Connect( p_access, p_sys ) ) < 0 )
+           goto exit_error;
 
+        msg_Info( p_access, "FTP Extended passive mode disabled" );
+    }
+    
     /* binary mode */
     if( ftp_SendCommand( p_access, "TYPE I" ) < 0 ||
         ftp_ReadCommand( p_access, &i_answer, NULL ) != 2 )
@@ -295,10 +321,8 @@ static int Open( vlc_object_t *p_this )
     return VLC_SUCCESS;
 
 exit_error:
-    if( p_sys->fd_cmd > 0 )
-    {
+    if( p_sys->fd_cmd >= 0 )
         net_Close( p_sys->fd_cmd );
-    }
     vlc_UrlClean( &p_sys->url );
     free( p_sys );
     return VLC_EGENERIC;