Commit 429d3006 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

- Fix (?) handling of EPSV non-compliant FTP servers

with EPSV compliant NAT
- Fix socket error value check
parent fe087a38
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment