]> git.sesse.net Git - vlc/blobdiff - src/network/udp.c
Doxygenization
[vlc] / src / network / udp.c
index e11d1bc88a7ae5727df3778ead53ef83cd6d9477..92a2c0d23411e1bc6539758de8a0bacbd6a867f1 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * udp.c:
  *****************************************************************************
- * Copyright (C) 2004-2005 the VideoLAN team
+ * Copyright (C) 2004-2006 the VideoLAN team
  * $Id$
  *
  * Authors: Laurent Aimar <fenrir@videolan.org>
@@ -19,7 +19,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 /*****************************************************************************
 
 #include <errno.h>
 
-#ifdef HAVE_FCNTL_H
-#   include <fcntl.h>
-#endif
 #ifdef HAVE_SYS_TIME_H
 #    include <sys/time.h>
 #endif
-#ifdef HAVE_UNISTD_H
-#   include <unistd.h>
-#endif
 
 #include "network.h"
 
-#ifndef INADDR_ANY
-#   define INADDR_ANY  0x00000000
+#ifdef WIN32
+#   if defined(UNDER_CE)
+#       undef IP_MULTICAST_TTL
+#       define IP_MULTICAST_TTL 3
+#       undef IP_ADD_MEMBERSHIP
+#       define IP_ADD_MEMBERSHIP 5
+#   endif
+#   define EAFNOSUPPORT WSAEAFNOSUPPORT
+#   define if_nametoindex( str ) atoi( str )
+#else
+#   include <unistd.h>
+#   ifdef HAVE_NET_IF_H
+#       include <net/if.h>
+#   endif
+#endif
+
+#ifndef SOL_IP
+# define SOL_IP IPPROTO_IP
+#endif
+#ifndef SOL_IPV6
+# define SOL_IPV6 IPPROTO_IPV6
 #endif
-#ifndef INADDR_NONE
-#   define INADDR_NONE 0xFFFFFFFF
+#ifndef IPPROTO_IPV6
+# define IPPROTO_IPV6 41
 #endif
 
 extern int net_Socket( vlc_object_t *p_this, int i_family, int i_socktype,
                        int i_protocol );
 
+
+static int net_SetMcastHopLimit( vlc_object_t *p_this,
+                                 int fd, int family, int hlim )
+{
+#ifndef SYS_BEOS
+    int proto, cmd;
+
+    /* There is some confusion in the world whether IP_MULTICAST_TTL 
+     * takes a byte or an int as an argument.
+     * BSD seems to indicate byte so we are going with that and use
+     * int as a fallback to be safe */
+    switch( family )
+    {
+        case AF_INET:
+            proto = SOL_IP;
+            cmd = IP_MULTICAST_TTL;
+            break;
+
+#ifdef IPV6_MULTICAST_HOPS
+        case AF_INET6:
+            proto = SOL_IPV6;
+            cmd = IPV6_MULTICAST_HOPS;
+            break;
+#endif
+
+        default:
+            msg_Warn( p_this, "%s", strerror( EAFNOSUPPORT ) );
+            return VLC_EGENERIC;
+    }
+
+    if( setsockopt( fd, proto, cmd, &hlim, sizeof( hlim ) ) < 0 )
+    {
+        /* BSD compatibility */
+        unsigned char buf;
+
+        buf = (unsigned char)(( hlim > 255 ) ? 255 : hlim);
+        if( setsockopt( fd, proto, cmd, &buf, sizeof( buf ) ) )
+            return VLC_EGENERIC;
+    }
+#endif
+    return VLC_SUCCESS;
+}
+
+
+static int net_SetMcastIface( vlc_object_t *p_this,
+                              int fd, int family, const char *str )
+{
+    switch( family )
+    {
+#ifndef SYS_BEOS
+        case AF_INET:
+        {
+            struct in_addr addr;
+
+            if( inet_pton( AF_INET, str, &addr) <= 0 )
+            {
+                msg_Err( p_this, "Invalid multicast interface %s", str );
+                return VLC_EGENERIC;
+            }
+
+            if( setsockopt( fd, SOL_IP, IP_MULTICAST_IF, &addr,
+                            sizeof( addr ) ) < 0 )
+            {
+                msg_Err( p_this, "Cannot use %s as multicast interface: %s",
+                         str, strerror(errno) );
+                return VLC_EGENERIC;
+            }
+            break;
+        }
+#endif /* SYS_BEOS */
+
+#ifdef IPV6_MULTICAST_IF
+        case AF_INET6:
+        {
+            int scope = if_nametoindex( str );
+
+            if( scope == 0 )
+            {
+                msg_Err( p_this, "Invalid multicast interface %s", str );
+                return VLC_EGENERIC;
+            }
+
+            if( setsockopt( fd, SOL_IPV6, IPV6_MULTICAST_IF,
+                            &scope, sizeof( scope ) ) < 0 )
+            {
+                msg_Err( p_this, "Cannot use %s as multicast interface: %s",
+                         str, strerror( errno ) );
+                return VLC_EGENERIC;
+            }
+            break;
+        }
+#endif
+
+        default:
+            msg_Warn( p_this, "%s", strerror( EAFNOSUPPORT ) );
+            return VLC_EGENERIC;
+    }
+
+    return VLC_SUCCESS;
+}
+
 /*****************************************************************************
  * __net_ConnectUDP:
  *****************************************************************************
@@ -59,7 +173,7 @@ extern int net_Socket( vlc_object_t *p_this, int i_family, int i_socktype,
  * hop limit.
  *****************************************************************************/
 int __net_ConnectUDP( vlc_object_t *p_this, const char *psz_host, int i_port,
-                      int hlim )
+                      int i_hlim )
 {
     struct addrinfo hints, *res, *ptr;
     int             i_val, i_handle = -1;
@@ -68,6 +182,9 @@ int __net_ConnectUDP( vlc_object_t *p_this, const char *psz_host, int i_port,
     if( i_port == 0 )
         i_port = 1234; /* historical VLC thing */
 
+    if( i_hlim < 1 )
+        i_hlim = var_CreateGetInteger( p_this, "ttl" );
+
     memset( &hints, 0, sizeof( hints ) );
     hints.ai_socktype = SOCK_DGRAM;
 
@@ -84,6 +201,7 @@ int __net_ConnectUDP( vlc_object_t *p_this, const char *psz_host, int i_port,
     for( ptr = res; ptr != NULL; ptr = ptr->ai_next )
     {
         int fd;
+        char *psz_mif;
 
         fd = net_Socket( p_this, ptr->ai_family, ptr->ai_socktype,
                          ptr->ai_protocol );
@@ -94,17 +212,32 @@ int __net_ConnectUDP( vlc_object_t *p_this, const char *psz_host, int i_port,
         {
             int i_val;
 
-            /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) to avoid
-            * packet loss caused by scheduling problems */
+            /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s)
+             * to avoid packet loss caused by scheduling problems */
             i_val = 0x80000;
-            setsockopt( i_handle, SOL_SOCKET, SO_RCVBUF, (void *)&i_val,
+            setsockopt( fd, SOL_SOCKET, SO_RCVBUF, (void *)&i_val,
                         sizeof( i_val ) );
             i_val = 0x80000;
-            setsockopt( i_handle, SOL_SOCKET, SO_SNDBUF, (void *)&i_val,
+            setsockopt( fd, SOL_SOCKET, SO_SNDBUF, (void *)&i_val,
+                        sizeof( i_val ) );
+
+            /* Allow broadcast sending */
+            i_val = 1;
+            setsockopt( fd, SOL_SOCKET, SO_BROADCAST, (void*)&i_val,
                         sizeof( i_val ) );
         }
 #endif
 
+        if( i_hlim > 0 )
+            net_SetMcastHopLimit( p_this, fd, ptr->ai_family, i_hlim );
+        psz_mif = config_GetPsz( p_this, (ptr->ai_family != AF_INET)
+                                            ? "miface" : "miface-addr" );
+        if( psz_mif != NULL )
+        {
+            net_SetMcastIface( p_this, fd, ptr->ai_family, psz_mif );
+            free( psz_mif );
+        }
+
         if( connect( fd, ptr->ai_addr, ptr->ai_addrlen ) == 0 )
         {
             /* success */
@@ -153,12 +286,12 @@ int __net_OpenUDP( vlc_object_t *p_this, const char *psz_bind, int i_bind,
     network_socket_t sock;
     module_t         *p_network = NULL;
 
-    if( ( psz_server != NULL ) && ( psz_server[0] == '\0' ) )
+/*    if( ( psz_server != NULL ) && ( psz_server[0] == '\0' ) )
         msg_Warn( p_this, "calling net_OpenUDP with an explicit destination "
                   "is obsolete - use net_ConnectUDP instead" );
     if( i_server != 0 )
         msg_Warn( p_this, "calling net_OpenUDP with an explicit destination "
-                  "port is obsolete - use __net_ConnectUDP instead" );
+                  "port is obsolete - use __net_ConnectUDP instead" );*/
 
     if( psz_server == NULL ) psz_server = "";
     if( psz_bind == NULL ) psz_bind = "";
@@ -224,8 +357,8 @@ int __net_OpenUDP( vlc_object_t *p_this, const char *psz_bind, int i_bind,
         {
             if( sock.i_handle != -1 )
             {
-                msg_Warn( p_this, "net: lame IPv6/IPv4 dual-stack present. "
-                                  "Using only IPv4." );
+                msg_Warn( p_this, "net: lame IPv6/IPv4 dual-stack present, "
+                                  "using only IPv4." );
                 net_Close( fd6 );
             }
             else