# 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>
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)
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 ) );
#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)
}
-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,
* 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 )
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;