Commit 851b8a43 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont
Browse files

- Only use IPV6_V6ONLY when it makes sense (i.e. receiving datagram socket)

 - Remove net_ListenSingle from LibVLC API
 - Improve error message when network protocol to be used is ambiguous
parent f9d3f5de
......@@ -46,6 +46,9 @@
# define ENETUNREACH WSAENETUNREACH
# define net_errno (WSAGetLastError())
extern const char *net_strerror( int val );
# ifndef IPV6_V6ONLY
# define IPV6_V6ONLY FIXME_FIXME_FIXME
# endif
#else
# if HAVE_SYS_SOCKET_H
# include <sys/socket.h>
......@@ -75,7 +78,6 @@ int net_SetupSocket (int fd);
VLC_EXPORT( int, __net_Connect, (vlc_object_t *p_this, const char *psz_host, int i_port, int socktype, int protocol) );
VLC_EXPORT( int *, net_Listen, (vlc_object_t *p_this, const char *psz_host, int i_port, int family, int socktype, int protocol) );
VLC_EXPORT( int, net_ListenSingle, (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)
#define net_ConnectTCP(a, b, c) __net_ConnectTCP(VLC_OBJECT(a), b, c)
......@@ -101,14 +103,14 @@ static inline int net_ConnectUDP (vlc_object_t *obj, const char *host, int port,
return net_ConnectDgram (obj, host, port, hlim, IPPROTO_UDP);
}
#define net_OpenDgram( a, b, c, d, e, g, h ) __net_OpenDgram(VLC_OBJECT(a), b, c, d, e, g, h)
VLC_EXPORT( int, __net_OpenDgram, ( vlc_object_t *p_this, const char *psz_bind, int i_bind, const char *psz_server, int i_server, int family, int proto ) );
static inline int net_ListenUDP1 (vlc_object_t *obj, const char *host, int port)
{
return net_ListenSingle (obj, host, port, AF_UNSPEC, SOCK_DGRAM, 0);
return net_OpenDgram (obj, host, port, NULL, 0, 0, IPPROTO_UDP);
}
#define net_OpenDgram( a, b, c, d, e, g, h ) __net_OpenDgram(VLC_OBJECT(a), b, c, d, e, g, h)
VLC_EXPORT( int, __net_OpenDgram, ( vlc_object_t *p_this, const char *psz_bind, int i_bind, const char *psz_server, int i_server, int family, int proto ) );
VLC_EXPORT( void, net_ListenClose, ( int *fd ) );
VLC_EXPORT( int, net_SetDSCP, ( int fd, uint8_t dscp ) );
......
......@@ -97,11 +97,11 @@ int net_Socket (vlc_object_t *p_this, int family, int socktype,
#ifdef IPV6_V6ONLY
/*
* Accepts only IPv6 and IPv4 connections on IPv6 sockets.
* Accepts only IPv6 connections on IPv6 sockets.
* If possible, we should open two sockets, but it is not always possible.
*/
if (family == AF_INET6)
setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, &(int){ 0 }, sizeof (int));
setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, &(int){ 1 }, sizeof (int));
#endif
#if defined (WIN32) || defined (UNDER_CE)
......@@ -239,28 +239,6 @@ int *net_Listen (vlc_object_t *p_this, const char *psz_host,
}
int net_ListenSingle (vlc_object_t *obj, const char *host, int port,
int family, int socktype, int protocol)
{
int *fdv = net_Listen (obj, host, port, family, socktype, protocol);
if (fdv == NULL)
return -1;
for (unsigned i = 1; fdv[i] != -1; i++)
{
msg_Warn (obj, "Multiple sockets opened. Dropping extra ones!");
net_Close (fdv[i]);
}
int fd = fdv[0];
assert (fd != -1);
free (fdv);
return fd;
}
static ssize_t
net_ReadInner (vlc_object_t *restrict p_this, unsigned fdc, const int *fdv,
const v_socket_t *const *restrict vsv,
......
......@@ -2,7 +2,7 @@
* udp.c:
*****************************************************************************
* Copyright (C) 2004-2006 the VideoLAN team
* Copyright © 2006 Rémi Denis-Courmont
* Copyright © 2006-2007 Rémi Denis-Courmont
*
* $Id$
*
......@@ -67,11 +67,90 @@
extern int net_Socket( vlc_object_t *p_this, int i_family, int i_socktype,
int i_protocol );
static int net_ListenSingle (vlc_object_t *obj, const char *host, int port,
int family, int protocol)
{
struct addrinfo hints, *res;
memset (&hints, 0, sizeof( hints ));
hints.ai_family = family;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
if (host && !*host)
host = NULL;
msg_Dbg (obj, "net: opening %s datagram port %d", host ?: "any", port);
int val = vlc_getaddrinfo (obj, host, port, &hints, &res);
if (val)
{
msg_Err (obj, "Cannot resolve %s port %d : %s", host, port,
vlc_gai_strerror (val));
return -1;
}
val = -1;
for (const struct addrinfo *ptr = res; ptr != NULL; ptr = ptr->ai_next)
{
int fd = net_Socket (obj, ptr->ai_family, ptr->ai_socktype,
protocol ?: ptr->ai_protocol);
if (fd == -1)
{
msg_Dbg (obj, "socket error: %s", net_strerror (net_errno));
continue;
}
if (ptr->ai_next != NULL)
{
#ifdef IPV6_V6ONLY
if ((ptr->ai_family != AF_INET6)
|| setsockopt (fd, SOL_IPV6, IPV6_V6ONLY, &(int){ 0 },
sizeof (int)))
#endif
{
msg_Err (obj, "Multiple network protocols present");
msg_Err (obj, "Please select network protocol manually");
}
}
/* Bind the socket */
#if defined (WIN32) || defined (UNDER_CE)
if (net_SockAddrIsMulticast (ptr->ai_addr, ptr->ai_addrlen)
&& (sizeof (struct sockaddr_storage) >= ptr->ai_addrlen))
{
struct sockaddr_in6 dumb =
{
.sin6_family = ptr->ai_addr->sa_family,
.sin6_port = ((struct sockaddr_in *)(ptr->ai_addr))->sin_port
};
bind (fd, (struct sockaddr *)&dumb, ptr->ai_addrlen);
}
else
#endif
if (bind (fd, ptr->ai_addr, ptr->ai_addrlen))
{
msg_Err (obj, "socket bind error (%s)", net_strerror (net_errno));
net_Close (fd);
continue;
}
if (net_SockAddrIsMulticast (ptr->ai_addr, ptr->ai_addrlen)
&& net_Subscribe (obj, fd, ptr->ai_addr, ptr->ai_addrlen))
{
net_Close (fd);
continue;
}
val = fd;
break;
}
vlc_freeaddrinfo (res);
return val;
}
/*
* XXX: I am too lazy to put all these dual functions in “next generation”
* network plugins.
*/
static int net_SetMcastHopLimit( vlc_object_t *p_this,
int fd, int family, int hlim )
......@@ -619,15 +698,14 @@ int __net_OpenDgram( vlc_object_t *obj, const char *psz_bind, int i_bind,
const char *psz_server, int i_server,
int family, int protocol )
{
struct addrinfo hints, *loc, *rem;
int val;
if ((psz_server == NULL) || (psz_server[0] == '\0'))
return net_ListenSingle (obj, psz_bind, i_bind, family, protocol);
if( !*psz_server )
return net_ListenSingle (obj, psz_bind, i_bind,
family, SOCK_DGRAM, protocol);
msg_Dbg (obj, "net: connecting to [%s]:%d from [%s]:%d",
psz_server, i_server, psz_bind, i_bind);
msg_Dbg( obj, "net: connecting to [%s]:%d from [%s]:%d",
psz_server, i_server, psz_bind, i_bind );
struct addrinfo hints, *loc, *rem;
int val;
memset (&hints, 0, sizeof (hints));
hints.ai_family = family;
......
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