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

Alexis de Lattre alexis at via.ecp.fr
Sun Feb 1 02:15:13 CET 2004


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
-------------- next part --------------
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
 


More information about the vlc-devel mailing list