]> git.sesse.net Git - vlc/blobdiff - src/network/udp.c
httpd: cosmetics
[vlc] / src / network / udp.c
index cb72868f70ef14d5af54e3e628a2db9d78e504f7..ce4e419e05e0a716e7c3725b5b0f4dfc491668fb 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * udp.c:
  *****************************************************************************
- * Copyright (C) 2004-2006 the VideoLAN team
+ * Copyright (C) 2004-2006 VLC authors and VideoLAN
  * Copyright © 2006-2007 Rémi Denis-Courmont
  *
  * $Id$
@@ -9,19 +9,19 @@
  * Authors: Laurent Aimar <fenrir@videolan.org>
  *          Rémi Denis-Courmont <rem # videolan.org>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
  *
- * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 /*****************************************************************************
 #include <vlc_common.h>
 
 #include <errno.h>
+#include <assert.h>
 
 #include <vlc_network.h>
 
-#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
+#ifdef _WIN32
+#   undef EAFNOSUPPORT
 #   define EAFNOSUPPORT WSAEAFNOSUPPORT
 #else
 #   include <unistd.h>
@@ -93,22 +89,14 @@ extern int net_Socket( vlc_object_t *p_this, int i_family, int i_socktype,
                        int i_protocol );
 
 /* */
-static int net_SetupDgramSocket( vlc_object_t *p_obj, int fd, const struct addrinfo *ptr )
+static int net_SetupDgramSocket (vlc_object_t *p_obj, int fd,
+                                 const struct addrinfo *ptr)
 {
 #ifdef SO_REUSEPORT
     setsockopt (fd, SOL_SOCKET, SO_REUSEPORT, &(int){ 1 }, sizeof (int));
 #endif
 
-#ifdef SO_RCVBUF
-    /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s)
-     * to avoid packet loss caused in case of scheduling hiccups */
-    setsockopt (fd, SOL_SOCKET, SO_RCVBUF,
-                (void *)&(int){ 0x80000 }, sizeof (int));
-    setsockopt (fd, SOL_SOCKET, SO_SNDBUF,
-                (void *)&(int){ 0x80000 }, sizeof (int));
-#endif
-
-#if defined (WIN32) || defined (UNDER_CE)
+#if defined (_WIN32)
     if (net_SockAddrIsMulticast (ptr->ai_addr, ptr->ai_addrlen)
      && (sizeof (struct sockaddr_storage) >= ptr->ai_addrlen))
     {
@@ -125,7 +113,7 @@ static int net_SetupDgramSocket( vlc_object_t *p_obj, int fd, const struct addri
 #endif
     if (bind (fd, ptr->ai_addr, ptr->ai_addrlen))
     {
-        msg_Err( p_obj, "socket bind error (%m)" );
+        msg_Err( p_obj, "socket bind error: %s", vlc_strerror_c(net_errno) );
         net_Close (fd);
         return -1;
     }
@@ -136,12 +124,11 @@ static int net_SetupDgramSocket( vlc_object_t *p_obj, int fd, const struct addri
 static int net_ListenSingle (vlc_object_t *obj, const char *host, int port,
                              int protocol)
 {
-    struct addrinfo hints, *res;
-
-    memset (&hints, 0, sizeof( hints ));
-    hints.ai_socktype = SOCK_DGRAM;
-    hints.ai_protocol = protocol;
-    hints.ai_flags = AI_PASSIVE;
+    struct addrinfo hints = {
+        .ai_socktype = SOCK_DGRAM,
+        .ai_protocol = protocol,
+        .ai_flags = AI_PASSIVE | AI_NUMERICSERV | AI_IDN,
+    }, *res;
 
     if (host && !*host)
         host = NULL;
@@ -149,7 +136,7 @@ static int net_ListenSingle (vlc_object_t *obj, const char *host, int port,
     msg_Dbg (obj, "net: opening %s datagram port %d",
              host ? host : "any", port);
 
-    int val = vlc_getaddrinfo (obj, host, port, &hints, &res);
+    int val = vlc_getaddrinfo (host, port, &hints, &res);
     if (val)
     {
         msg_Err (obj, "Cannot resolve %s port %d : %s", host, port,
@@ -165,7 +152,7 @@ static int net_ListenSingle (vlc_object_t *obj, const char *host, int port,
                              ptr->ai_protocol);
         if (fd == -1)
         {
-            msg_Dbg (obj, "socket error: %m");
+            msg_Dbg (obj, "socket error: %s", vlc_strerror_c(net_errno));
             continue;
         }
 
@@ -221,7 +208,7 @@ static int net_SetMcastHopLimit( vlc_object_t *p_this,
 
         default:
             errno = EAFNOSUPPORT;
-            msg_Warn( p_this, "%m" );
+            msg_Warn( p_this, "%s", vlc_strerror_c(EAFNOSUPPORT) );
             return VLC_EGENERIC;
     }
 
@@ -230,11 +217,13 @@ static int net_SetMcastHopLimit( vlc_object_t *p_this,
         /* BSD compatibility */
         unsigned char buf;
 
-        msg_Dbg( p_this, "cannot set hop limit (%d): %m", hlim );
+        msg_Dbg( p_this, "cannot set hop limit (%d): %s", hlim,
+                 vlc_strerror_c(net_errno) );
         buf = (unsigned char)(( hlim > 255 ) ? 255 : hlim);
         if( setsockopt( fd, proto, cmd, &buf, sizeof( buf ) ) )
         {
-            msg_Err( p_this, "cannot set hop limit (%d): %m", hlim );
+            msg_Err( p_this, "cannot set hop limit (%d): %s", hlim,
+                     vlc_strerror_c(net_errno) );
             return VLC_EGENERIC;
         }
     }
@@ -243,185 +232,59 @@ static int net_SetMcastHopLimit( vlc_object_t *p_this,
 }
 
 
-static int net_SetMcastOutIface (int fd, int family, int scope)
+static int net_SetMcastOut (vlc_object_t *p_this, int fd, int family,
+                            const char *iface)
 {
+    int scope = if_nametoindex (iface);
+    if (scope == 0)
+    {
+        msg_Err (p_this, "invalid multicast interface: %s", iface);
+        return -1;
+    }
+
     switch (family)
     {
 #ifdef IPV6_MULTICAST_IF
         case AF_INET6:
-            return setsockopt (fd, SOL_IPV6, IPV6_MULTICAST_IF,
-                               &scope, sizeof (scope));
+            if (setsockopt (fd, SOL_IPV6, IPV6_MULTICAST_IF,
+                            &scope, sizeof (scope)) == 0)
+                return 0;
+            break;
 #endif
 
 #ifdef __linux__
         case AF_INET:
         {
             struct ip_mreqn req = { .imr_ifindex = scope };
-
-            return setsockopt (fd, SOL_IP, IP_MULTICAST_IF, &req,
-                               sizeof (req));
-        }
-#endif
-    }
-
-    errno = EAFNOSUPPORT;
-    return -1;
-}
-
-
-static inline int net_SetMcastOutIPv4 (int fd, struct in_addr ipv4)
-{
-#ifdef IP_MULTICAST_IF
-    return setsockopt( fd, SOL_IP, IP_MULTICAST_IF, &ipv4, sizeof (ipv4));
-#else
-    errno = EAFNOSUPPORT;
-    return -1;
-#endif
-}
-
-
-static int net_SetMcastOut (vlc_object_t *p_this, int fd, int family,
-                            const char *iface, const char *addr)
-{
-    if (iface != NULL)
-    {
-        int scope = if_nametoindex (iface);
-        if (scope == 0)
-        {
-            msg_Err (p_this, "invalid multicast interface: %s", iface);
-            return -1;
-        }
-
-        if (net_SetMcastOutIface (fd, family, scope) == 0)
-            return 0;
-
-        msg_Err (p_this, "%s: %m", iface);
-    }
-
-    if (addr != NULL)
-    {
-        if (family == AF_INET)
-        {
-            struct in_addr ipv4;
-            if (inet_pton (AF_INET, addr, &ipv4) <= 0)
-            {
-                msg_Err (p_this, "invalid IPv4 address for multicast: %s",
-                         addr);
-                return -1;
-            }
-
-            if (net_SetMcastOutIPv4 (fd, ipv4) == 0)
+            if (setsockopt (fd, SOL_IP, IP_MULTICAST_IF,
+                            &req, sizeof (req)) == 0)
                 return 0;
-
-            msg_Err (p_this, "%s: %m", addr);
+            break;
         }
-    }
-
-    return -1;
-}
-
-
-/**
- * Old-style any-source multicast join.
- * In use on Windows XP/2003 and older.
- */
-static int
-net_IPv4Join (vlc_object_t *obj, int fd,
-              const struct sockaddr_in *src, const struct sockaddr_in *grp)
-{
-#ifdef IP_ADD_MEMBERSHIP
-    union
-    {
-        struct ip_mreq gr4;
-# ifdef IP_ADD_SOURCE_MEMBERSHIP
-        struct ip_mreq_source gsr4;
-# endif
-    } opt;
-    int cmd;
-    struct in_addr id = { .s_addr = INADDR_ANY };
-    socklen_t optlen;
-
-    /* Multicast interface IPv4 address */
-    char *iface = var_InheritString (obj, "miface-addr");
-    if ((iface != NULL)
-     && (inet_pton (AF_INET, iface, &id) <= 0))
-    {
-        msg_Err (obj, "invalid multicast interface address %s", iface);
-        free (iface);
-        goto error;
-    }
-    free (iface);
-
-    memset (&opt, 0, sizeof (opt));
-    if (src != NULL)
-    {
-# if defined( IP_ADD_SOURCE_MEMBERSHIP ) && !defined( __ANDROID__ )
-        cmd = IP_ADD_SOURCE_MEMBERSHIP;
-        opt.gsr4.imr_multiaddr = grp->sin_addr;
-        opt.gsr4.imr_sourceaddr = src->sin_addr;
-        opt.gsr4.imr_interface = id;
-        optlen = sizeof (opt.gsr4);
-# else
-        errno = ENOSYS;
-        goto error;
-# endif
-    }
-    else
-    {
-        cmd = IP_ADD_MEMBERSHIP;
-        opt.gr4.imr_multiaddr = grp->sin_addr;
-        opt.gr4.imr_interface = id;
-        optlen = sizeof (opt.gr4);
-    }
-
-    msg_Dbg (obj, "IP_ADD_%sMEMBERSHIP multicast request",
-             (src != NULL) ? "SOURCE_" : "");
-
-    if (setsockopt (fd, SOL_IP, cmd, &opt, optlen) == 0)
-        return 0;
-
-error:
 #endif
-
-    msg_Err (obj, "cannot join IPv4 multicast group (%m)");
+        default:
+            errno = EAFNOSUPPORT;
+    }
+    msg_Err (p_this, "cannot force multicast interface %s: %s", iface,
+             vlc_strerror_c(errno));
     return -1;
 }
 
 
-static int
-net_IPv6Join (vlc_object_t *obj, int fd, const struct sockaddr_in6 *src)
+static unsigned var_GetIfIndex (vlc_object_t *obj)
 {
-#ifdef IPV6_JOIN_GROUP
-    struct ipv6_mreq gr6;
-    memset (&gr6, 0, sizeof (gr6));
-    gr6.ipv6mr_interface = src->sin6_scope_id;
-    memcpy (&gr6.ipv6mr_multiaddr, &src->sin6_addr, 16);
-
-    msg_Dbg (obj, "IPV6_JOIN_GROUP multicast request");
-
-    if (!setsockopt (fd, SOL_IPV6, IPV6_JOIN_GROUP, &gr6, sizeof (gr6)))
+    char *ifname = var_InheritString (obj, "miface");
+    if (ifname == NULL)
         return 0;
-#else
-    errno = ENOSYS;
-#endif
 
-    msg_Err (obj, "cannot join IPv6 any-source multicast group (%m)");
-    return -1;
+    unsigned ifindex = if_nametoindex (ifname);
+    if (ifindex == 0)
+        msg_Err (obj, "invalid multicast interface: %s", ifname);
+    free (ifname);
+    return ifindex;
 }
 
 
-#if defined (WIN32) && !defined (MCAST_JOIN_SOURCE_GROUP)
-/*
- * I hate manual definitions: Error-prone. Portability hell.
- * Developers shall use UP-TO-DATE compilers. Full point.
- * If you remove the warning, you remove the whole ifndef.
- */
-#  warning Your C headers are out-of-date. Please update.
-
-#  define MCAST_JOIN_GROUP 41
-#  define MCAST_JOIN_SOURCE_GROUP 45 /* from <ws2ipdef.h> */
-#endif
-
 /**
  * IP-agnostic multicast join,
  * with fallback to old APIs, and fallback from SSM to ASM.
@@ -431,151 +294,166 @@ net_SourceSubscribe (vlc_object_t *obj, int fd,
                      const struct sockaddr *src, socklen_t srclen,
                      const struct sockaddr *grp, socklen_t grplen)
 {
-    int level, iid = 0;
+#ifdef MCAST_JOIN_SOURCE_GROUP
+    /* Agnostic SSM multicast join */
+    int level;
+    struct group_source_req gsr;
 
-    char *iface = var_InheritString (obj, "miface");
-    if (iface != NULL)
-    {
-        iid = if_nametoindex (iface);
-        if (iid == 0)
-        {
-            msg_Err (obj, "invalid multicast interface: %s", iface);
-            free (iface);
-            return -1;
-        }
-        free (iface);
-    }
+    memset (&gsr, 0, sizeof (gsr));
+    gsr.gsr_interface = var_GetIfIndex (obj);
 
     switch (grp->sa_family)
     {
 #ifdef AF_INET6
         case AF_INET6:
+        {
+            const struct sockaddr_in6 *g6 = (const struct sockaddr_in6 *)grp;
+
             level = SOL_IPV6;
-            if (((const struct sockaddr_in6 *)grp)->sin6_scope_id)
-                iid = ((const struct sockaddr_in6 *)grp)->sin6_scope_id;
+            assert (grplen >= sizeof (struct sockaddr_in6));
+            if (g6->sin6_scope_id != 0)
+                gsr.gsr_interface = g6->sin6_scope_id;
             break;
+        }
 #endif
-
         case AF_INET:
             level = SOL_IP;
             break;
-
         default:
             errno = EAFNOSUPPORT;
             return -1;
     }
 
-    if (src != NULL)
-        switch (src->sa_family)
-        {
-#ifdef AF_INET6
-            case AF_INET6:
-                if (memcmp (&((const struct sockaddr_in6 *)src)->sin6_addr,
-                            &in6addr_any, sizeof (in6addr_any)) == 0)
-                    src = NULL;
-            break;
-#endif
-
-            case AF_INET:
-                if (((const struct sockaddr_in *)src)->sin_addr.s_addr
-                     == INADDR_ANY)
-                    src = NULL;
-                break;
-        }
-
+    assert (grplen <= sizeof (gsr.gsr_group));
+    memcpy (&gsr.gsr_source, src, srclen);
+    assert (srclen <= sizeof (gsr.gsr_source));
+    memcpy (&gsr.gsr_group,  grp, grplen);
+    if (setsockopt (fd, level, MCAST_JOIN_SOURCE_GROUP,
+                    &gsr, sizeof (gsr)) == 0)
+        return 0;
 
-    /* Agnostic ASM/SSM multicast join */
-#ifdef MCAST_JOIN_SOURCE_GROUP
-    union
+#else
+    if (src->sa_family != grp->sa_family)
     {
-        struct group_req gr;
-        struct group_source_req gsr;
-    } opt;
-    socklen_t optlen;
-
-    memset (&opt, 0, sizeof (opt));
+        errno = EAFNOSUPPORT;
+        return -1;
+    }
 
-    if (src != NULL)
+    switch (grp->sa_family)
     {
-        if ((grplen > sizeof (opt.gsr.gsr_group))
-         || (srclen > sizeof (opt.gsr.gsr_source)))
-            return -1;
-
-        opt.gsr.gsr_interface = iid;
-        memcpy (&opt.gsr.gsr_source, src, srclen);
-        memcpy (&opt.gsr.gsr_group,  grp, grplen);
-        optlen = sizeof (opt.gsr);
+# ifdef IP_ADD_SOURCE_MEMBERSHIP
+        /* IPv4-specific API */
+        case AF_INET:
+        {
+            struct ip_mreq_source imr;
+
+            memset (&imr, 0, sizeof (imr));
+            assert (grplen >= sizeof (struct sockaddr_in));
+            imr.imr_multiaddr = ((const struct sockaddr_in *)grp)->sin_addr;
+            assert (srclen >= sizeof (struct sockaddr_in));
+            imr.imr_sourceaddr = ((const struct sockaddr_in *)src)->sin_addr;
+            if (setsockopt (fd, SOL_IP, IP_ADD_SOURCE_MEMBERSHIP,
+                            &imr, sizeof (imr)) == 0)
+                return 0;
+            break;
+        }
+# endif
+        default:
+            errno = EAFNOSUPPORT;
     }
-    else
-    {
-        if (grplen > sizeof (opt.gr.gr_group))
-            return -1;
 
-        opt.gr.gr_interface = iid;
-        memcpy (&opt.gr.gr_group, grp, grplen);
-        optlen = sizeof (opt.gr);
-    }
+#endif
+    msg_Err (obj, "cannot join source multicast group: %s",
+             vlc_strerror_c(net_errno));
+    msg_Warn (obj, "trying ASM instead of SSM...");
+    return net_Subscribe (obj, fd, grp, grplen);
+}
 
-    msg_Dbg (obj, "Multicast %sgroup join request", src ? "source " : "");
 
-    if (setsockopt (fd, level,
-                    src ? MCAST_JOIN_SOURCE_GROUP : MCAST_JOIN_GROUP,
-                    (void *)&opt, optlen) == 0)
-        return 0;
-#endif
+int net_Subscribe (vlc_object_t *obj, int fd,
+                   const struct sockaddr *grp, socklen_t grplen)
+{
+/* MCAST_JOIN_GROUP was introduced to OS X in v10.7, but it doesn't work,
+ * so ignore it to use the same code as on 10.5 or 10.6 */
+#if defined (MCAST_JOIN_GROUP) && !defined (__APPLE__)
+    /* Agnostic SSM multicast join */
+    int level;
+    struct group_req gr;
 
-    /* Fallback to IPv-specific APIs */
-    if ((src != NULL) && (src->sa_family != grp->sa_family))
-        return -1;
+    memset (&gr, 0, sizeof (gr));
+    gr.gr_interface = var_GetIfIndex (obj);
 
     switch (grp->sa_family)
     {
-        case AF_INET:
-            if ((grplen < sizeof (struct sockaddr_in))
-             || ((src != NULL) && (srclen < sizeof (struct sockaddr_in))))
-                return -1;
-
-            if (net_IPv4Join (obj, fd, (const struct sockaddr_in *)src,
-                              (const struct sockaddr_in *)grp) == 0)
-                return 0;
-            break;
-
 #ifdef AF_INET6
         case AF_INET6:
-            if ((grplen < sizeof (struct sockaddr_in6))
-             || ((src != NULL) && (srclen < sizeof (struct sockaddr_in6))))
-                return -1;
-
-            /* IPv6-specific SSM API does not exist. So if we're here
-             * it means IPv6 SSM is not supported on this OS and we
-             * directly fallback to ASM */
+        {
+            const struct sockaddr_in6 *g6 = (const struct sockaddr_in6 *)grp;
 
-            if (net_IPv6Join (obj, fd, (const struct sockaddr_in6 *)grp) == 0)
-                return 0;
+            level = SOL_IPV6;
+            assert (grplen >= sizeof (struct sockaddr_in6));
+            if (g6->sin6_scope_id != 0)
+                gr.gr_interface = g6->sin6_scope_id;
             break;
+        }
 #endif
+        case AF_INET:
+            level = SOL_IP;
+            break;
+        default:
+            errno = EAFNOSUPPORT;
+            return -1;
     }
 
-    msg_Err (obj, "Multicast group join error (%m)");
+    assert (grplen <= sizeof (gr.gr_group));
+    memcpy (&gr.gr_group, grp, grplen);
+    if (setsockopt (fd, level, MCAST_JOIN_GROUP, &gr, sizeof (gr)) == 0)
+        return 0;
 
-    if (src != NULL)
+#else
+    switch (grp->sa_family)
     {
-        msg_Warn (obj, "Trying ASM instead of SSM...");
-        return net_Subscribe (obj, fd, grp, grplen);
+# ifdef IPV6_JOIN_GROUP
+        case AF_INET6:
+        {
+            struct ipv6_mreq ipv6mr;
+            const struct sockaddr_in6 *g6 = (const struct sockaddr_in6 *)grp;
+
+            memset (&ipv6mr, 0, sizeof (ipv6mr));
+            assert (grplen >= sizeof (struct sockaddr_in6));
+            ipv6mr.ipv6mr_multiaddr = g6->sin6_addr;
+            ipv6mr.ipv6mr_interface = g6->sin6_scope_id;
+            if (!setsockopt (fd, SOL_IPV6, IPV6_JOIN_GROUP,
+                             &ipv6mr, sizeof (ipv6mr)))
+                return 0;
+            break;
+        }
+# endif
+# ifdef IP_ADD_MEMBERSHIP
+        case AF_INET:
+        {
+            struct ip_mreq imr;
+
+            memset (&imr, 0, sizeof (imr));
+            assert (grplen >= sizeof (struct sockaddr_in));
+            imr.imr_multiaddr = ((const struct sockaddr_in *)grp)->sin_addr;
+            if (setsockopt (fd, SOL_IP, IP_ADD_MEMBERSHIP,
+                            &imr, sizeof (imr)) == 0)
+                return 0;
+            break;
+        }
+# endif
+        default:
+            errno = EAFNOSUPPORT;
     }
 
-    msg_Err (obj, "Multicast not supported");
+#endif
+    msg_Err (obj, "cannot join multicast group: %s",
+             vlc_strerror_c(net_errno));
     return -1;
 }
 
 
-int net_Subscribe (vlc_object_t *obj, int fd,
-                   const struct sockaddr *addr, socklen_t addrlen)
-{
-    return net_SourceSubscribe (obj, fd, NULL, 0, addr, addrlen);
-}
-
-
 static int net_SetDSCP( int fd, uint8_t dscp )
 {
     struct sockaddr_storage addr;
@@ -618,28 +496,28 @@ static int net_SetDSCP( int fd, uint8_t dscp )
 int net_ConnectDgram( vlc_object_t *p_this, const char *psz_host, int i_port,
                       int i_hlim, int proto )
 {
-    struct addrinfo hints, *res, *ptr;
-    int             i_val, i_handle = -1;
+    struct addrinfo hints = {
+        .ai_socktype = SOCK_DGRAM,
+        .ai_protocol = proto,
+        .ai_flags = AI_NUMERICSERV | AI_IDN,
+    }, *res;
+    int       i_handle = -1;
     bool      b_unreach = false;
 
     if( i_hlim < 0 )
         i_hlim = var_InheritInteger( p_this, "ttl" );
 
-    memset( &hints, 0, sizeof( hints ) );
-    hints.ai_socktype = SOCK_DGRAM;
-    hints.ai_protocol = proto;
-
     msg_Dbg( p_this, "net: connecting to [%s]:%d", psz_host, i_port );
 
-    i_val = vlc_getaddrinfo( p_this, psz_host, i_port, &hints, &res );
-    if( i_val )
+    int val = vlc_getaddrinfo (psz_host, i_port, &hints, &res);
+    if (val)
     {
-        msg_Errp_this, "cannot resolve [%s]:%d : %s", psz_host, i_port,
-                 gai_strerror( i_val ) );
+        msg_Err (p_this, "cannot resolve [%s]:%d : %s", psz_host, i_port,
+                 gai_strerror (val));
         return -1;
     }
 
-    for( ptr = res; ptr != NULL; ptr = ptr->ai_next )
+    for (struct addrinfo *ptr = res; ptr != NULL; ptr = ptr->ai_next)
     {
         char *str;
         int fd = net_Socket (p_this, ptr->ai_family, ptr->ai_socktype,
@@ -647,11 +525,6 @@ int net_ConnectDgram( vlc_object_t *p_this, const char *psz_host, int i_port,
         if (fd == -1)
             continue;
 
-        /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s)
-        * to avoid packet loss caused by scheduling problems */
-        setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &(int){ 0x80000 }, sizeof (int));
-        setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &(int){ 0x80000 }, sizeof (int));
-
         /* Allow broadcast sending */
         setsockopt (fd, SOL_SOCKET, SO_BROADCAST, &(int){ 1 }, sizeof (int));
 
@@ -661,14 +534,7 @@ int net_ConnectDgram( vlc_object_t *p_this, const char *psz_host, int i_port,
         str = var_InheritString (p_this, "miface");
         if (str != NULL)
         {
-            net_SetMcastOut (p_this, fd, ptr->ai_family, str, NULL);
-            free (str);
-        }
-
-        str = var_InheritString (p_this, "miface-addr");
-        if (str != NULL)
-        {
-            net_SetMcastOut (p_this, fd, ptr->ai_family, NULL, str);
+            net_SetMcastOut (p_this, fd, ptr->ai_family, str);
             free (str);
         }
 
@@ -681,18 +547,16 @@ int net_ConnectDgram( vlc_object_t *p_this, const char *psz_host, int i_port,
             break;
         }
 
-#if defined( WIN32 ) || defined( UNDER_CE )
+#if defined( _WIN32 )
         if( WSAGetLastError () == WSAENETUNREACH )
 #else
         if( errno == ENETUNREACH )
 #endif
             b_unreach = true;
         else
-        {
-            msg_Warn( p_this, "%s port %d : %m", psz_host, i_port);
-            net_Close( fd );
-            continue;
-        }
+            msg_Warn( p_this, "%s port %d : %s", psz_host, i_port,
+                      vlc_strerror_c(errno) );
+        net_Close( fd );
     }
 
     freeaddrinfo( res );
@@ -723,14 +587,13 @@ int net_OpenDgram( vlc_object_t *obj, const char *psz_bind, int 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_socktype = SOCK_DGRAM;
-    hints.ai_protocol = protocol;
+    struct addrinfo hints = {
+        .ai_socktype = SOCK_DGRAM,
+        .ai_protocol = protocol,
+        .ai_flags = AI_NUMERICSERV | AI_IDN,
+    }, *loc, *rem;
 
-    val = vlc_getaddrinfo (obj, psz_server, i_server, &hints, &rem);
+    int val = vlc_getaddrinfo (psz_server, i_server, &hints, &rem);
     if (val)
     {
         msg_Err (obj, "cannot resolve %s port %d : %s", psz_bind, i_bind,
@@ -738,8 +601,8 @@ int net_OpenDgram( vlc_object_t *obj, const char *psz_bind, int i_bind,
         return -1;
     }
 
-    hints.ai_flags = AI_PASSIVE;
-    val = vlc_getaddrinfo (obj, psz_bind, i_bind, &hints, &loc);
+    hints.ai_flags |= AI_PASSIVE;
+    val = vlc_getaddrinfo (psz_bind, i_bind, &hints, &loc);
     if (val)
     {
         msg_Err (obj, "cannot resolve %s port %d : %s", psz_bind, i_bind,
@@ -773,8 +636,8 @@ int net_OpenDgram( vlc_object_t *obj, const char *psz_bind, int i_bind,
                                      ptr->ai_addr, ptr->ai_addrlen)
               : connect (fd, ptr2->ai_addr, ptr2->ai_addrlen))
             {
-                msg_Err (obj, "cannot connect to %s port %d: %m",
-                         psz_server, i_server);
+                msg_Err (obj, "cannot connect to %s port %d: %s",
+                         psz_server, i_server, vlc_strerror_c(net_errno));
                 continue;
             }
             val = fd;