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 )
{
msg_Err( p_this, "Invalid multicast interface %s", str );
return VLC_EGENERIC;
}
if( setsockopt( fd, SOL_IP, IP_MULTICAST_IF, &addr, return setsockopt (fd, SOL_IP, IP_MULTICAST_IF, &req,
sizeof( addr ) ) < 0 ) sizeof (req));
{
msg_Err( p_this, "Cannot use %s as multicast interface: %s",
str, strerror(errno) );
return VLC_EGENERIC;
}
break;
} }
#endif /* SYS_BEOS */ #endif
}
#ifdef IPV6_MULTICAST_IF errno = EAFNOSUPPORT;
case AF_INET6: 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)
{ {
int scope = if_nametoindex( str ); msg_Err (p_this, "%s: invalid interface for multicast", iface);
return -1;
}
if( scope == 0 ) if (net_SetMcastOutIface (fd, family, scope) == 0)
{ return 0;
msg_Err( p_this, "Invalid multicast interface %s", str );
return VLC_EGENERIC;
}
if( setsockopt( fd, SOL_IPV6, IPV6_MULTICAST_IF, msg_Err (p_this, "%s: %s", iface, net_strerror (net_errno));
&scope, sizeof( scope ) ) < 0 ) }
if (addr != NULL)
{
if (family == AF_INET)
{
struct in_addr ipv4;
if (inet_pton (AF_INET, addr, &ipv4) <= 0)
{ {
msg_Err( p_this, "Cannot use %s as multicast interface: %s", msg_Err (p_this, "%s: invalid IPv4 address for multicast",
str, strerror( errno ) ); addr);
return VLC_EGENERIC; return -1;
} }
break;
}
#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 ) #if !defined( SYS_BEOS )
else /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s)
{ * to avoid packet loss caused by scheduling problems */
int i_val; setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &(int){ 0x80000 }, sizeof (int));
setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &(int){ 0x80000 }, sizeof (int));
/* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s)
* to avoid packet loss caused by scheduling problems */ /* Allow broadcast sending */
i_val = 0x80000; setsockopt (fd, SOL_SOCKET, SO_BROADCAST, &(int){ 1 }, sizeof (int));
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 ) );
/* Allow broadcast sending */
i_val = 1;
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_SetMcastOut (p_this, fd, ptr->ai_family, str, NULL);
free (str);
}
str = var_CreateGetString (p_this, "miface-addr");
if (str != NULL)
{ {
net_SetMcastIface( p_this, fd, ptr->ai_family, psz_mif ); net_SetMcastOut (p_this, fd, ptr->ai_family, NULL, str);
free( psz_mif ); 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