[vlc-devel] First patch for IGMPv3 under Windows

Alexis de Lattre alexis at via.ecp.fr
Mon Jan 19 01:21:00 CET 2004


This is my first patch that adds IGMPv3 support for VLC under win32.

IGMPv3, as specified in RFC 3376, allows a host to subscribe to a
multicast group with a source filter. For example, a host can say "I
want to receive the stream 239.255.12.42 sent by 138.195.131.16", and he
won't be polluted by the other streamers that send packets on the same
multicast address. IGMPv3 works with PIM-SSM. MDLv2 is the equivalent of
IGMPv3 over IPv6.

Today, IGMPv3 is supported by Linux (2.4.22+ and 2.6.0+), BSD and
Windows XP. I don't know about Mac OS X...

My patch adds IGMPv3 support for VLC Windows. To make it work, you need
an IGMPv3 aware network and you should run VLC with this command line :

vlc udp:138.195.131.16 at 239.255.12.42

where "138.195.131.16" is the source address and 239.255.12.42 the
multicast address.

You can see the result of a test I made :

http://vthr.via.ecp.fr/~alexis/ethereal-igmpv3-7-2.png

You can find a package of VLC for win32 with IGMPv3 support here :

http://vthr.via.ecp.fr/~alexis/vlc-0.7.1-igmpv3-8.zip

TODO :
- test if it doesn't cause problems on Windows 2000
- try to reduce the diff size (I have some ideas, but didn't have time
  to test them)
- peer reviews !

P.S. : I have tried to code the support of IGMPv3 for Linux, but as it
is not in the glib headers yet, it's not convenient at all !

-- 
Alexis
-------------- next part --------------
diff -Nru vlc/modules/access/udp.c vlc-igmpv3/modules/access/udp.c
--- vlc/modules/access/udp.c	2003-12-04 17:49:43.000000000 +0100
+++ vlc-igmpv3/modules/access/udp.c	2004-01-19 00:50:02.000000000 +0100
@@ -242,7 +242,7 @@
     p_input->stream.i_method = INPUT_METHOD_NETWORK;
     vlc_mutex_unlock( &p_input->stream.stream_lock );
 
-    if( *psz_server_addr || i_server_port )
+/*    if( *psz_server_addr || i_server_port )
     {
         msg_Err( p_input, "this UDP syntax is deprecated; the server argument will be");
         msg_Err( p_input, "ignored (%s:%d). If you wanted to enter a multicast address",
@@ -253,7 +253,7 @@
 
         i_server_port = 0;
         psz_server_addr = "";
-    }
+    } */
  
     msg_Dbg( p_input, "opening server=%s:%d local=%s:%d",
              psz_server_addr, i_server_port, psz_bind_addr, i_bind_port );
diff -Nru vlc/modules/misc/network/ipv4.c vlc-igmpv3/modules/misc/network/ipv4.c
--- vlc/modules/misc/network/ipv4.c	2004-01-15 15:57:00.000000000 +0100
+++ vlc-igmpv3/modules/misc/network/ipv4.c	2004-01-19 00:49:37.000000000 +0100
@@ -281,7 +281,91 @@
         }
     }
 
-#if !defined( UNDER_CE ) && !defined( SYS_BEOS )
+#if defined( WIN32 )
+/* Only Win32 has the support for IP_ADD_SOURCE_MEMBERSHIP
+   with the headers that are included */
+
+    /* 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 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 */
+        if( *psz_server_addr )
+        {
+            struct ip_mreq_source imr;
+
+            imr.imr_multiaddr.s_addr = sock.sin_addr.s_addr;
+            imr.imr_sourceaddr.s_addr = inet_addr(psz_server_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_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 )
+            {
+#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 );
+            }
+         }
+         /* If there is no source address, we use IP_ADD_MEMBERSHIP */
+         else
+         {
+             struct ip_mreq imr;
+
+             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 without source filter */
+            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 /* UNDER_CE, SYS_BEOS */
+
+#if !defined( UNDER_CE ) && !defined( SYS_BEOS ) && !defined( WIN32 )
+/* This code is for the OSes that 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) ) )
     {
@@ -301,6 +385,7 @@
         }
         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 )
@@ -315,7 +400,7 @@
             return( -1 );
         }
     }
-#endif /* UNDER_CE, SYS_BEOS */
+#endif
 
     if( *psz_server_addr )
     {


More information about the vlc-devel mailing list