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

Really backport fixes for #734 and #780.

parent cf95d0f8
...@@ -169,17 +169,12 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -169,17 +169,12 @@ static int OpenUDP( vlc_object_t * p_this )
# define strerror( x ) winsock_strerror( strerror_buf ) # define strerror( x ) winsock_strerror( strerror_buf )
#endif #endif
/* If IP_ADD_SOURCE_MEMBERSHIP is not defined in the headers /* Build the local socket */
(because it's not in glibc for example), we have to define the if( BuildAddr( p_this, &sock, psz_bind_addr, i_bind_port ) == -1 )
headers required for IGMPv3 here */ {
#ifndef IP_ADD_SOURCE_MEMBERSHIP msg_Dbg( p_this, "could not build local address" );
#define IP_ADD_SOURCE_MEMBERSHIP 39 return 0;
struct ip_mreq_source { }
struct in_addr imr_multiaddr;
struct in_addr imr_interface;
struct in_addr imr_sourceaddr;
};
#endif
p_socket->i_handle = -1; p_socket->i_handle = -1;
...@@ -187,33 +182,19 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -187,33 +182,19 @@ static int OpenUDP( vlc_object_t * p_this )
* protocol */ * protocol */
if( (i_handle = socket( AF_INET, SOCK_DGRAM, 0 )) == -1 ) if( (i_handle = socket( AF_INET, SOCK_DGRAM, 0 )) == -1 )
{ {
msg_Warn( p_this, "cannot create socket (%s)", strerror(errno) ); msg_Err( p_this, "cannot create socket (%s)", strerror(errno) );
return 0; return 0;
} }
/* We may want to reuse an already used socket */ /* We may want to reuse an already used socket */
i_opt = 1; setsockopt( i_handle, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof( int ) );
if( setsockopt( i_handle, SOL_SOCKET, SO_REUSEADDR,
(void *) &i_opt, sizeof( i_opt ) ) == -1 )
{
msg_Warn( p_this, "cannot configure socket (SO_REUSEADDR: %s)",
strerror(errno));
close( i_handle );
return 0;
}
#ifdef SO_REUSEPORT #ifdef SO_REUSEPORT
i_opt = 1; setsockopt( i_handle, SOL_SOCKET, SO_REUSEPORT, &(int){ 1 }, sizeof( int ) );
if( setsockopt( i_handle, SOL_SOCKET, SO_REUSEPORT,
(void *) &i_opt, sizeof( i_opt ) ) == -1 )
{
msg_Warn( p_this, "cannot configure socket (SO_REUSEPORT)" );
}
#endif #endif
/* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) to avoid /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) to avoid
* packet loss caused by scheduling problems */ * packet loss caused by scheduling problems */
#if !defined( SYS_BEOS ) #ifdef SO_RCVBUF
i_opt = 0x80000; i_opt = 0x80000;
if( setsockopt( i_handle, SOL_SOCKET, SO_RCVBUF, (void *) &i_opt, if( setsockopt( i_handle, SOL_SOCKET, SO_RCVBUF, (void *) &i_opt,
sizeof( i_opt ) ) == -1 ) sizeof( i_opt ) ) == -1 )
...@@ -226,23 +207,28 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -226,23 +207,28 @@ static int OpenUDP( vlc_object_t * p_this )
strerror(errno)); strerror(errno));
#endif #endif
/* Build the local socket */
#if defined( WIN32 ) || defined( UNDER_CE ) #if defined( WIN32 ) || defined( UNDER_CE )
/* Under Win32 and for multicasting, we bind to INADDR_ANY, /*
* so let's call BuildAddr with "" instead of psz_bind_addr */ * Under Win32 and for multicasting, we bind to INADDR_ANY.
if( BuildAddr( p_this, &sock, * This is of course a severe bug, since the socket would logically
IN_MULTICAST( ntohl( inet_addr(psz_bind_addr) ) ) ? * receive unicast traffic, and multicast traffic of groups subscribed
"" : psz_bind_addr, i_bind_port ) == -1 ) * to via other sockets. How this actually works in Winsock, I don't
#else * know.
if( BuildAddr( p_this, &sock, psz_bind_addr, i_bind_port ) == -1 ) */
#endif if( IN_MULTICAST( ntohl( sock.sin_addr.s_addr ) ) )
{ {
msg_Dbg( p_this, "could not build local address" ); struct sockaddr_in stupid = sock;
close( i_handle ); stupid.sin_addr.s_addr = INADDR_ANY;
return 0;
}
if( bind( i_handle, (struct sockaddr *)&stupid, sizeof( stupid ) ) < 0 )
{
msg_Warn( p_this, "cannot bind socket (%d)", WSAGetLastError() );
close( i_handle );
return 0;
}
}
else
#endif
/* Bind it */ /* Bind it */
if( bind( i_handle, (struct sockaddr *)&sock, sizeof( sock ) ) < 0 ) if( bind( i_handle, (struct sockaddr *)&sock, sizeof( sock ) ) < 0 )
{ {
...@@ -251,19 +237,6 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -251,19 +237,6 @@ static int OpenUDP( vlc_object_t * p_this )
return 0; return 0;
} }
#if defined( WIN32 ) || defined( UNDER_CE )
/* Restore the sock struct so we can spare a few #ifdef WIN32 later on */
if( IN_MULTICAST( ntohl( inet_addr(psz_bind_addr) ) ) )
{
if ( BuildAddr( p_this, &sock, psz_bind_addr, i_bind_port ) == -1 )
{
msg_Dbg( p_this, "could not build local address" );
close( i_handle );
return 0;
}
}
#endif
#if !defined( SYS_BEOS ) #if !defined( SYS_BEOS )
/* Allow broadcast reception if we bound on INADDR_ANY */ /* Allow broadcast reception if we bound on INADDR_ANY */
if( !*psz_bind_addr ) if( !*psz_bind_addr )
...@@ -283,6 +256,7 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -283,6 +256,7 @@ static int OpenUDP( vlc_object_t * p_this )
/* Determine interface to be used for multicast */ /* Determine interface to be used for multicast */
char * psz_if_addr = config_GetPsz( p_this, "miface-addr" ); char * psz_if_addr = config_GetPsz( p_this, "miface-addr" );
#ifdef IP_ADD_SOURCE_MEMBERSHIP
/* If we have a source address, we use IP_ADD_SOURCE_MEMBERSHIP /* If we have a source address, we use IP_ADD_SOURCE_MEMBERSHIP
so that IGMPv3 aware OSes running on IGMPv3 aware networks so that IGMPv3 aware OSes running on IGMPv3 aware networks
will do an IGMPv3 query on the network */ will do an IGMPv3 query on the network */
...@@ -295,37 +269,35 @@ static int OpenUDP( vlc_object_t * p_this ) ...@@ -295,37 +269,35 @@ static int OpenUDP( vlc_object_t * p_this )
if( psz_if_addr != NULL && *psz_if_addr if( psz_if_addr != NULL && *psz_if_addr
&& inet_addr(psz_if_addr) != INADDR_NONE ) && inet_addr(psz_if_addr) != INADDR_NONE )
{
imr.imr_interface.s_addr = inet_addr(psz_if_addr); imr.imr_interface.s_addr = inet_addr(psz_if_addr);
}
else else
{
imr.imr_interface.s_addr = INADDR_ANY; imr.imr_interface.s_addr = INADDR_ANY;
}
if( psz_if_addr != NULL ) free( psz_if_addr );
msg_Dbg( p_this, "IP_ADD_SOURCE_MEMBERSHIP multicast request" ); if( psz_if_addr != NULL )
free( psz_if_addr );
/* Join Multicast group with source filter */ /* Join Multicast group with source filter */
if( setsockopt( i_handle, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP, if( setsockopt( i_handle, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP,
(char*)&imr, (char*)&imr,
sizeof(struct ip_mreq_source) ) == -1 ) sizeof(struct ip_mreq_source) ) == -1 )
{ {
msg_Err( p_this, "failed to join IP multicast group (%s)", msg_Warn( p_this, "Source specific multicast failed (%s) -"
strerror(errno) ); "falling back to non-specific mode",
msg_Err( p_this, "are you sure your OS supports IGMPv3?" ); strerror(errno) );
close( i_handle ); goto igmpv2;
return 0;
} }
} }
/* If there is no source address, we use IP_ADD_MEMBERSHIP */ /* If there is no source address, we use IP_ADD_MEMBERSHIP */
else else
{ #endif
struct ip_mreq imr; {
struct ip_mreq imr;
imr.imr_interface.s_addr = INADDR_ANY; igmpv2:
imr.imr_multiaddr.s_addr = sock.sin_addr.s_addr; imr.imr_interface.s_addr = INADDR_ANY;
if( psz_if_addr != NULL && *psz_if_addr imr.imr_multiaddr.s_addr = sock.sin_addr.s_addr;
&& inet_addr(psz_if_addr) != INADDR_NONE ) if( psz_if_addr != NULL && *psz_if_addr
&& inet_addr(psz_if_addr) != INADDR_NONE )
{ {
imr.imr_interface.s_addr = inet_addr(psz_if_addr); imr.imr_interface.s_addr = inet_addr(psz_if_addr);
} }
......
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