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[] = ...@@ -437,15 +437,20 @@ static char *ppsz_clock_descriptions[] =
"the multicast packets sent by the stream output (0 = use operating "\ "the multicast packets sent by the stream output (0 = use operating "\
"system built-in default).") "system built-in default).")
#define MIFACE_TEXT N_("IPv6 multicast output interface") #define MIFACE_TEXT N_("Multicast output interface")
#define MIFACE_LONGTEXT N_( \ #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_TEXT N_("IPv4 multicast output interface address")
#define MIFACE_ADDR_LONGTEXT N_( \ #define MIFACE_ADDR_LONGTEXT N_( \
"IPv4 adress for the default multicast interface. This overrides " \ "IPv4 adress for the default multicast interface. This overrides " \
"the routing table.") "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_TEXT N_("Program")
#define INPUT_PROGRAM_LONGTEXT N_( \ #define INPUT_PROGRAM_LONGTEXT N_( \
"Choose the program to select by giving its Service ID. " \ "Choose the program to select by giving its Service ID. " \
...@@ -1535,6 +1540,7 @@ vlc_module_begin(); ...@@ -1535,6 +1540,7 @@ vlc_module_begin();
add_integer( "ttl", 0, NULL, TTL_TEXT, TTL_LONGTEXT, VLC_TRUE ); 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", NULL, NULL, MIFACE_TEXT, MIFACE_LONGTEXT, VLC_TRUE );
add_string( "miface-addr", NULL, NULL, MIFACE_ADDR_TEXT, MIFACE_ADDR_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 ); set_subcategory( SUBCAT_SOUT_PACKETIZER );
add_module( "packetizer","packetizer", NULL, NULL, add_module( "packetizer","packetizer", NULL, NULL,
......
...@@ -111,61 +111,81 @@ static int net_SetMcastHopLimit( vlc_object_t *p_this, ...@@ -111,61 +111,81 @@ static int net_SetMcastHopLimit( vlc_object_t *p_this,
} }
static int net_SetMcastIface( vlc_object_t *p_this, static int net_SetMcastOutIface (int fd, int family, int scope)
int fd, int family, const char *str )
{ {
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: case AF_INET:
{ {
struct in_addr addr; struct ip_mreqn req = { .imr_ifindex = scope };
if( inet_pton( AF_INET, str, &addr) <= 0 ) return setsockopt (fd, SOL_IP, IP_MULTICAST_IF, &req,
{ sizeof (req));
msg_Err( p_this, "Invalid multicast interface %s", str ); }
return VLC_EGENERIC; #endif
} }
if( setsockopt( fd, SOL_IP, IP_MULTICAST_IF, &addr, errno = EAFNOSUPPORT;
sizeof( addr ) ) < 0 ) 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", int scope = if_nametoindex (iface);
str, strerror(errno) ); if (scope == 0)
return VLC_EGENERIC; {
} msg_Err (p_this, "%s: invalid interface for multicast", iface);
break; return -1;
} }
#endif /* SYS_BEOS */
#ifdef IPV6_MULTICAST_IF if (net_SetMcastOutIface (fd, family, scope) == 0)
case AF_INET6: return 0;
{
int scope = if_nametoindex( str );
if( scope == 0 ) msg_Err (p_this, "%s: %s", iface, net_strerror (net_errno));
{
msg_Err( p_this, "Invalid multicast interface %s", str );
return VLC_EGENERIC;
} }
if( setsockopt( fd, SOL_IPV6, IPV6_MULTICAST_IF, if (addr != NULL)
&scope, sizeof( scope ) ) < 0 )
{ {
msg_Err( p_this, "Cannot use %s as multicast interface: %s", if (family == AF_INET)
str, strerror( errno ) ); {
return VLC_EGENERIC; struct in_addr ipv4;
} if (inet_pton (AF_INET, addr, &ipv4) <= 0)
break; {
msg_Err (p_this, "%s: invalid IPv4 address for multicast",
addr);
return -1;
} }
#endif
default: if (net_SetMcastOutIPv4 (fd, ipv4) == 0)
msg_Warn( p_this, "%s", strerror( EAFNOSUPPORT ) ); return 0;
return VLC_EGENERIC;
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, ...@@ -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 ) for( ptr = res; ptr != NULL; ptr = ptr->ai_next )
{ {
int fd; char *str;
char *psz_mif; int fd = net_Socket (p_this, ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
fd = net_Socket( p_this, ptr->ai_family, ptr->ai_socktype, if (fd == -1)
ptr->ai_protocol );
if( fd == -1 )
continue; 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) /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s)
* to avoid packet loss caused by scheduling problems */ * to avoid packet loss caused by scheduling problems */
i_val = 0x80000; setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &(int){ 0x80000 }, sizeof (int));
setsockopt( fd, SOL_SOCKET, SO_RCVBUF, (void *)&i_val, setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &(int){ 0x80000 }, sizeof (int));
sizeof( i_val ) );
i_val = 0x80000;
setsockopt( fd, SOL_SOCKET, SO_SNDBUF, (void *)&i_val,
sizeof( i_val ) );
/* Allow broadcast sending */ /* Allow broadcast sending */
i_val = 1; setsockopt (fd, SOL_SOCKET, SO_BROADCAST, &(int){ 1 }, sizeof (int));
setsockopt( fd, SOL_SOCKET, SO_BROADCAST, (void*)&i_val,
sizeof( i_val ) );
}
#endif #endif
if( i_hlim > 0 ) if( i_hlim > 0 )
net_SetMcastHopLimit( p_this, fd, ptr->ai_family, i_hlim ); net_SetMcastHopLimit( p_this, fd, ptr->ai_family, i_hlim );
psz_mif = config_GetPsz( p_this, (ptr->ai_family != AF_INET)
? "miface" : "miface-addr" ); str = var_CreateGetString (p_this, "miface");
if( psz_mif != NULL ) if (str != NULL)
{ {
net_SetMcastIface( p_this, fd, ptr->ai_family, psz_mif ); net_SetMcastOut (p_this, fd, ptr->ai_family, str, NULL);
free( psz_mif ); 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 ) if( connect( fd, ptr->ai_addr, ptr->ai_addrlen ) == 0 )
{ {
/* success */ /* 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