[vlc-devel] [patch] IGMPv3 support for Linux

R. Bernstein rocky at panix.com
Sun Feb 1 02:54:28 CET 2004


A general comment. Instead of having specific OS tests in the code, I
think it preferable to have an autoconf test for some "feature" which
then sets a define in config.h. 

For example perhaps instead putting in misc/network/ipv4.c: 
#if defined( SYS_LINUX )

how about: 

#ifdef NEED_IP_REQ_SOURCE

which is deternined in configure. 

And perhaps configure.ac could arrange to set IP_ADD_SOURCE_MEMBERSHIP
as well. One possibility (around line 103 in configure.ac):

  linux*)
    SYS=linux
    AC_DEFINE(IP_ADD_SOURCE_MEMBERSHIP, 34, Some meaningful description of what this does)


In this way, dealing with another OS or a new release of an existing
OS is all done in configure rather than buried deep in the code.
Perhaps, somewhere else that definition may be needed and you won't
have to duplicate the logic.


Alexis de Lattre writes:
 > 
 > After I commited the support of IGMPv3 support for Win32, I started
 > working on IGMPv3 support for Linux. As the required headers are not
 > part of glibc, Gibalou suggested to write the required headers
 > inside the code of ipv4.c, i.e. :
 > - #define IP_ADD_SOURCE_MEMBERSHIP  39
 > - create a vlc_ip_mreq_source structure to remplace the missing
 >   ip_mreq_source structure.
 > 
 > With that code, IGMPv3 was working fine on Linux but not on Win32 any
 > more. After some tests, I figured out that Win32 didn't like the new
 > vlc_ip_mreq_source, but wanted to have the ip_mreq_source structure, even
 > if the definition is the same ! I don't understand why...
 > 
 > So I decided to put :
 > 
 > #if defined( SYS_LINUX )
 >     struct ip_mreq_source {
 >         struct in_addr  imr_multiaddr;
 >         struct in_addr  imr_interface;
 >         struct in_addr  imr_sourceaddr;
 >      };
 > 
 >     #define IP_ADD_SOURCE_MEMBERSHIP  39
 > #endif
 > 
 > so that ip_mreq_source is defined by this code under Linux, but Win32
 > uses it's headers to define the structure. With that solution, it works
 > under Win32 and Linux. I have also put some #if defined( SYS_DARWIN ) to
 > avoid all code duplication, as suggested by Gibalou.
 > 
 > Here is a new package for win32:
 > 
 > http://vthr.via.ecp.fr/~alexis/vlc-0.7.1-igmpv3-11.zip
 > 
 > Here is an example of an IGMPv3 request under Linux:
 > 
 > http://vthr.via.ecp.fr/~alexis/ethereal-igmpv3-linux-1.png
 > 
 > I would like to have some comments on my patch enclosed before I commit
 > it.
 > 
 > Moreover, can someone check if OSX implements IP_ADD_SOURCE_MEMBERSHIP
 > or not ? If the answer is yes, I would then remove my #if defined(
 > SYS_DARWIN ) to enable IGMPv3 support for OSX...
 > 
 > -- 
 > Alexis
 > diff -Nru vlc/modules/misc/network/ipv4.c vlc-igmpv3/modules/misc/network/ipv4.c
 > --- vlc/modules/misc/network/ipv4.c	2004-01-31 19:02:32.000000000 +0100
 > +++ vlc-igmpv3/modules/misc/network/ipv4.c	2004-02-01 01:47:31.000000000 +0100
 > @@ -74,6 +74,7 @@
 >  #   define IN_MULTICAST(a) IN_CLASSD(a)
 >  #endif
 >  
 > +
 >  /*****************************************************************************
 >   * Local prototypes
 >   *****************************************************************************/
 > @@ -153,6 +154,18 @@
 >      socklen_t i_opt_size;
 >      struct sockaddr_in sock;
 >  
 > +    /* As IGMPv3 headers are not part of glibc yet, we have to define the
 > +       headers for Linux here */
 > +#if defined( SYS_LINUX )
 > +    struct ip_mreq_source {
 > +        struct in_addr  imr_multiaddr;
 > +        struct in_addr  imr_interface;
 > +        struct in_addr  imr_sourceaddr;
 > +     };
 > +
 > +    #define IP_ADD_SOURCE_MEMBERSHIP  39
 > +#endif
 > +
 >      /* Open a SOCK_DGRAM (UDP) socket, in the AF_INET domain, automatic (0)
 >       * protocol */
 >      if( (i_handle = socket( AF_INET, SOCK_DGRAM, 0 )) == -1 )
 > @@ -282,16 +295,14 @@
 >          }
 >      }
 >  
 > -#if defined( WIN32 )
 > -/* Only Win32 has the support for IP_ADD_SOURCE_MEMBERSHIP
 > -   with the headers that are included */
 > -
 > +#if !defined( UNDER_CE ) && !defined( SYS_BEOS )
 >      /* Join the multicast group if the socket is a multicast address */
 >      if( IN_MULTICAST( ntohl(sock.sin_addr.s_addr) ) )
 >      {
 >          /* Determine interface to be used for multicast */
 >          char * psz_if_addr = config_GetPsz( p_this, "iface-addr" );
 >  
 > +#if !defined( SYS_DARWIN )
 >          /* If we have a source address, we use IP_ADD_SOURCE_MEMBERSHIP
 >             so that IGMPv3 aware OSes running on IGMPv3 aware networks
 >             will do an IGMPv3 query on the network */
 > @@ -316,7 +327,8 @@
 >              msg_Dbg( p_this, "IP_ADD_SOURCE_MEMBERSHIP multicast request" );
 >              /* Join Multicast group with source filter */
 >              if( setsockopt( i_handle, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP,
 > -                         (char*)&imr, sizeof(struct ip_mreq_source) ) == -1 )
 > +                         (char*)&imr,
 > +                         sizeof(struct ip_mreq_source) ) == -1 )
 >              {
 >  #ifdef HAVE_ERRNO_H
 >                  msg_Err( p_this, "failed to join IP multicast group (%s)",
 > @@ -331,6 +343,7 @@
 >           /* If there is no source address, we use IP_ADD_MEMBERSHIP */
 >           else
 >           {
 > +#endif
 >               struct ip_mreq imr;
 >  
 >               imr.imr_multiaddr.s_addr = sock.sin_addr.s_addr;
 > @@ -359,47 +372,9 @@
 >                  close( i_handle );
 >                  return( -1 );
 >              }
 > +#if !defined( SYS_DARWIN )
 >           }
 > -    }
 >  #endif
 > -
 > -#if !defined( UNDER_CE ) && !defined( SYS_BEOS ) && !defined( WIN32 )
 > -/* This code is for the OSes that have multicast support but
 > -   don't have IP_ADD_SOURCE_MEMBERSHIP with the headers included */
 > -
 > -    /* Join the multicast group if the socket is a multicast address */
 > -    if( IN_MULTICAST( ntohl(sock.sin_addr.s_addr) ) )
 > -    {
 > -        struct ip_mreq imr;
 > -
 > -        /* Determine interface to be used for multicast */
 > -        char * psz_if_addr = config_GetPsz( p_this, "iface-addr" );
 > -        imr.imr_multiaddr.s_addr = sock.sin_addr.s_addr;
 > -        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);
 > -        }
 > -        else
 > -        {
 > -            imr.imr_interface.s_addr = INADDR_ANY;
 > -        }
 > -        if( psz_if_addr != NULL ) free( psz_if_addr );
 > -
 > -        msg_Dbg( p_this, "IP_ADD_MEMBERSHIP multicast request" );
 > -        /* Join Multicast group */
 > -        if( setsockopt( i_handle, IPPROTO_IP, IP_ADD_MEMBERSHIP,
 > -                        (char*)&imr, sizeof(struct ip_mreq) ) == -1 )
 > -        {
 > -#ifdef HAVE_ERRNO_H
 > -            msg_Err( p_this, "failed to join IP multicast group (%s)",
 > -                              strerror(errno) );
 > -#else
 > -            msg_Err( p_this, "failed to join IP multicast group" );
 > -#endif
 > -            close( i_handle );
 > -            return( -1 );
 > -        }
 >      }
 >  #endif
 >  

-- 
This is the vlc-devel mailing-list, see http://www.videolan.org/vlc/
To unsubscribe, please read http://developers.videolan.org/lists.html
If you are in trouble, please contact <postmaster at videolan.org>



More information about the vlc-devel mailing list