From: Rémi Denis-Courmont Date: Sun, 15 Apr 2007 08:20:45 +0000 (+0000) Subject: - Only use IPV6_V6ONLY when it makes sense (i.e. receiving datagram socket) X-Git-Tag: 0.9.0-test0~7736 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=851b8a430e99148da397d24dd8ad75afbf05ea2d;p=vlc - 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 --- diff --git a/include/vlc_network.h b/include/vlc_network.h index 53d04d989f..9506ef5af4 100644 --- a/include/vlc_network.h +++ b/include/vlc_network.h @@ -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 @@ -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 ) ); diff --git a/src/network/io.c b/src/network/io.c index 59f6bdc6b4..622150967c 100644 --- a/src/network/io.c +++ b/src/network/io.c @@ -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, diff --git a/src/network/udp.c b/src/network/udp.c index e59c8ee37a..0bd13a7fac 100644 --- a/src/network/udp.c +++ b/src/network/udp.c @@ -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;