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

Factorize socket listen code

parent 3640b72c
......@@ -87,6 +87,9 @@ struct network_socket_t
#define net_OpenTCP(a, b, c) __net_ConnectTCP(VLC_OBJECT(a), b, c)
VLC_EXPORT( int, __net_ConnectTCP, ( vlc_object_t *p_this, const char *psz_host, int i_port ) );
VLC_EXPORT( int *, net_Listen, (vlc_object_t *p_this, const char *psz_host, int i_port,
int family, int socktype, int protocol) );
#define net_ListenTCP(a, b, c) __net_ListenTCP(VLC_OBJECT(a), b, c)
VLC_EXPORT( int *, __net_ListenTCP, ( vlc_object_t *, const char *, int ) );
......
......@@ -62,6 +62,9 @@
# define EAFNOSUPPORT WSAEAFNOSUPPORT
#endif
extern int rootwrap_bind (int family, int socktype, int protocol,
const struct sockaddr *addr, size_t alen);
int net_Socket (vlc_object_t *p_this, int family, int socktype,
int protocol)
{
......@@ -110,6 +113,97 @@ int net_Socket (vlc_object_t *p_this, int family, int socktype,
}
int *net_Listen (vlc_object_t *p_this, const char *psz_host, int i_port,
int family, int socktype, int protocol)
{
struct addrinfo hints, *res;
memset (&hints, 0, sizeof( hints ));
hints.ai_family = family;
hints.ai_socktype = socktype;
hints.ai_protocol = protocol;
hints.ai_flags = AI_PASSIVE;
msg_Dbg (p_this, "net: listening to %s port %d", psz_host, i_port);
int i_val = vlc_getaddrinfo (p_this, psz_host, i_port, &hints, &res);
if (i_val)
{
msg_Err (p_this, "Cannot resolve %s port %d : %s", psz_host, i_port,
vlc_gai_strerror (i_val));
return NULL;
}
int *sockv = NULL;
unsigned sockc = 0;
for (struct addrinfo *ptr = res; ptr != NULL; ptr = ptr->ai_next)
{
int fd = net_Socket (p_this, ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (fd == -1)
{
msg_Dbg (p_this, "socket error: %s", net_strerror (net_errno));
continue;
}
/* Bind the socket */
if (bind (fd, ptr->ai_addr, ptr->ai_addrlen))
{
int saved_errno = net_errno;
net_Close (fd);
#if !defined(WIN32) && !defined(UNDER_CE)
fd = rootwrap_bind (ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol, ptr->ai_addr,
ptr->ai_addrlen);
if (fd != -1)
{
msg_Dbg (p_this, "got socket %d from rootwrap", fd);
}
else
#endif
{
msg_Err (p_this, "socket bind error (%s)",
net_strerror( saved_errno ) );
continue;
}
}
/* Listen */
switch (ptr->ai_socktype)
{
case SOCK_STREAM:
case SOCK_RDM:
case SOCK_SEQPACKET:
if (listen (fd, INT_MAX))
{
msg_Err (p_this, "socket listen error (%s)",
net_strerror (net_errno));
net_Close (fd);
continue;
}
}
int *nsockv = (int *)realloc (sockv, (sockc + 2) * sizeof (int));
if (nsockv != NULL)
{
nsockv[sockc++] = fd;
sockv = nsockv;
}
else
net_Close (fd);
}
vlc_freeaddrinfo (res);
if (sockv != NULL)
sockv[sockc] = -1;
return sockv;
}
/*****************************************************************************
* __net_Close:
*****************************************************************************
......
......@@ -59,8 +59,6 @@ static int SocksHandshakeTCP( vlc_object_t *,
const char *psz_host, int i_port );
extern int net_Socket( vlc_object_t *p_this, int i_family, int i_socktype,
int i_protocol );
extern int rootwrap_bind (int family, int socktype, int protocol,
const struct sockaddr *addr, size_t alen);
/*****************************************************************************
* __net_ConnectTCP:
......@@ -267,91 +265,10 @@ next_ai: /* failure */
* Open TCP passive "listening" socket(s)
* This function returns NULL in case of error.
*****************************************************************************/
int *__net_ListenTCP( vlc_object_t *p_this, const char *psz_host, int i_port )
int *__net_ListenTCP (vlc_object_t *p_this, const char *psz_host, int i_port)
{
struct addrinfo hints, *res, *ptr;
int i_val, *pi_handles, i_size;
memset( &hints, 0, sizeof( hints ) );
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
msg_Dbg( p_this, "net: listening to %s port %d", psz_host, i_port );
i_val = vlc_getaddrinfo( p_this, psz_host, i_port, &hints, &res );
if( i_val )
{
msg_Err( p_this, "Cannot resolve %s port %d : %s", psz_host, i_port,
vlc_gai_strerror( i_val ) );
return NULL;
}
pi_handles = NULL;
i_size = 1;
for( ptr = res; ptr != NULL; ptr = ptr->ai_next )
{
int fd, *newpi;
fd = net_Socket( p_this, ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol );
if( fd == -1 )
{
msg_Dbg( p_this, "socket error: %s", net_strerror( net_errno ) );
continue;
}
/* Bind the socket */
if( bind( fd, ptr->ai_addr, ptr->ai_addrlen ) )
{
int saved_errno;
saved_errno = net_errno;
net_Close( fd );
#if !defined(WIN32) && !defined(UNDER_CE)
fd = rootwrap_bind( ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol, ptr->ai_addr,
ptr->ai_addrlen );
if( fd != -1 )
{
msg_Dbg( p_this, "got socket %d from rootwrap", fd );
}
else
#endif
{
msg_Err( p_this, "cannot bind socket (%s)",
net_strerror( saved_errno ) );
continue;
}
}
/* Listen */
if( listen( fd, 100 ) == -1 )
{
msg_Err( p_this, "cannot bring the socket in listening mode (%s)",
net_strerror( net_errno ) );
net_Close( fd );
continue;
}
newpi = (int *)realloc( pi_handles, (++i_size) * sizeof( int ) );
if( newpi == NULL )
{
net_Close( fd );
break;
}
else
{
newpi[i_size - 2] = fd;
pi_handles = newpi;
}
}
vlc_freeaddrinfo( res );
if( pi_handles != NULL )
pi_handles[i_size - 1] = -1;
return pi_handles;
return net_Listen (p_this, psz_host, i_port, AF_UNSPEC, SOCK_STREAM,
IPPROTO_TCP);
}
/*****************************************************************************
......
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