Commit 495353bb authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

- Support for setting DSCP via dscp option

- Support for setting outgoing IPv4 multicast interface
  (note that only the Linux kernel can do that)
- Some cleaning/dirtying up
parent e4f7eb8e
......@@ -437,15 +437,20 @@ static char *ppsz_clock_descriptions[] =
"the multicast packets sent by the stream output (0 = use operating "\
"system built-in default).")
#define MIFACE_TEXT N_("IPv6 multicast output interface")
#define MIFACE_TEXT N_("Multicast output interface")
#define MIFACE_LONGTEXT N_( \
"Default IPv6 multicast interface. This overrides the routing table.")
"Default multicast interface. This overrides the routing table.")
#define MIFACE_ADDR_TEXT N_("IPv4 multicast output interface address")
#define MIFACE_ADDR_LONGTEXT N_( \
"IPv4 adress for the default multicast interface. This overrides " \
"the routing table.")
#define DSCP_TEXT N_("DiffServ Code Point")
#define DSCP_LONGTEXT N_("Differentiated Services Code Point " \
"for outgoing UDP streams (or IPv4 Type Of Service, " \
"or IPv6 Traffic Class). This is used for network Quality of Service.")
#define INPUT_PROGRAM_TEXT N_("Program")
#define INPUT_PROGRAM_LONGTEXT N_( \
"Choose the program to select by giving its Service ID. " \
......@@ -1535,6 +1540,7 @@ vlc_module_begin();
add_integer( "ttl", 0, NULL, TTL_TEXT, TTL_LONGTEXT, VLC_TRUE );
add_string( "miface", NULL, NULL, MIFACE_TEXT, MIFACE_LONGTEXT, VLC_TRUE );
add_string( "miface-addr", NULL, NULL, MIFACE_ADDR_TEXT, MIFACE_ADDR_LONGTEXT, VLC_TRUE );
add_integer( "dscp", 0, NULL, DSCP_TEXT, DSCP_LONGTEXT, VLC_TRUE );
set_subcategory( SUBCAT_SOUT_PACKETIZER );
add_module( "packetizer","packetizer", NULL, NULL,
......
......@@ -111,61 +111,81 @@ static int net_SetMcastHopLimit( vlc_object_t *p_this,
}
static int net_SetMcastIface( vlc_object_t *p_this,
int fd, int family, const char *str )
static int net_SetMcastOutIface (int fd, int family, int scope)
{
switch( family )
switch (family)
{
#ifndef SYS_BEOS
#ifdef IPV6_MULTICAST_IF
case AF_INET6:
return setsockopt (fd, SOL_IPV6, IPV6_MULTICAST_IF,
&scope, sizeof (scope));
#endif
#ifdef __linux__
case AF_INET:
{
struct in_addr addr;
struct ip_mreqn req = { .imr_ifindex = scope };
if( inet_pton( AF_INET, str, &addr) <= 0 )
{
msg_Err( p_this, "Invalid multicast interface %s", str );
return VLC_EGENERIC;
return setsockopt (fd, SOL_IP, IP_MULTICAST_IF, &req,
sizeof (req));
}
#endif
}
if( setsockopt( fd, SOL_IP, IP_MULTICAST_IF, &addr,
sizeof( addr ) ) < 0 )
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)
{
msg_Err( p_this, "Cannot use %s as multicast interface: %s",
str, strerror(errno) );
return VLC_EGENERIC;
}
break;
int scope = if_nametoindex (iface);
if (scope == 0)
{
msg_Err (p_this, "%s: invalid interface for multicast", iface);
return -1;
}
#endif /* SYS_BEOS */
#ifdef IPV6_MULTICAST_IF
case AF_INET6:
{
int scope = if_nametoindex( str );
if (net_SetMcastOutIface (fd, family, scope) == 0)
return 0;
if( scope == 0 )
{
msg_Err( p_this, "Invalid multicast interface %s", str );
return VLC_EGENERIC;
msg_Err (p_this, "%s: %s", iface, net_strerror (net_errno));
}
if( setsockopt( fd, SOL_IPV6, IPV6_MULTICAST_IF,
&scope, sizeof( scope ) ) < 0 )
if (addr != NULL)
{
msg_Err( p_this, "Cannot use %s as multicast interface: %s",
str, strerror( errno ) );
return VLC_EGENERIC;
}
break;
if (family == AF_INET)
{
struct in_addr ipv4;
if (inet_pton (AF_INET, addr, &ipv4) <= 0)
{
msg_Err (p_this, "%s: invalid IPv4 address for multicast",
addr);
return -1;
}
#endif
default:
msg_Warn( p_this, "%s", strerror( EAFNOSUPPORT ) );
return VLC_EGENERIC;
if (net_SetMcastOutIPv4 (fd, ipv4) == 0)
return 0;
msg_Err (p_this, "%s: %s", addr, net_strerror (net_errno));
}
}
return VLC_SUCCESS;
return -1;
}
......@@ -236,44 +256,41 @@ 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 );
if( fd == -1 )
char *str;
int fd = net_Socket (p_this, ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (fd == -1)
continue;
#if !defined( SYS_BEOS )
else
{
int i_val;
#if !defined( SYS_BEOS )
/* 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( fd, SOL_SOCKET, SO_RCVBUF, (void *)&i_val,
sizeof( i_val ) );
i_val = 0x80000;
setsockopt( fd, SOL_SOCKET, SO_SNDBUF, (void *)&i_val,
sizeof( i_val ) );
setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &(int){ 0x80000 }, sizeof (int));
setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &(int){ 0x80000 }, sizeof (int));
/* Allow broadcast sending */
i_val = 1;
setsockopt( fd, SOL_SOCKET, SO_BROADCAST, (void*)&i_val,
sizeof( i_val ) );
}
setsockopt (fd, SOL_SOCKET, SO_BROADCAST, &(int){ 1 }, sizeof (int));
#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 )
str = var_CreateGetString (p_this, "miface");
if (str != NULL)
{
net_SetMcastIface( p_this, fd, ptr->ai_family, psz_mif );
free( psz_mif );
net_SetMcastOut (p_this, fd, ptr->ai_family, str, NULL);
free (str);
}
str = var_CreateGetString (p_this, "miface-addr");
if (str != NULL)
{
net_SetMcastOut (p_this, fd, ptr->ai_family, NULL, str);
free (str);
}
net_SetDSCP (fd, var_CreateGetInteger (p_this, "dscp"));
if( connect( fd, ptr->ai_addr, ptr->ai_addrlen ) == 0 )
{
/* success */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment