]> git.sesse.net Git - vlc/commitdiff
- Only use IPV6_V6ONLY when it makes sense (i.e. receiving datagram socket)
authorRémi Denis-Courmont <rem@videolan.org>
Sun, 15 Apr 2007 08:20:45 +0000 (08:20 +0000)
committerRémi Denis-Courmont <rem@videolan.org>
Sun, 15 Apr 2007 08:20:45 +0000 (08:20 +0000)
 - Remove net_ListenSingle from LibVLC API
 - Improve error message when network protocol to be used is ambiguous

include/vlc_network.h
src/network/io.c
src/network/udp.c

index 53d04d989f89d37a019ed706aed4148c19b7e9af..9506ef5af46a519225a4f39e6d0bea8f2e112615 100644 (file)
@@ -46,6 +46,9 @@
 #   define ENETUNREACH WSAENETUNREACH
 #   define net_errno (WSAGetLastError())
 extern const char *net_strerror( int val );
+#   ifndef IPV6_V6ONLY
+#       define IPV6_V6ONLY FIXME_FIXME_FIXME
+#   endif
 #else
 #   if HAVE_SYS_SOCKET_H
 #      include <sys/socket.h>
@@ -75,7 +78,6 @@ int net_SetupSocket (int fd);
 VLC_EXPORT( int, __net_Connect, (vlc_object_t *p_this, const char *psz_host, int i_port, int socktype, int protocol) );
 
 VLC_EXPORT( int *, net_Listen, (vlc_object_t *p_this, const char *psz_host, int i_port, int family, int socktype, int protocol) );
-VLC_EXPORT( int, net_ListenSingle, (vlc_object_t *p_this, const char *psz_host, int i_port, int family, int socktype, int protocol) );
 
 #define net_ListenTCP(a, b, c) __net_ListenTCP(VLC_OBJECT(a), b, c)
 #define net_ConnectTCP(a, b, c) __net_ConnectTCP(VLC_OBJECT(a), b, c)
@@ -101,14 +103,14 @@ static inline int net_ConnectUDP (vlc_object_t *obj, const char *host, int port,
     return net_ConnectDgram (obj, host, port, hlim, IPPROTO_UDP);
 }
 
+#define net_OpenDgram( a, b, c, d, e, g, h ) __net_OpenDgram(VLC_OBJECT(a), b, c, d, e, g, h)
+VLC_EXPORT( int, __net_OpenDgram, ( vlc_object_t *p_this, const char *psz_bind, int i_bind, const char *psz_server, int i_server, int family, int proto ) );
+
 static inline int net_ListenUDP1 (vlc_object_t *obj, const char *host, int port)
 {
-    return net_ListenSingle (obj, host, port, AF_UNSPEC, SOCK_DGRAM, 0);
+    return net_OpenDgram (obj, host, port, NULL, 0, 0, IPPROTO_UDP);
 }
 
-#define net_OpenDgram( a, b, c, d, e, g, h ) __net_OpenDgram(VLC_OBJECT(a), b, c, d, e, g, h)
-VLC_EXPORT( int, __net_OpenDgram, ( vlc_object_t *p_this, const char *psz_bind, int i_bind, const char *psz_server, int i_server, int family, int proto ) );
-
 VLC_EXPORT( void, net_ListenClose, ( int *fd ) );
 
 VLC_EXPORT( int, net_SetDSCP, ( int fd, uint8_t dscp ) );
index 59f6bdc6b4567bb379c903107fb0c39d747872a1..622150967c10ec794e7da0371588be78b6c0dec6 100644 (file)
@@ -97,11 +97,11 @@ int net_Socket (vlc_object_t *p_this, int family, int socktype,
 
 #ifdef IPV6_V6ONLY
     /*
-     * Accepts only IPv6 and IPv4 connections on IPv6 sockets.
+     * Accepts only IPv6 connections on IPv6 sockets.
      * If possible, we should open two sockets, but it is not always possible.
      */
     if (family == AF_INET6)
-        setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, &(int){ 0 }, sizeof (int));
+        setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, &(int){ 1 }, sizeof (int));
 #endif
 
 #if defined (WIN32) || defined (UNDER_CE)
@@ -239,28 +239,6 @@ int *net_Listen (vlc_object_t *p_this, const char *psz_host,
 }
 
 
-int net_ListenSingle (vlc_object_t *obj, const char *host, int port,
-                      int family, int socktype, int protocol)
-{
-    int *fdv = net_Listen (obj, host, port, family, socktype, protocol);
-    if (fdv == NULL)
-        return -1;
-
-    for (unsigned i = 1; fdv[i] != -1; i++)
-    {
-        msg_Warn (obj, "Multiple sockets opened. Dropping extra ones!");
-        net_Close (fdv[i]);
-    }
-
-    int fd = fdv[0];
-    assert (fd != -1);
-
-    free (fdv);
-    return fd;
-}
-
-
-
 static ssize_t
 net_ReadInner (vlc_object_t *restrict p_this, unsigned fdc, const int *fdv,
                const v_socket_t *const *restrict vsv,
index e59c8ee37aae48941a49fda6e46249b998e7553b..0bd13a7fac8b94e8b269239e847228658aea2486 100644 (file)
@@ -2,7 +2,7 @@
  * udp.c:
  *****************************************************************************
  * Copyright (C) 2004-2006 the VideoLAN team
- * Copyright © 2006 Rémi Denis-Courmont
+ * Copyright © 2006-2007 Rémi Denis-Courmont
  *
  * $Id$
  *
 extern int net_Socket( vlc_object_t *p_this, int i_family, int i_socktype,
                        int i_protocol );
 
+static int net_ListenSingle (vlc_object_t *obj, const char *host, int port,
+                             int family, int protocol)
+{
+    struct addrinfo hints, *res;
+
+    memset (&hints, 0, sizeof( hints ));
+    hints.ai_family = family;
+    hints.ai_socktype = SOCK_DGRAM;
+    hints.ai_flags = AI_PASSIVE;
+
+    if (host && !*host)
+        host = NULL;
+
+    msg_Dbg (obj, "net: opening %s datagram port %d", host ?: "any", port);
+
+    int val = vlc_getaddrinfo (obj, host, port, &hints, &res);
+    if (val)
+    {
+        msg_Err (obj, "Cannot resolve %s port %d : %s", host, port,
+                 vlc_gai_strerror (val));
+        return -1;
+    }
+
+    val = -1;
+
+    for (const struct addrinfo *ptr = res; ptr != NULL; ptr = ptr->ai_next)
+    {
+        int fd = net_Socket (obj, ptr->ai_family, ptr->ai_socktype,
+                             protocol ?: ptr->ai_protocol);
+        if (fd == -1)
+        {
+            msg_Dbg (obj, "socket error: %s", net_strerror (net_errno));
+            continue;
+        }
+
+        if (ptr->ai_next != NULL)
+        {
+#ifdef IPV6_V6ONLY
+            if ((ptr->ai_family != AF_INET6)
+             || setsockopt (fd, SOL_IPV6, IPV6_V6ONLY, &(int){ 0 },
+                            sizeof (int)))
+#endif
+            {
+                msg_Err (obj, "Multiple network protocols present");
+                msg_Err (obj, "Please select network protocol manually");
+            }
+        }
+
+        /* Bind the socket */
+#if defined (WIN32) || defined (UNDER_CE)
+        if (net_SockAddrIsMulticast (ptr->ai_addr, ptr->ai_addrlen)
+         && (sizeof (struct sockaddr_storage) >= ptr->ai_addrlen))
+        {
+            struct sockaddr_in6 dumb =
+            {
+                .sin6_family = ptr->ai_addr->sa_family,
+                .sin6_port =  ((struct sockaddr_in *)(ptr->ai_addr))->sin_port
+            };
+            bind (fd, (struct sockaddr *)&dumb, ptr->ai_addrlen);
+        }
+        else
+#endif
+        if (bind (fd, ptr->ai_addr, ptr->ai_addrlen))
+        {
+            msg_Err (obj, "socket bind error (%s)", net_strerror (net_errno));
+            net_Close (fd);
+            continue;
+        }
+
+        if (net_SockAddrIsMulticast (ptr->ai_addr, ptr->ai_addrlen)
+         && net_Subscribe (obj, fd, ptr->ai_addr, ptr->ai_addrlen))
+        {
+            net_Close (fd);
+            continue;
+        }
+
+        val = fd;
+        break;
+    }
+
+    vlc_freeaddrinfo (res);
+    return val;
+}
 
-/*
- * XXX: I am too lazy to put all these dual functions in “next generation”
- * network plugins.
- */
 
 static int net_SetMcastHopLimit( vlc_object_t *p_this,
                                  int fd, int family, int hlim )
@@ -619,15 +698,14 @@ int __net_OpenDgram( vlc_object_t *obj, const char *psz_bind, int i_bind,
                      const char *psz_server, int i_server,
                      int family, int protocol )
 {
-    struct addrinfo hints, *loc, *rem;
-    int val;
+    if ((psz_server == NULL) || (psz_server[0] == '\0'))
+        return net_ListenSingle (obj, psz_bind, i_bind, family, protocol);
 
-    if( !*psz_server )
-        return net_ListenSingle (obj, psz_bind, i_bind,
-                                 family, SOCK_DGRAM, protocol);
+    msg_Dbg (obj, "net: connecting to [%s]:%d from [%s]:%d",
+             psz_server, i_server, psz_bind, i_bind);
 
-    msg_Dbg( obj, "net: connecting to [%s]:%d from [%s]:%d",
-             psz_server, i_server, psz_bind, i_bind );
+    struct addrinfo hints, *loc, *rem;
+    int val;
 
     memset (&hints, 0, sizeof (hints));
     hints.ai_family = family;