/*****************************************************************************
* Preamble
*****************************************************************************/
-#include <stdlib.h>
#include <vlc/vlc.h>
#include <errno.h>
struct addrinfo hints, *res, *ptr;
const char *psz_realhost;
char *psz_socks;
- int i_realport, i_val, i_handle = -1, i_saved_errno = 0;
- unsigned u_errstep = 0;
+ int i_realport, i_val, i_handle = -1;
if( i_port == 0 )
i_port = 80; /* historical VLC thing */
memset( &hints, 0, sizeof( hints ) );
hints.ai_socktype = SOCK_STREAM;
- psz_socks = var_CreateGetString( p_this, "socks" );
- if( *psz_socks && *psz_socks != ':' )
+ psz_socks = var_CreateGetNonEmptyString( p_this, "socks" );
+ if( psz_socks != NULL )
{
char *psz = strchr( psz_socks, ':' );
psz_realhost = psz_socks;
i_realport = ( psz != NULL ) ? atoi( psz ) : 1080;
+ hints.ai_flags &= ~AI_NUMERICHOST;
- msg_Dbg( p_this, "net: connecting to %s port %d for %s port %d",
- psz_realhost, i_realport, psz_host, i_port );
+ msg_Dbg( p_this, "net: connecting to %s port %d (SOCKS) "
+ "for %s port %d", psz_realhost, i_realport,
+ psz_host, i_port );
+
+ /* We only implement TCP with SOCKS */
+ switch( type )
+ {
+ case 0:
+ type = SOCK_STREAM;
+ case SOCK_STREAM:
+ break;
+ default:
+ msg_Err( p_this, "Socket type not supported through SOCKS" );
+ free( psz_socks );
+ return -1;
+ }
+ switch( proto )
+ {
+ case 0:
+ proto = IPPROTO_TCP;
+ case IPPROTO_TCP:
+ break;
+ default:
+ msg_Err( p_this, "Transport not supported through SOCKS" );
+ free( psz_socks );
+ return -1;
+ }
}
else
{
}
i_val = vlc_getaddrinfo( p_this, psz_realhost, i_realport, &hints, &res );
+ free( psz_socks );
+
if( i_val )
{
msg_Err( p_this, "cannot resolve %s port %d : %s", psz_realhost,
i_realport, vlc_gai_strerror( i_val ) );
- free( psz_socks );
return -1;
}
proto ?: ptr->ai_protocol );
if( fd == -1 )
{
- if( u_errstep <= 0 )
- {
- u_errstep = 1;
- i_saved_errno = net_errno;
- }
msg_Dbg( p_this, "socket error: %s", strerror( net_errno ) );
continue;
}
{
socklen_t i_val_size = sizeof( i_val );
div_t d;
- struct timeval tv;
vlc_value_t timeout;
if( net_errno != EINPROGRESS )
{
- if( u_errstep <= 1 )
- {
- u_errstep = 2;
- i_saved_errno = net_errno;
- }
- msg_Dbg( p_this, "connect error: %s", strerror( net_errno ) );
+ msg_Err( p_this, "connection failed: %s",
+ strerror( net_errno ) );
goto next_ai;
}
msg_Dbg( p_this, "connection in progress" );
for (;;)
{
- fd_set fds;
+ struct pollfd ufd = { .fd = fd, .events = POLLOUT };
int i_ret;
if( p_this->b_die )
msg_Dbg( p_this, "connection aborted" );
net_Close( fd );
vlc_freeaddrinfo( res );
- free( psz_socks );
return -1;
}
- /* Initialize file descriptor set */
- FD_ZERO( &fds );
- FD_SET( fd, &fds );
-
/*
* We'll wait 0.1 second if nothing happens
* NOTE:
* time out will be shortened if we catch a signal (EINTR)
*/
- tv.tv_sec = 0;
- tv.tv_usec = (d.quot > 0) ? 100000 : (1000 * d.rem);
-
- i_ret = select( fd + 1, NULL, &fds, NULL, &tv );
+ i_ret = poll (&ufd, 1, (d.quot > 0) ? 100 : d.rem);
if( i_ret == 1 )
break;
if( ( i_ret == -1 ) && ( net_errno != EINTR ) )
{
- msg_Warn( p_this, "select error: %s",
+ msg_Err( p_this, "connection polling error: %s",
strerror( net_errno ) );
goto next_ai;
}
if( d.quot <= 0 )
{
- msg_Dbg( p_this, "select timed out" );
- if( u_errstep <= 2 )
- {
- u_errstep = 3;
- i_saved_errno = ETIMEDOUT;
- }
+ msg_Warn( p_this, "connection timed out" );
goto next_ai;
}
if( getsockopt( fd, SOL_SOCKET, SO_ERROR, (void*)&i_val,
&i_val_size ) == -1 || i_val != 0 )
{
- u_errstep = 4;
- i_saved_errno = i_val;
- msg_Dbg( p_this, "connect error (via getsockopt): %s",
+ msg_Err( p_this, "connection failed: %s",
net_strerror( i_val ) );
goto next_ai;
}
vlc_freeaddrinfo( res );
if( i_handle == -1 )
- {
- msg_Err( p_this, "Connection to %s port %d failed: %s", psz_host,
- i_port, net_strerror( i_saved_errno ) );
- free( psz_socks );
return -1;
- }
- if( *psz_socks && *psz_socks != ':' )
+ if( psz_socks != NULL )
{
+ /* NOTE: psz_socks already free'd! */
char *psz_user = var_CreateGetString( p_this, "socks-user" );
char *psz_pwd = var_CreateGetString( p_this, "socks-pwd" );
if( SocksHandshakeTCP( p_this, i_handle, 5, psz_user, psz_pwd,
psz_host, i_port ) )
{
- msg_Err( p_this, "Failed to use the SOCKS server" );
+ msg_Err( p_this, "SOCKS handshake failed" );
net_Close( i_handle );
i_handle = -1;
}
free( psz_user );
free( psz_pwd );
}
- free( psz_socks );
return i_handle;
}
i_socks_version = 5;
}
- if( i_socks_version == 5 &&
+ if( i_socks_version == 5 &&
SocksNegociate( p_obj, fd, i_socks_version,
psz_socks_user, psz_socks_passwd ) )
return VLC_EGENERIC;
struct addrinfo hints, *p_res;
/* v4 only support ipv4 */
- memset (&hints, 0, sizeof (hints));
+ memset (&hints, 0, sizeof (hints));
hints.ai_family = AF_INET;
if( vlc_getaddrinfo( p_obj, psz_host, 0, &hints, &p_res ) )
return VLC_EGENERIC;
i_len = buffer[4] + 2;
else if( buffer[3] == 0x04 )
i_len = 16-1+2;
- else
+ else
return VLC_EGENERIC;
if( net_Read( p_obj, fd, NULL, buffer, i_len, VLC_TRUE ) != i_len )