Changeset 495353bb08f93ba5b01caaa1cc7cb71d4a17fda4
- Timestamp:
- 20/10/06 21:16:25
(2 years ago)
- Author:
- Rémi Denis-Courmont <rem@videolan.org>
- git-committer:
- Rémi Denis-Courmont <rem@videolan.org> 1161371785 +0000
- git-parent:
[e4f7eb8e91b05d9e56375119793bef68073b058e]
- git-author:
- Rémi Denis-Courmont <rem@videolan.org> 1161371785 +0000
- Message:
- 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
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| rc4ec9be |
r495353b |
|
| 438 | 438 | "system built-in default).") |
|---|
| 439 | 439 | |
|---|
| 440 | | #define MIFACE_TEXT N_("IPv6 multicast output interface") |
|---|
| | 440 | #define MIFACE_TEXT N_("Multicast output interface") |
|---|
| 441 | 441 | #define MIFACE_LONGTEXT N_( \ |
|---|
| 442 | | "Default IPv6 multicast interface. This overrides the routing table.") |
|---|
| | 442 | "Default multicast interface. This overrides the routing table.") |
|---|
| 443 | 443 | |
|---|
| 444 | 444 | #define MIFACE_ADDR_TEXT N_("IPv4 multicast output interface address") |
|---|
| … | … | |
| 446 | 446 | "IPv4 adress for the default multicast interface. This overrides " \ |
|---|
| 447 | 447 | "the routing table.") |
|---|
| | 448 | |
|---|
| | 449 | #define DSCP_TEXT N_("DiffServ Code Point") |
|---|
| | 450 | #define DSCP_LONGTEXT N_("Differentiated Services Code Point " \ |
|---|
| | 451 | "for outgoing UDP streams (or IPv4 Type Of Service, " \ |
|---|
| | 452 | "or IPv6 Traffic Class). This is used for network Quality of Service.") |
|---|
| 448 | 453 | |
|---|
| 449 | 454 | #define INPUT_PROGRAM_TEXT N_("Program") |
|---|
| … | … | |
| 1536 | 1541 | add_string( "miface", NULL, NULL, MIFACE_TEXT, MIFACE_LONGTEXT, VLC_TRUE ); |
|---|
| 1537 | 1542 | add_string( "miface-addr", NULL, NULL, MIFACE_ADDR_TEXT, MIFACE_ADDR_LONGTEXT, VLC_TRUE ); |
|---|
| | 1543 | add_integer( "dscp", 0, NULL, DSCP_TEXT, DSCP_LONGTEXT, VLC_TRUE ); |
|---|
| 1538 | 1544 | |
|---|
| 1539 | 1545 | set_subcategory( SUBCAT_SOUT_PACKETIZER ); |
|---|
| re7ef1d9 |
r495353b |
|
| 112 | 112 | |
|---|
| 113 | 113 | |
|---|
| 114 | | static int net_SetMcastIface( vlc_object_t *p_this, |
|---|
| 115 | | int fd, int family, const char *str ) |
|---|
| 116 | | { |
|---|
| 117 | | switch( family ) |
|---|
| 118 | | { |
|---|
| 119 | | #ifndef SYS_BEOS |
|---|
| 120 | | case AF_INET: |
|---|
| 121 | | { |
|---|
| 122 | | struct in_addr addr; |
|---|
| 123 | | |
|---|
| 124 | | if( inet_pton( AF_INET, str, &addr) <= 0 ) |
|---|
| 125 | | { |
|---|
| 126 | | msg_Err( p_this, "Invalid multicast interface %s", str ); |
|---|
| 127 | | return VLC_EGENERIC; |
|---|
| 128 | | } |
|---|
| 129 | | |
|---|
| 130 | | if( setsockopt( fd, SOL_IP, IP_MULTICAST_IF, &addr, |
|---|
| 131 | | sizeof( addr ) ) < 0 ) |
|---|
| 132 | | { |
|---|
| 133 | | msg_Err( p_this, "Cannot use %s as multicast interface: %s", |
|---|
| 134 | | str, strerror(errno) ); |
|---|
| 135 | | return VLC_EGENERIC; |
|---|
| 136 | | } |
|---|
| 137 | | break; |
|---|
| 138 | | } |
|---|
| 139 | | #endif /* SYS_BEOS */ |
|---|
| 140 | | |
|---|
| | 114 | static int net_SetMcastOutIface (int fd, int family, int scope) |
|---|
| | 115 | { |
|---|
| | 116 | switch (family) |
|---|
| | 117 | { |
|---|
| 141 | 118 | #ifdef IPV6_MULTICAST_IF |
|---|
| 142 | 119 | case AF_INET6: |
|---|
| 143 | | { |
|---|
| 144 | | int scope = if_nametoindex( str ); |
|---|
| 145 | | |
|---|
| 146 | | if( scope == 0 ) |
|---|
| | 120 | return setsockopt (fd, SOL_IPV6, IPV6_MULTICAST_IF, |
|---|
| | 121 | &scope, sizeof (scope)); |
|---|
| | 122 | #endif |
|---|
| | 123 | |
|---|
| | 124 | #ifdef __linux__ |
|---|
| | 125 | case AF_INET: |
|---|
| | 126 | { |
|---|
| | 127 | struct ip_mreqn req = { .imr_ifindex = scope }; |
|---|
| | 128 | |
|---|
| | 129 | return setsockopt (fd, SOL_IP, IP_MULTICAST_IF, &req, |
|---|
| | 130 | sizeof (req)); |
|---|
| | 131 | } |
|---|
| | 132 | #endif |
|---|
| | 133 | } |
|---|
| | 134 | |
|---|
| | 135 | errno = EAFNOSUPPORT; |
|---|
| | 136 | return -1; |
|---|
| | 137 | } |
|---|
| | 138 | |
|---|
| | 139 | |
|---|
| | 140 | static inline int net_SetMcastOutIPv4 (int fd, struct in_addr ipv4) |
|---|
| | 141 | { |
|---|
| | 142 | #ifdef IP_MULTICAST_IF |
|---|
| | 143 | return setsockopt( fd, SOL_IP, IP_MULTICAST_IF, &ipv4, sizeof (ipv4)); |
|---|
| | 144 | #else |
|---|
| | 145 | errno = EAFNOSUPPORT; |
|---|
| | 146 | return -1; |
|---|
| | 147 | #endif |
|---|
| | 148 | } |
|---|
| | 149 | |
|---|
| | 150 | |
|---|
| | 151 | static int net_SetMcastOut (vlc_object_t *p_this, int fd, int family, |
|---|
| | 152 | const char *iface, const char *addr) |
|---|
| | 153 | { |
|---|
| | 154 | if (iface != NULL) |
|---|
| | 155 | { |
|---|
| | 156 | int scope = if_nametoindex (iface); |
|---|
| | 157 | if (scope == 0) |
|---|
| | 158 | { |
|---|
| | 159 | msg_Err (p_this, "%s: invalid interface for multicast", iface); |
|---|
| | 160 | return -1; |
|---|
| | 161 | } |
|---|
| | 162 | |
|---|
| | 163 | if (net_SetMcastOutIface (fd, family, scope) == 0) |
|---|
| | 164 | return 0; |
|---|
| | 165 | |
|---|
| | 166 | msg_Err (p_this, "%s: %s", iface, net_strerror (net_errno)); |
|---|
| | 167 | } |
|---|
| | 168 | |
|---|
| | 169 | if (addr != NULL) |
|---|
| | 170 | { |
|---|
| | 171 | if (family == AF_INET) |
|---|
| | 172 | { |
|---|
| | 173 | struct in_addr ipv4; |
|---|
| | 174 | if (inet_pton (AF_INET, addr, &ipv4) <= 0) |
|---|
| 147 | 175 | { |
|---|
| 148 | | msg_Err( p_this, "Invalid multicast interface %s", str ); |
|---|
| 149 | | return VLC_EGENERIC; |
|---|
| | 176 | msg_Err (p_this, "%s: invalid IPv4 address for multicast", |
|---|
| | 177 | addr); |
|---|
| | 178 | return -1; |
|---|
| 150 | 179 | } |
|---|
| 151 | 180 | |
|---|
| 152 | | if( setsockopt( fd, SOL_IPV6, IPV6_MULTICAST_IF, |
|---|
| 153 | | &scope, sizeof( scope ) ) < 0 ) |
|---|
| 154 | | { |
|---|
| 155 | | msg_Err( p_this, "Cannot use %s as multicast interface: %s", |
|---|
| 156 | | str, strerror( errno ) ); |
|---|
| 157 | | return VLC_EGENERIC; |
|---|
| 158 | | } |
|---|
| 159 | | break; |
|---|
| 160 | | } |
|---|
| 161 | | #endif |
|---|
| 162 | | |
|---|
| 163 | | default: |
|---|
| 164 | | msg_Warn( p_this, "%s", strerror( EAFNOSUPPORT ) ); |
|---|
| 165 | | return VLC_EGENERIC; |
|---|
| 166 | | } |
|---|
| 167 | | |
|---|
| 168 | | return VLC_SUCCESS; |
|---|
| | 181 | if (net_SetMcastOutIPv4 (fd, ipv4) == 0) |
|---|
| | 182 | return 0; |
|---|
| | 183 | |
|---|
| | 184 | msg_Err (p_this, "%s: %s", addr, net_strerror (net_errno)); |
|---|
| | 185 | } |
|---|
| | 186 | } |
|---|
| | 187 | |
|---|
| | 188 | return -1; |
|---|
| 169 | 189 | } |
|---|
| 170 | 190 | |
|---|
| … | … | |
| 237 | 257 | for( ptr = res; ptr != NULL; ptr = ptr->ai_next ) |
|---|
| 238 | 258 | { |
|---|
| 239 | | int fd; |
|---|
| 240 | | char *psz_mif; |
|---|
| 241 | | |
|---|
| 242 | | fd = net_Socket( p_this, ptr->ai_family, ptr->ai_socktype, |
|---|
| 243 | | ptr->ai_protocol ); |
|---|
| 244 | | if( fd == -1 ) |
|---|
| | 259 | char *str; |
|---|
| | 260 | int fd = net_Socket (p_this, ptr->ai_family, ptr->ai_socktype, |
|---|
| | 261 | ptr->ai_protocol); |
|---|
| | 262 | if (fd == -1) |
|---|
| 245 | 263 | continue; |
|---|
| | 264 | |
|---|
| 246 | 265 | #if !defined( SYS_BEOS ) |
|---|
| 247 | | else |
|---|
| 248 | | { |
|---|
| 249 | | int i_val; |
|---|
| 250 | | |
|---|
| 251 | | /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) |
|---|
| 252 | | * to avoid packet loss caused by scheduling problems */ |
|---|
| 253 | | i_val = 0x80000; |
|---|
| 254 | | setsockopt( fd, SOL_SOCKET, SO_RCVBUF, (void *)&i_val, |
|---|
| 255 | | sizeof( i_val ) ); |
|---|
| 256 | | i_val = 0x80000; |
|---|
| 257 | | setsockopt( fd, SOL_SOCKET, SO_SNDBUF, (void *)&i_val, |
|---|
| 258 | | sizeof( i_val ) ); |
|---|
| 259 | | |
|---|
| 260 | | /* Allow broadcast sending */ |
|---|
| 261 | | i_val = 1; |
|---|
| 262 | | setsockopt( fd, SOL_SOCKET, SO_BROADCAST, (void*)&i_val, |
|---|
| 263 | | sizeof( i_val ) ); |
|---|
| 264 | | } |
|---|
| | 266 | /* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) |
|---|
| | 267 | * to avoid packet loss caused by scheduling problems */ |
|---|
| | 268 | setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &(int){ 0x80000 }, sizeof (int)); |
|---|
| | 269 | setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &(int){ 0x80000 }, sizeof (int)); |
|---|
| | 270 | |
|---|
| | 271 | /* Allow broadcast sending */ |
|---|
| | 272 | setsockopt (fd, SOL_SOCKET, SO_BROADCAST, &(int){ 1 }, sizeof (int)); |
|---|
| 265 | 273 | #endif |
|---|
| 266 | 274 | |
|---|
| 267 | 275 | if( i_hlim > 0 ) |
|---|
| 268 | 276 | net_SetMcastHopLimit( p_this, fd, ptr->ai_family, i_hlim ); |
|---|
| 269 | | psz_mif = config_GetPsz( p_this, (ptr->ai_family != AF_INET) |
|---|
| 270 | | ? "miface" : "miface-addr" ); |
|---|
| 271 | | if( psz_mif != NULL ) |
|---|
| 272 | | { |
|---|
| 273 | | net_SetMcastIface( p_this, fd, ptr->ai_family, psz_mif ); |
|---|
| 274 | | free( psz_mif ); |
|---|
| 275 | | } |
|---|
| | 277 | |
|---|
| | 278 | str = var_CreateGetString (p_this, "miface"); |
|---|
| | 279 | if (str != NULL) |
|---|
| | 280 | { |
|---|
| | 281 | net_SetMcastOut (p_this, fd, ptr->ai_family, str, NULL); |
|---|
| | 282 | free (str); |
|---|
| | 283 | } |
|---|
| | 284 | |
|---|
| | 285 | str = var_CreateGetString (p_this, "miface-addr"); |
|---|
| | 286 | if (str != NULL) |
|---|
| | 287 | { |
|---|
| | 288 | net_SetMcastOut (p_this, fd, ptr->ai_family, NULL, str); |
|---|
| | 289 | free (str); |
|---|
| | 290 | } |
|---|
| | 291 | |
|---|
| | 292 | net_SetDSCP (fd, var_CreateGetInteger (p_this, "dscp")); |
|---|
| 276 | 293 | |
|---|
| 277 | 294 | if( connect( fd, ptr->ai_addr, ptr->ai_addrlen ) == 0 ) |
|---|