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

- Use the new vlc_getaddrinfo API

- Unduplicate TCP networking code (closes #101)
- Modify net_ListenTCP to support multiple listening sockets
- Update net_ListenTCP callers to the new API
parent c370d8ac
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Laurent Aimar <fenrir@via.ecp.fr> * Laurent Aimar <fenrir@via.ecp.fr>
* Rémi Denis-Courmont <courmisch # via.ecp.fr> * Rémi Denis-Courmont <rem # videolan.org>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -31,8 +31,6 @@ ...@@ -31,8 +31,6 @@
*****************************************************************************/ *****************************************************************************/
struct network_socket_t struct network_socket_t
{ {
unsigned int i_type;
char * psz_bind_addr; char * psz_bind_addr;
int i_bind_port; int i_bind_port;
...@@ -46,12 +44,6 @@ struct network_socket_t ...@@ -46,12 +44,6 @@ struct network_socket_t
size_t i_mtu; size_t i_mtu;
}; };
/* Socket types */
#define NETWORK_UDP 1
#define NETWORK_TCP 2
#define NETWORK_TCP_PASSIVE 3
typedef struct typedef struct
{ {
char *psz_protocol; char *psz_protocol;
...@@ -277,22 +269,21 @@ static inline char *vlc_b64_encode( char *src ) ...@@ -277,22 +269,21 @@ static inline char *vlc_b64_encode( char *src )
return ret; return ret;
} }
VLC_EXPORT( int, net_ConvertIPv4, ( uint32_t *p_addr, const char * psz_address ) );
/* Portable networking layer communication */ /* Portable networking layer communication */
#define net_OpenTCP(a, b, c) __net_OpenTCP(VLC_OBJECT(a), b, c) #define net_OpenTCP(a, b, c) __net_OpenTCP(VLC_OBJECT(a), b, c)
VLC_EXPORT( int, __net_OpenTCP, ( vlc_object_t *p_this, const char *psz_host, int i_port ) ); VLC_EXPORT( int, __net_OpenTCP, ( vlc_object_t *p_this, const char *psz_host, int i_port ) );
#define net_ListenTCP(a, b, c) __net_ListenTCP(VLC_OBJECT(a), b, c) #define net_ListenTCP(a, b, c) __net_ListenTCP(VLC_OBJECT(a), b, c)
VLC_EXPORT( int, __net_ListenTCP, ( vlc_object_t *p_this, char *psz_localaddr, int i_port ) ); VLC_EXPORT( int *, __net_ListenTCP, ( vlc_object_t *, const char *, int ) );
#define net_Accept(a, b, c) __net_Accept(VLC_OBJECT(a), b, c) #define net_Accept(a, b, c) __net_Accept(VLC_OBJECT(a), b, c)
VLC_EXPORT( int, __net_Accept, ( vlc_object_t *p_this, int fd_listen, mtime_t i_wait ) ); VLC_EXPORT( int, __net_Accept, ( vlc_object_t *, int *, mtime_t ) );
#define net_OpenUDP(a, b, c, d, e ) __net_OpenUDP(VLC_OBJECT(a), b, c, d, e) #define net_OpenUDP(a, b, c, d, e ) __net_OpenUDP(VLC_OBJECT(a), b, c, d, e)
VLC_EXPORT( int, __net_OpenUDP, ( vlc_object_t *p_this, char *psz_bind, int i_bind, char *psz_server, int i_server ) ); VLC_EXPORT( int, __net_OpenUDP, ( vlc_object_t *p_this, char *psz_bind, int i_bind, char *psz_server, int i_server ) );
VLC_EXPORT( void, net_Close, ( int fd ) ); VLC_EXPORT( void, net_Close, ( int fd ) );
VLC_EXPORT( void, net_ListenClose, ( int *fd ) );
/* Functions to read from or write to the networking layer */ /* Functions to read from or write to the networking layer */
...@@ -323,4 +314,83 @@ VLC_EXPORT( int, net_Printf, ( vlc_object_t *p_this, int fd, v_socket_t *, const ...@@ -323,4 +314,83 @@ VLC_EXPORT( int, net_Printf, ( vlc_object_t *p_this, int fd, v_socket_t *, const
#define net_vaPrintf(a,b,c,d,e) __net_vaPrintf(VLC_OBJECT(a),b,c,d,e) #define net_vaPrintf(a,b,c,d,e) __net_vaPrintf(VLC_OBJECT(a),b,c,d,e)
VLC_EXPORT( int, __net_vaPrintf, ( vlc_object_t *p_this, int fd, v_socket_t *, const char *psz_fmt, va_list args ) ); VLC_EXPORT( int, __net_vaPrintf, ( vlc_object_t *p_this, int fd, v_socket_t *, const char *psz_fmt, va_list args ) );
/* Portable network names/addresses resolution layer */
/* GAI error codes */
# ifndef EAI_BADFLAGS
# define EAI_BADFLAGS -1
# endif
# ifndef EAI_NONAME
# define EAI_NONAME -2
# endif
# ifndef EAI_AGAIN
# define EAI_AGAIN -3
# endif
# ifndef EAI_FAIL
# define EAI_FAIL -4
# endif
# ifndef EAI_NODATA
# define EAI_NODATA -5
# endif
# ifndef EAI_FAMILY
# define EAI_FAMILY -6
# endif
# ifndef EAI_SOCKTYPE
# define EAI_SOCKTYPE -7
# endif
# ifndef EAI_SERVICE
# define EAI_SERVICE -8
# endif
# ifndef EAI_ADDRFAMILY
# define EAI_ADDRFAMILY -9
# endif
# ifndef EAI_MEMORY
# define EAI_MEMORY -10
# endif
# ifndef EAI_SYSTEM
# define EAI_SYSTEM -11
# endif
# ifndef NI_MAXHOST
# define NI_MAXHOST 1025
# define NI_MAXSERV 32
# endif
# ifndef NI_NUMERICHOST
# define NI_NUMERICHOST 0x01
# define NI_NUMERICSERV 0x02
# define NI_NOFQDN 0x04
# define NI_NAMEREQD 0x08
# define NI_DGRAM 0x10
# endif
# ifndef HAVE_STRUCT_ADDRINFO
struct addrinfo
{
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
size_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};
# define AI_PASSIVE 1
# define AI_CANONNAME 2
# define AI_NUMERICHOST 4
# endif /* if !HAVE_STRUCT_ADDRINFO */
/*** libidn support ***/
# ifndef AI_IDN
# define AI_IDN 0
# define AI_CANONIDN 0
# endif
VLC_EXPORT( const char *, vlc_gai_strerror, ( int ) );
VLC_EXPORT( int, vlc_getnameinfo, ( vlc_object_t *, const struct sockaddr *, int, char *, int, char *, int, int ) );
VLC_EXPORT( int, vlc_getaddrinfo, ( vlc_object_t *, const char *, const char *, const struct addrinfo *, struct addrinfo ** ) );
VLC_EXPORT( void, vlc_freeaddrinfo, ( struct addrinfo * ) );
#endif #endif
...@@ -92,7 +92,7 @@ static int AudioConfig ( vlc_object_t *, char const *, ...@@ -92,7 +92,7 @@ static int AudioConfig ( vlc_object_t *, char const *,
struct intf_sys_t struct intf_sys_t
{ {
int i_socket_listen; int *pi_socket_listen;
int i_socket; int i_socket;
char *psz_unix_path; char *psz_unix_path;
...@@ -173,7 +173,7 @@ static int Activate( vlc_object_t *p_this ) ...@@ -173,7 +173,7 @@ static int Activate( vlc_object_t *p_this )
intf_thread_t *p_intf = (intf_thread_t*)p_this; intf_thread_t *p_intf = (intf_thread_t*)p_this;
playlist_t *p_playlist; playlist_t *p_playlist;
char *psz_host, *psz_unix_path; char *psz_host, *psz_unix_path;
int i_socket = -1; int *pi_socket = NULL;
#if defined(HAVE_ISATTY) && !defined(WIN32) #if defined(HAVE_ISATTY) && !defined(WIN32)
/* Check that stdin is a TTY */ /* Check that stdin is a TTY */
...@@ -187,6 +187,8 @@ static int Activate( vlc_object_t *p_this ) ...@@ -187,6 +187,8 @@ static int Activate( vlc_object_t *p_this )
psz_unix_path = config_GetPsz( p_intf, "rc-unix" ); psz_unix_path = config_GetPsz( p_intf, "rc-unix" );
if( psz_unix_path ) if( psz_unix_path )
{ {
int i_socket;
#ifndef PF_LOCAL #ifndef PF_LOCAL
msg_Warn( p_intf, "your OS doesn't support filesystem sockets" ); msg_Warn( p_intf, "your OS doesn't support filesystem sockets" );
free( psz_unix_path ); free( psz_unix_path );
...@@ -227,10 +229,21 @@ static int Activate( vlc_object_t *p_this ) ...@@ -227,10 +229,21 @@ static int Activate( vlc_object_t *p_this )
net_Close( i_socket ); net_Close( i_socket );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
/* FIXME: we need a core function to merge listening sockets sets */
pi_socket = calloc( 2, sizeof( int ) );
if( pi_socket == NULL )
{
free( psz_unix_path );
net_Close( i_socket );
return VLC_ENOMEM;
}
pi_socket[0] = i_socket;
pi_socket[1] = -1;
#endif #endif
} }
if( ( i_socket == -1) && if( ( pi_socket == NULL ) &&
( psz_host = config_GetPsz( p_intf, "rc-host" ) ) != NULL ) ( psz_host = config_GetPsz( p_intf, "rc-host" ) ) != NULL )
{ {
vlc_url_t url; vlc_url_t url;
...@@ -239,7 +252,8 @@ static int Activate( vlc_object_t *p_this ) ...@@ -239,7 +252,8 @@ static int Activate( vlc_object_t *p_this )
msg_Dbg( p_intf, "base %s port %d", url.psz_host, url.i_port ); msg_Dbg( p_intf, "base %s port %d", url.psz_host, url.i_port );
if( (i_socket = net_ListenTCP(p_this, url.psz_host, url.i_port)) == -1) pi_socket = net_ListenTCP(p_this, url.psz_host, url.i_port);
if( pi_socket == NULL )
{ {
msg_Warn( p_intf, "can't listen to %s port %i", msg_Warn( p_intf, "can't listen to %s port %i",
url.psz_host, url.i_port ); url.psz_host, url.i_port );
...@@ -259,7 +273,7 @@ static int Activate( vlc_object_t *p_this ) ...@@ -259,7 +273,7 @@ static int Activate( vlc_object_t *p_this )
return VLC_ENOMEM; return VLC_ENOMEM;
} }
p_intf->p_sys->i_socket_listen = i_socket; p_intf->p_sys->pi_socket_listen = pi_socket;
p_intf->p_sys->i_socket = -1; p_intf->p_sys->i_socket = -1;
p_intf->p_sys->psz_unix_path = psz_unix_path; p_intf->p_sys->psz_unix_path = psz_unix_path;
...@@ -297,8 +311,7 @@ static void Deactivate( vlc_object_t *p_this ) ...@@ -297,8 +311,7 @@ static void Deactivate( vlc_object_t *p_this )
{ {
intf_thread_t *p_intf = (intf_thread_t*)p_this; intf_thread_t *p_intf = (intf_thread_t*)p_this;
if( p_intf->p_sys->i_socket_listen != -1 ) net_ListenClose( p_intf->p_sys->pi_socket_listen );
net_Close( p_intf->p_sys->i_socket_listen );
if( p_intf->p_sys->i_socket != -1 ) if( p_intf->p_sys->i_socket != -1 )
net_Close( p_intf->p_sys->i_socket ); net_Close( p_intf->p_sys->i_socket );
if( p_intf->p_sys->psz_unix_path != NULL ) if( p_intf->p_sys->psz_unix_path != NULL )
...@@ -477,11 +490,11 @@ static void Run( intf_thread_t *p_intf ) ...@@ -477,11 +490,11 @@ static void Run( intf_thread_t *p_intf )
char *psz_cmd, *psz_arg; char *psz_cmd, *psz_arg;
vlc_bool_t b_complete; vlc_bool_t b_complete;
if( p_intf->p_sys->i_socket_listen != - 1 && if( p_intf->p_sys->pi_socket_listen != NULL &&
p_intf->p_sys->i_socket == -1 ) p_intf->p_sys->i_socket == -1 )
{ {
p_intf->p_sys->i_socket = p_intf->p_sys->i_socket =
net_Accept( p_intf, p_intf->p_sys->i_socket_listen, 0 ); net_Accept( p_intf, p_intf->p_sys->pi_socket_listen, 0 );
} }
b_complete = ReadCommand( p_intf, p_buffer, &i_size ); b_complete = ReadCommand( p_intf, p_buffer, &i_size );
......
/***************************************************************************** /*****************************************************************************
* telnet.c: VLM interface plugin * telnet.c: VLM interface plugin
***************************************************************************** *****************************************************************************
* Copyright (C) 2000, 2001 VideoLAN * Copyright (C) 2000-2005 VideoLAN
* $Id$ * $Id$
* *
* Authors: Simon Latapie <garf@videolan.org> * Authors: Simon Latapie <garf@videolan.org>
...@@ -120,7 +120,7 @@ struct intf_sys_t ...@@ -120,7 +120,7 @@ struct intf_sys_t
{ {
telnet_client_t **clients; telnet_client_t **clients;
int i_clients; int i_clients;
int fd; int *pi_fd;
vlm_t *mediatheque; vlm_t *mediatheque;
}; };
...@@ -144,7 +144,8 @@ static int Open( vlc_object_t *p_this ) ...@@ -144,7 +144,8 @@ static int Open( vlc_object_t *p_this )
i_telnetport = config_GetInt( p_intf, "telnet-port" ); i_telnetport = config_GetInt( p_intf, "telnet-port" );
p_intf->p_sys = malloc( sizeof( intf_sys_t ) ); p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
if( ( p_intf->p_sys->fd = net_ListenTCP( p_intf , "", i_telnetport ) ) < 0 ) if( ( p_intf->p_sys->pi_fd = net_ListenTCP( p_intf , "", i_telnetport ) )
== NULL )
{ {
msg_Err( p_intf, "cannot listen for telnet" ); msg_Err( p_intf, "cannot listen for telnet" );
free( p_intf->p_sys ); free( p_intf->p_sys );
...@@ -178,7 +179,7 @@ static void Close( vlc_object_t *p_this ) ...@@ -178,7 +179,7 @@ static void Close( vlc_object_t *p_this )
} }
if( p_sys->clients != NULL ) free( p_sys->clients ); if( p_sys->clients != NULL ) free( p_sys->clients );
net_Close( p_sys->fd ); net_ListenClose( p_sys->pi_fd );
vlm_Delete( p_sys->mediatheque ); vlm_Delete( p_sys->mediatheque );
...@@ -203,7 +204,7 @@ static void Run( intf_thread_t *p_intf ) ...@@ -203,7 +204,7 @@ static void Run( intf_thread_t *p_intf )
int i_ret, i_len, fd, i; int i_ret, i_len, fd, i;
/* if a new client wants to communicate */ /* if a new client wants to communicate */
fd = net_Accept( p_intf, p_sys->fd, p_sys->i_clients > 0 ? 0 : -1 ); fd = net_Accept( p_intf, p_sys->pi_fd, p_sys->i_clients > 0 ? 0 : -1 );
if( fd > 0 ) if( fd > 0 )
{ {
telnet_client_t *cl; telnet_client_t *cl;
......
/***************************************************************************** /*****************************************************************************
* ipv4.c: IPv4 network abstraction layer * ipv4.c: IPv4 network abstraction layer
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001-2005 VideoLAN
* $Id$ * $Id$
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
...@@ -92,11 +92,6 @@ static int NetOpen( vlc_object_t * ); ...@@ -92,11 +92,6 @@ static int NetOpen( vlc_object_t * );
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
*****************************************************************************/ *****************************************************************************/
#define TIMEOUT_TEXT N_("TCP connection timeout in ms")
#define TIMEOUT_LONGTEXT N_( \
"Allows you to modify the default TCP connection timeout. This " \
"value should be set in millisecond units." )
#define MIFACE_TEXT N_("Multicast output interface") #define MIFACE_TEXT N_("Multicast output interface")
#define MIFACE_LONGTEXT N_( \ #define MIFACE_LONGTEXT N_( \
"Indicate here the multicast output interface. " \ "Indicate here the multicast output interface. " \
...@@ -106,9 +101,6 @@ vlc_module_begin(); ...@@ -106,9 +101,6 @@ vlc_module_begin();
set_description( _("IPv4 network abstraction layer") ); set_description( _("IPv4 network abstraction layer") );
set_capability( "network", 50 ); set_capability( "network", 50 );
set_callbacks( NetOpen, NULL ); set_callbacks( NetOpen, NULL );
add_integer( "ipv4-timeout", 5 * 1000, NULL, TIMEOUT_TEXT,
TIMEOUT_LONGTEXT, VLC_TRUE );
add_string( "miface-addr", NULL, NULL, MIFACE_TEXT, MIFACE_LONGTEXT, VLC_TRUE ); add_string( "miface-addr", NULL, NULL, MIFACE_TEXT, MIFACE_LONGTEXT, VLC_TRUE );
vlc_module_end(); vlc_module_end();
...@@ -501,230 +493,6 @@ static int OpenUDP( vlc_object_t * p_this, network_socket_t * p_socket ) ...@@ -501,230 +493,6 @@ static int OpenUDP( vlc_object_t * p_this, network_socket_t * p_socket )
return( 0 ); return( 0 );
} }
/*****************************************************************************
* SocketTCP: create a TCP socket
*****************************************************************************
* This function returns -1 in case of error.
*****************************************************************************/
static int SocketTCP( vlc_object_t * p_this )
{
int i_handle;
/* Open a SOCK_STREAM (TCP) socket, in the PF_INET domain, automatic (0)
* protocol */
if( (i_handle = socket( PF_INET, SOCK_STREAM, 0 )) == -1 )
{
#if defined(WIN32) || defined(UNDER_CE)
msg_Warn( p_this, "cannot create socket (%i)", WSAGetLastError() );
#else
msg_Warn( p_this, "cannot create socket (%s)", strerror(errno) );
#endif
return -1;
}
/* Set to non-blocking */
#if defined( WIN32 ) || defined( UNDER_CE )
{
unsigned long i_dummy = 1;
if( ioctlsocket( i_handle, FIONBIO, &i_dummy ) != 0 )
{
msg_Err( p_this, "cannot set socket to non-blocking mode" );
}
}
#else
{
int i_flags;
if( ( i_flags = fcntl( i_handle, F_GETFL, 0 ) ) < 0 ||
fcntl( i_handle, F_SETFL, i_flags | O_NONBLOCK ) < 0 )
{
msg_Err( p_this, "cannot set socket to non-blocking mode" );
}
}
#endif
return i_handle;
}
/*****************************************************************************
* OpenTCP: open a TCP socket
*****************************************************************************
* psz_server_addr, i_server_port : address and port used for the connect()
* system call. If i_server_port == 0, 80 is used.
* Other parameters are ignored.
* This function returns -1 in case of error.
*****************************************************************************/
static int OpenTCP( vlc_object_t * p_this, network_socket_t * p_socket )
{
char * psz_server_addr = p_socket->psz_server_addr;
int i_server_port = p_socket->i_server_port;
int i_handle;
struct sockaddr_in sock;
if( i_server_port == 0 )
{
i_server_port = 80;
}
if( (i_handle = SocketTCP( p_this )) == -1 )
return VLC_EGENERIC;
/* Build remote address */
if ( BuildAddr( &sock, psz_server_addr, i_server_port ) == -1 )
{
msg_Dbg( p_this, "could not build local address" );
goto error;
}
/* Connect the socket */
if( connect( i_handle, (struct sockaddr *) &sock, sizeof( sock ) ) == -1 )
{
#if defined( WIN32 ) || defined( UNDER_CE )
if( WSAGetLastError() == WSAEWOULDBLOCK )
#else
if( errno == EINPROGRESS )
#endif
{
int i_ret, i_opt, i_opt_size = sizeof( i_opt ), i_max_count;
struct timeval timeout;
vlc_value_t val;
fd_set fds;
if( var_Get( p_this, "ipv4-timeout", &val ) != VLC_SUCCESS )
{
var_Create( p_this, "ipv4-timeout",
VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
var_Get( p_this, "ipv4-timeout", &val );
}
i_max_count = val.i_int * 1000 / 100000 /* timeout.tv_usec */;
msg_Dbg( p_this, "connection in progress" );
do
{
if( p_this->b_die || i_max_count <= 0 )
{
msg_Dbg( p_this, "connection aborted" );
goto error;
}
i_max_count--;
/* Initialize file descriptor set */
FD_ZERO( &fds );
FD_SET( i_handle, &fds );
/* We'll wait 0.1 second if nothing happens */
timeout.tv_sec = 0;
timeout.tv_usec = 100000;
} while( ( i_ret = select( i_handle + 1, NULL, &fds, NULL,
&timeout ) ) == 0 ||
#if defined( WIN32 ) || defined( UNDER_CE )
( i_ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK ) );
#else
( i_ret < 0 && errno == EINTR ) );
#endif
if( i_ret < 0 )
{
msg_Warn( p_this, "cannot connect socket (select failed)" );
goto error;
}
#if !defined( SYS_BEOS ) && !defined( UNDER_CE )
if( getsockopt( i_handle, SOL_SOCKET, SO_ERROR, (void*)&i_opt,
&i_opt_size ) == -1 || i_opt != 0 )
{
msg_Warn( p_this, "cannot connect socket (SO_ERROR)" );
goto error;
}
#endif
}
else
{
#if defined(WIN32) || defined(UNDER_CE)
msg_Warn( p_this, "cannot connect socket (%i)", WSAGetLastError());
#else
msg_Warn( p_this, "cannot connect socket (%s)", strerror(errno) );
#endif
goto error;
}
}
p_socket->i_handle = i_handle;
p_socket->i_mtu = 0; /* There is no MTU notion in TCP */
return VLC_SUCCESS;
error:
close( i_handle );
return VLC_EGENERIC;
}
/*****************************************************************************
* ListenTCP: open a TCP passive socket (server-side)
*****************************************************************************
* psz_server_addr, i_server_port : address and port used for the bind()
* system call. If i_server_port == 0, 80 is used.
* Other parameters are ignored.
* This function returns -1 in case of error.
*****************************************************************************/
static int ListenTCP( vlc_object_t * p_this, network_socket_t * p_socket )
{
char * psz_server_addr = p_socket->psz_server_addr;
int i_server_port = p_socket->i_server_port;
int i_handle, i_dummy = 1;
struct sockaddr_in sock;
if( (i_handle = SocketTCP( p_this )) == -1 )
return VLC_EGENERIC;
if ( setsockopt( i_handle, SOL_SOCKET, SO_REUSEADDR,
(void *)&i_dummy, sizeof( i_dummy ) ) == -1 )
{
msg_Warn( p_this, "cannot configure socket (SO_REUSEADDR)" );
}
/* Build remote address */
if ( BuildAddr( &sock, psz_server_addr, i_server_port ) == -1 )
{
msg_Dbg( p_this, "could not build local address" );
return VLC_EGENERIC;
}
/* Bind the socket */
if( bind( i_handle, (struct sockaddr *) &sock, sizeof( sock )) == -1 )
{
#if defined(WIN32) || defined(UNDER_CE)
msg_Err( p_this, "cannot bind socket (%i)", WSAGetLastError());
#else
msg_Err( p_this, "cannot bind socket (%s)", strerror(errno) );
#endif
goto error;
}
/* Listen */
if( listen( i_handle, 100 ) == -1 )
{
#if defined(WIN32) || defined(UNDER_CE)
msg_Err( p_this, "cannot bring socket in listening mode (%i)",
WSAGetLastError());
#else
msg_Err( p_this, "cannot bring the socket in listening mode (%s)",
strerror(errno) );
#endif
goto error;
}
p_socket->i_handle = i_handle;
p_socket->i_mtu = 0; /* There is no MTU notion in TCP */
return VLC_SUCCESS;
error:
close( i_handle );
return VLC_EGENERIC;
}
/***************************************************************************** /*****************************************************************************
* NetOpen: wrapper around OpenUDP, ListenTCP and OpenTCP * NetOpen: wrapper around OpenUDP, ListenTCP and OpenTCP
*****************************************************************************/ *****************************************************************************/
...@@ -732,16 +500,5 @@ static int NetOpen( vlc_object_t * p_this ) ...@@ -732,16 +500,5 @@ static int NetOpen( vlc_object_t * p_this )
{ {
network_socket_t * p_socket = p_this->p_private; network_socket_t * p_socket = p_this->p_private;
if( p_socket->i_type == NETWORK_UDP )
{
return OpenUDP( p_this, p_socket ); return OpenUDP( p_this, p_socket );
}
else if( p_socket->i_type == NETWORK_TCP_PASSIVE )
{
return ListenTCP( p_this, p_socket );
}
else
{
return OpenTCP( p_this, p_socket );
}
} }
/***************************************************************************** /*****************************************************************************
* ipv6.c: IPv6 network abstraction layer * ipv6.c: IPv6 network abstraction layer
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 VideoLAN * Copyright (C) 2002-2005 VideoLAN
* $Id$ * $Id$
* *
* Authors: Alexis Guillard <alexis.guillard@bt.com> * Authors: Alexis Guillard <alexis.guillard@bt.com>
...@@ -260,6 +260,19 @@ static int OpenUDP( vlc_object_t * p_this, network_socket_t * p_socket ) ...@@ -260,6 +260,19 @@ static int OpenUDP( vlc_object_t * p_this, network_socket_t * p_socket )
return( -1 ); return( -1 );
} }
#ifdef WIN32
# ifdef IPV6_PROTECTION_LEVEL
if( ptr->ai_family == PF_INET6 )
{
i_val = PROTECTION_LEVEL_UNRESTRICTED;
setsockopt( fd, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, &i_val,
sizeof( i_val ) );
}
# else
# warning You are using outdated headers for Winsock !
# endif
#endif
/* We may want to reuse an already used socket */ /* We may want to reuse an already used socket */
i_opt = 1; i_opt = 1;
if( setsockopt( i_handle, SOL_SOCKET, SO_REUSEADDR, if( setsockopt( i_handle, SOL_SOCKET, SO_REUSEADDR,
...@@ -403,12 +416,8 @@ static int OpenUDP( vlc_object_t * p_this, network_socket_t * p_socket ) ...@@ -403,12 +416,8 @@ static int OpenUDP( vlc_object_t * p_this, network_socket_t * p_socket )
if( setsockopt( i_handle, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, if( setsockopt( i_handle, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
(void *)&ttl, sizeof( ttl ) ) < 0 ) (void *)&ttl, sizeof( ttl ) ) < 0 )
{ {
#ifdef HAVE_ERRNO_H
msg_Err( p_this, "failed to set multicast ttl (%s)", msg_Err( p_this, "failed to set multicast ttl (%s)",
strerror(errno) ); strerror(errno) );
#else
msg_Err( p_this, "failed to set multicast ttl" );
#endif
} }
} }
else else
...@@ -417,12 +426,8 @@ static int OpenUDP( vlc_object_t * p_this, network_socket_t * p_socket ) ...@@ -417,12 +426,8 @@ static int OpenUDP( vlc_object_t * p_this, network_socket_t * p_socket )
if( setsockopt( i_handle, IPPROTO_IPV6, IPV6_UNICAST_HOPS, if( setsockopt( i_handle, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
(void *)&ttl, sizeof( ttl ) ) < 0 ) (void *)&ttl, sizeof( ttl ) ) < 0 )
{ {
#ifdef HAVE_ERRNO_H
msg_Err( p_this, "failed to set unicast ttl (%s)", msg_Err( p_this, "failed to set unicast ttl (%s)",
strerror(errno) ); strerror(errno) );
#else
msg_Err( p_this, "failed to set unicast ttl" );
#endif
} }
} }
} }
...@@ -437,232 +442,6 @@ static int OpenUDP( vlc_object_t * p_this, network_socket_t * p_socket ) ...@@ -437,232 +442,6 @@ static int OpenUDP( vlc_object_t * p_this, network_socket_t * p_socket )
return( 0 ); return( 0 );
} }
/*****************************************************************************
* SocketTCP: create a TCP socket
*****************************************************************************
* This function returns -1 in case of error.
*****************************************************************************/
static int SocketTCP( vlc_object_t * p_this )
{
int i_handle;
/* Open a SOCK_STREAM (TCP) socket, in the PF_INET6 domain, automatic (0)
* protocol */
if( (i_handle = socket( PF_INET6, SOCK_STREAM, 0 )) == -1 )
{
#ifdef HAVE_ERRNO_H
msg_Warn( p_this, "cannot create socket (%s)", strerror(errno) );
#else
msg_Warn( p_this, "cannot create socket" );
#endif
return -1;
}
/* Set to non-blocking */
#if defined( WIN32 ) || defined( UNDER_CE )
{
unsigned long i_dummy = 1;
if( ioctlsocket( i_handle, FIONBIO, &i_dummy ) != 0 )
{
msg_Err( p_this, "cannot set socket to non-blocking mode" );
}
}
#elif defined( HAVE_ERRNO_H )
{
int i_flags;
if( ( i_flags = fcntl( i_handle, F_GETFL, 0 ) ) < 0 ||
fcntl( i_handle, F_SETFL, i_flags | O_NONBLOCK ) < 0 )
{
msg_Err( p_this, "cannot set socket to non-blocking mode" );
}
}
#endif
return i_handle;
}
/*****************************************************************************
* OpenTCP: open a TCP socket
*****************************************************************************
* psz_server_addr, i_server_port : address and port used for the connect()
* system call. If i_server_port == 0, 80 is used.
* Other parameters are ignored.
* This function returns -1 in case of error.
*****************************************************************************/
static int OpenTCP( vlc_object_t * p_this, network_socket_t * p_socket )
{
char * psz_server_addr = p_socket->psz_server_addr;
int i_server_port = p_socket->i_server_port;
int i_handle;
struct sockaddr_in6 sock;
if( i_server_port == 0 )
{
i_server_port = 80;
}
if( (i_handle = SocketTCP( p_this )) == -1 )
return VLC_EGENERIC;
/* Build remote address */
if ( BuildAddr( p_this, &sock, psz_server_addr, i_server_port ) == -1 )
goto error;
/* Connect the socket */
if( connect( i_handle, (struct sockaddr *) &sock, sizeof( sock ) ) == -1 )
{
#if defined( WIN32 ) || defined( UNDER_CE )
if( WSAGetLastError() == WSAEWOULDBLOCK )
#elif defined( HAVE_ERRNO_H )
if( errno == EINPROGRESS )
#else
if( 0 )
#endif
{
int i_ret, i_opt, i_opt_size = sizeof( i_opt ), i_max_count;
struct timeval timeout;
vlc_value_t val;
fd_set fds;
/* FIXME: There is no ipv6-timeout option, so we use ipv4-timeout
* instead */
if( !var_Type( p_this, "ipv4-timeout" ) )
{
var_Create( p_this, "ipv4-timeout",
VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
}
var_Get( p_this, "ipv4-timeout", &val );
i_max_count = val.i_int * 1000 / 100000 /* timeout.tv_usec */;
msg_Dbg( p_this, "connection in progress" );
do
{
if( p_this->b_die || i_max_count <= 0 )
{
msg_Dbg( p_this, "connection aborted" );
goto error;
}
i_max_count--;
/* Initialize file descriptor set */
FD_ZERO( &fds );
FD_SET( i_handle, &fds );
/* We'll wait 0.1 second if nothing happens */
timeout.tv_sec = 0;
timeout.tv_usec = 100000;
} while( ( i_ret = select( i_handle + 1, NULL, &fds, NULL,
&timeout ) ) == 0 ||
#if defined( WIN32 ) || defined( UNDER_CE )
( i_ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK ) );
#elif defined( HAVE_ERRNO_H )
( i_ret < 0 && errno == EINTR ) );
#else
( i_ret < 0 ) );
#endif
if( i_ret < 0 )
{
msg_Warn( p_this, "cannot connect socket (select failed)" );
goto error;
}
#if !defined( SYS_BEOS )
if( getsockopt( i_handle, SOL_SOCKET, SO_ERROR, (void*)&i_opt,
&i_opt_size ) == -1 || i_opt != 0 )
{
msg_Warn( p_this, "cannot connect socket (SO_ERROR)" );
goto error;
}
#endif
}
else
{
#if defined( HAVE_ERRNO_H )
msg_Warn( p_this, "cannot connect socket (%s)", strerror(errno) );
#else
msg_Warn( p_this, "cannot connect socket" );
#endif
goto error;
}
}
p_socket->i_handle = i_handle;
p_socket->i_mtu = 0; /* There is no MTU notion in TCP */
return VLC_SUCCESS;
error:
close( i_handle );
return VLC_EGENERIC;
}
/*****************************************************************************
* ListenTCP: open a TCP passive socket (server-side)
*****************************************************************************
* psz_server_addr, i_server_port : address and port used for the bind()
* system call. If i_server_port == 0, 80 is used.
* Other parameters are ignored.
* This function returns -1 in case of error.
*****************************************************************************/
static int ListenTCP( vlc_object_t * p_this, network_socket_t * p_socket )
{
char * psz_server_addr = p_socket->psz_server_addr;
int i_server_port = p_socket->i_server_port;
int i_handle, i_dummy = 1;
struct sockaddr_in6 sock;
if( (i_handle = SocketTCP( p_this )) == -1 )
return VLC_EGENERIC;
if ( setsockopt( i_handle, SOL_SOCKET, SO_REUSEADDR,
(void *)&i_dummy, sizeof( i_dummy ) ) == -1 )
{
msg_Warn( p_this, "cannot configure socket (SO_REUSEADDR)" );
}
/* Build remote address */
if ( BuildAddr( p_this, &sock, psz_server_addr, i_server_port ) == -1 )
{
msg_Dbg( p_this, "could not build local address" );
return VLC_EGENERIC;
}
/* Bind the socket */
if( bind( i_handle, (struct sockaddr *) &sock, sizeof( sock )) == -1 )
{
#ifdef HAVE_ERRNO_H
msg_Err( p_this, "cannot bind socket (%s)", strerror(errno) );
#else
msg_Err( p_this, "cannot bind socket" );
#endif
goto error;
}
/* Listen */
if( listen( i_handle, 100 ) == -1 )
{
#ifdef HAVE_ERRNO_H
msg_Err( p_this, "cannot bring the socket in listening mode (%s)",
strerror(errno) );
#else
msg_Err( p_this, "cannot bring the socket in listening mode" );
#endif
goto error;
}
p_socket->i_handle = i_handle;
p_socket->i_mtu = 0; /* There is no MTU notion in TCP */
return VLC_SUCCESS;
error:
close( i_handle );
return VLC_EGENERIC;
}
/***************************************************************************** /*****************************************************************************
* NetOpen: wrapper around OpenUDP, ListenTCP and OpenTCP * NetOpen: wrapper around OpenUDP, ListenTCP and OpenTCP
*****************************************************************************/ *****************************************************************************/
...@@ -670,16 +449,5 @@ static int NetOpen( vlc_object_t * p_this ) ...@@ -670,16 +449,5 @@ static int NetOpen( vlc_object_t * p_this )
{ {
network_socket_t * p_socket = p_this->p_private; network_socket_t * p_socket = p_this->p_private;
if( p_socket->i_type == NETWORK_UDP )
{
return OpenUDP( p_this, p_socket ); return OpenUDP( p_this, p_socket );
}
else if( p_socket->i_type == NETWORK_TCP_PASSIVE )
{
return ListenTCP( p_this, p_socket );
}
else
{
return OpenTCP( p_this, p_socket );
}
} }
...@@ -463,6 +463,11 @@ static char *ppsz_clock_descriptions[] = ...@@ -463,6 +463,11 @@ static char *ppsz_clock_descriptions[] =
"If you check this box, IPv4 will be used by default for all UDP and " \ "If you check this box, IPv4 will be used by default for all UDP and " \
"HTTP connections.") "HTTP connections.")
#define TIMEOUT_TEXT N_("TCP connection timeout in ms")
#define TIMEOUT_LONGTEXT N_( \
"Allows you to modify the default TCP connection timeout. This " \
"value should be set in millisecond units." )
#define SOCKS_SERVER_TEXT N_("SOCKS server") #define SOCKS_SERVER_TEXT N_("SOCKS server")
#define SOCKS_SERVER_LONGTEXT N_( \ #define SOCKS_SERVER_LONGTEXT N_( \
"Allow you to specify a SOCKS server to use. It must be of the form " \ "Allow you to specify a SOCKS server to use. It must be of the form " \
...@@ -1089,6 +1094,8 @@ vlc_module_begin(); ...@@ -1089,6 +1094,8 @@ vlc_module_begin();
change_short('6'); change_short('6');
add_bool( "ipv4", 0, NULL, IPV4_TEXT, IPV4_LONGTEXT, VLC_FALSE ); add_bool( "ipv4", 0, NULL, IPV4_TEXT, IPV4_LONGTEXT, VLC_FALSE );
change_short('4'); change_short('4');
add_integer( "ipv4-timeout", 5 * 1000, NULL, TIMEOUT_TEXT,
TIMEOUT_LONGTEXT, VLC_TRUE );
set_section( N_( "Socks proxy") , NULL ) set_section( N_( "Socks proxy") , NULL )
add_string( "socks", NULL, NULL, add_string( "socks", NULL, NULL,
......
This diff is collapsed.
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