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

- hopefuly fix sending of SAP announces over IPv6

- automatically select SAP multicast address (closes #141)
- some clean up
parent 1d8cad44
...@@ -259,39 +259,10 @@ struct announce_method_t ...@@ -259,39 +259,10 @@ struct announce_method_t
int i_type; int i_type;
/* For SAP */ /* For SAP */
int i_ip_version;
char *psz_address; /* If we use a custom address */ char *psz_address; /* If we use a custom address */
char sz_ipv6_scope;
}; };
/* SAP Specific structures */
/* 100ms */
#define SAP_IDLE ((mtime_t)(0.100*CLOCK_FREQ))
#define SAP_MAX_BUFFER 65534
#define MIN_INTERVAL 2
#define MAX_INTERVAL 300
/* A SAP announce address. For each of these, we run the
* control flow algorithm */
struct sap_address_t
{
char *psz_address;
int i_ip_version;
int i_port;
int i_rfd; /* Read socket */
int i_wfd; /* Write socket */
/* Used for flow control */
mtime_t t1;
vlc_bool_t b_enabled;
vlc_bool_t b_ready;
int i_interval;
int i_buff;
int i_limit;
};
/* A SAP session descriptor, enqueued in the SAP handler queue */ /* A SAP session descriptor, enqueued in the SAP handler queue */
struct sap_session_t struct sap_session_t
{ {
......
...@@ -1234,6 +1234,7 @@ static int SapSetup( sout_stream_t *p_stream ) ...@@ -1234,6 +1234,7 @@ static int SapSetup( sout_stream_t *p_stream )
{ {
sout_stream_sys_t *p_sys = p_stream->p_sys; sout_stream_sys_t *p_sys = p_stream->p_sys;
sout_instance_t *p_sout = p_stream->p_sout; sout_instance_t *p_sout = p_stream->p_sout;
/* FIXME: use sout_AnnounceMethodCreate */
announce_method_t *p_method = (announce_method_t *) announce_method_t *p_method = (announce_method_t *)
malloc(sizeof(announce_method_t)); malloc(sizeof(announce_method_t));
...@@ -1246,7 +1247,6 @@ static int SapSetup( sout_stream_t *p_stream ) ...@@ -1246,7 +1247,6 @@ static int SapSetup( sout_stream_t *p_stream )
} }
p_method->i_type = METHOD_TYPE_SAP; p_method->i_type = METHOD_TYPE_SAP;
p_method->psz_address = NULL; /* FIXME */ p_method->psz_address = NULL; /* FIXME */
p_method->i_ip_version = 4; /* FIXME ! */
if( p_sys->i_es > 0 && p_sys->psz_sdp && *p_sys->psz_sdp ) if( p_sys->i_es > 0 && p_sys->psz_sdp && *p_sys->psz_sdp )
{ {
......
...@@ -63,9 +63,6 @@ ...@@ -63,9 +63,6 @@
#define SAP_TEXT N_("SAP announcing") #define SAP_TEXT N_("SAP announcing")
#define SAP_LONGTEXT N_("Announce this session with SAP") #define SAP_LONGTEXT N_("Announce this session with SAP")
#define SAPv6_TEXT N_("SAP IPv6 announcing")
#define SAPv6_LONGTEXT N_("Use IPv6 to announce this session with SAP")
#define SLP_TEXT N_("SLP announcing") #define SLP_TEXT N_("SLP announcing")
#define SLP_LONGTEXT N_("Announce this session with SLP") #define SLP_LONGTEXT N_("Announce this session with SLP")
...@@ -95,8 +92,7 @@ vlc_module_begin(); ...@@ -95,8 +92,7 @@ vlc_module_begin();
VLC_TRUE ); VLC_TRUE );
add_string( SOUT_CFG_PREFIX "group", "", NULL, GROUP_TEXT, GROUP_LONGTEXT, add_string( SOUT_CFG_PREFIX "group", "", NULL, GROUP_TEXT, GROUP_LONGTEXT,
VLC_TRUE ); VLC_TRUE );
add_bool( SOUT_CFG_PREFIX "sap-ipv6", 0, NULL, SAPv6_TEXT, SAPv6_LONGTEXT, add_deprecated( SOUT_CFG_PREFIX "sap-ipv6", VLC_FALSE );
VLC_TRUE );
add_bool( SOUT_CFG_PREFIX "slp", 0, NULL, SLP_TEXT, SLP_LONGTEXT, VLC_TRUE ); add_bool( SOUT_CFG_PREFIX "slp", 0, NULL, SLP_TEXT, SLP_LONGTEXT, VLC_TRUE );
...@@ -109,11 +105,9 @@ vlc_module_end(); ...@@ -109,11 +105,9 @@ vlc_module_end();
*****************************************************************************/ *****************************************************************************/
static const char *ppsz_sout_options[] = { static const char *ppsz_sout_options[] = {
"access", "mux", "url", "access", "mux", "url",
"sap", "name", "sap-ipv6", "group", "sap", "name", "group", "slp", NULL
"slp", NULL
}; };
#define DEFAULT_IPV6_SCOPE '8'
#define DEFAULT_PORT 1234 #define DEFAULT_PORT 1234
static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * ); static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
...@@ -349,9 +343,6 @@ static int Open( vlc_object_t *p_this ) ...@@ -349,9 +343,6 @@ static int Open( vlc_object_t *p_this )
} }
free( val.psz_string ); free( val.psz_string );
var_Get( p_stream, SOUT_CFG_PREFIX "sap-ipv6", &val );
p_method->i_ip_version = val.b_bool ? 6 : 4;
/* Now, parse the URL to extract host and port */ /* Now, parse the URL to extract host and port */
vlc_UrlParse( &url, psz_url , 0); vlc_UrlParse( &url, psz_url , 0);
...@@ -369,13 +360,11 @@ static int Open( vlc_object_t *p_this ) ...@@ -369,13 +360,11 @@ static int Open( vlc_object_t *p_this )
msg_Info( p_this, "SAP Enabled"); msg_Info( p_this, "SAP Enabled");
sout_AnnounceRegister( p_sout, p_session, p_method ); sout_AnnounceRegister( p_sout, p_session, p_method );
/* FIXME: Free p_method */
p_stream->p_sys->p_session = p_session; p_stream->p_sys->p_session = p_session;
} }
vlc_UrlClean( &url ); vlc_UrlClean( &url );
/* FIXME: Free p_method */
if( p_method->psz_address) free( p_method->psz_address ); if( p_method->psz_address) free( p_method->psz_address );
free( p_method ); free( p_method );
} }
......
...@@ -204,12 +204,8 @@ announce_method_t * sout_AnnounceMethodCreate( int i_type ) ...@@ -204,12 +204,8 @@ announce_method_t * sout_AnnounceMethodCreate( int i_type )
{ {
p_method->i_type = i_type; p_method->i_type = i_type;
if( i_type == METHOD_TYPE_SAP ) if( i_type == METHOD_TYPE_SAP )
{ /* Default value */
/* Default values */
p_method->psz_address = NULL; p_method->psz_address = NULL;
p_method->i_ip_version = 4 ;
p_method->sz_ipv6_scope = '\0';
}
} }
return p_method; return p_method;
} }
......
/***************************************************************************** /*****************************************************************************
* sap.c : SAP announce handler * sap.c : SAP announce handler
***************************************************************************** *****************************************************************************
* Copyright (C) 2002-2004 VideoLAN * Copyright (C) 2002-2005 VideoLAN
* $Id$ * $Id$
* *
* Authors: Clment Stenac <zorglub@videolan.org> * Authors: Clment Stenac <zorglub@videolan.org>
...@@ -27,25 +27,56 @@ ...@@ -27,25 +27,56 @@
#include <stdlib.h> /* free() */ #include <stdlib.h> /* free() */
#include <stdio.h> /* sprintf() */ #include <stdio.h> /* sprintf() */
#include <string.h> /* strerror() */ #include <string.h> /* strerror() */
#include <ctype.h> /* tolower(), isxdigit() */
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <vlc/sout.h> #include <vlc/sout.h>
#include <network.h> #include "network.h"
#if defined( WIN32 ) || defined( UNDER_CE )
# if defined(UNDER_CE) && defined(sockaddr_storage)
# undef sockaddr_storage
# endif
# include <winsock2.h>
# include <ws2tcpip.h>
#else
# include <netdb.h>
#endif
#include "charset.h" #include "charset.h"
#define SAP_IPV4_ADDR "224.2.127.254" /* Standard port and address for SAP */ /* SAP is always on that port */
#define SAP_PORT 9875 #define SAP_PORT 9875
#define SAP_IPV6_ADDR_1 "FF0"
#define SAP_IPV6_ADDR_2 "::2:7FFE"
#define DEFAULT_IPV6_SCOPE '8'
#define DEFAULT_PORT "1234" #define DEFAULT_PORT "1234"
#undef EXTRA_DEBUG #undef EXTRA_DEBUG
/* SAP Specific structures */
/* 100ms */
#define SAP_IDLE ((mtime_t)(0.100*CLOCK_FREQ))
#define SAP_MAX_BUFFER 65534
#define MIN_INTERVAL 2
#define MAX_INTERVAL 300
/* A SAP announce address. For each of these, we run the
* control flow algorithm */
struct sap_address_t
{
char *psz_address;
int i_port;
int i_rfd; /* Read socket */
int i_wfd; /* Write socket */
/* Used for flow control */
mtime_t t1;
vlc_bool_t b_enabled;
vlc_bool_t b_ready;
int i_interval;
int i_buff;
int i_limit;
};
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
*****************************************************************************/ *****************************************************************************/
...@@ -227,7 +258,7 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap, ...@@ -227,7 +258,7 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap,
char *psz_type = "application/sdp"; char *psz_type = "application/sdp";
int i_header_size; int i_header_size;
char *psz_head; char *psz_head;
vlc_bool_t b_found = VLC_FALSE; vlc_bool_t b_found = VLC_FALSE, b_ipv6;
sap_session_t *p_sap_session; sap_session_t *p_sap_session;
mtime_t i_hash; mtime_t i_hash;
...@@ -243,31 +274,84 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap, ...@@ -243,31 +274,84 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap,
} }
} }
if( !p_method->psz_address ) if( p_method->psz_address == NULL )
{ {
if( p_method->i_ip_version == 6 ) /* Determine SAP multicast address automatically */
char psz_buf[NI_MAXHOST];
const char *psz_addr;
struct addrinfo hints, *res;
if( p_session->psz_uri == NULL )
{ {
char sz_scope; msg_Err( p_sap, "*FIXME* Unexpected NULL URI for SAP announce" );
if( p_method->sz_ipv6_scope ) msg_Err( p_sap, "This should not happen. VLC needs fixing." );
vlc_mutex_unlock( &p_sap->object_lock );
return VLC_EGENERIC;
}
/* Canonicalize IP address (e.g. 224.00.010.1 => 224.0.10.1) */
memset( &hints, 0, sizeof( hints ) );
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_NUMERICHOST;
i = vlc_getaddrinfo( (vlc_object_t *)p_sap, p_session->psz_uri, NULL,
&hints, &res );
if( i == 0 )
i = vlc_getnameinfo( (vlc_object_t *)p_sap, res->ai_addr,
res->ai_addrlen, psz_buf, sizeof( psz_buf ),
NULL, 0, NI_NUMERICHOST );
if( i )
{
msg_Err( p_sap, "Invalid URI for SAP announce : %s : %s",
p_session->psz_uri, vlc_gai_strerror( i ) );
vlc_mutex_unlock( &p_sap->object_lock );
return VLC_EGENERIC;
}
if( strchr( psz_buf, ':' ) != NULL )
{
b_ipv6 = VLC_TRUE;
/* See RFC3513 for list of valid IPv6 scopes */
if( ( tolower( psz_buf[0] ) == 'f' )
&& ( tolower( psz_buf[1] ) == 'f' )
&& isxdigit( psz_buf[2] ) && isxdigit( psz_buf[3] ) )
{ {
sz_scope = p_method->sz_ipv6_scope; /* Multicast IPv6 */
psz_buf[2] = '0'; /* force flags to zero */
/* keep scope in psz_addr[3] */
memcpy( &psz_buf[4], "::2:7ffe", sizeof( "::2:7ffe" ) );
psz_addr = psz_buf;
} }
else else
{ /* Unicast IPv6 - assume global scope */
sz_scope = DEFAULT_IPV6_SCOPE; psz_addr = "ff0e::2:7ffe";
}
p_method->psz_address = (char*)malloc( 30*sizeof(char ));
sprintf( p_method->psz_address, "%s%c%s",
SAP_IPV6_ADDR_1, sz_scope, SAP_IPV6_ADDR_2 );
} }
else else
{ {
/* IPv4 */ b_ipv6 = VLC_FALSE;
p_method->psz_address = (char*)malloc( 15*sizeof(char) );
snprintf(p_method->psz_address, 15, SAP_IPV4_ADDR ); /* See RFC2365 for IPv4 scopes */
if( memcmp( psz_buf, "224.0.0.", 8 ) == 0 )
psz_addr = "224.0.0.255";
else
if( memcmp( psz_buf, "239.255.", 8 ) == 0 )
psz_addr = "239.255.255.255";
else
if( ( memcmp( psz_buf, "239.19", 6 ) == 0 )
&& ( ( psz_buf[6] >= '2' ) && ( psz_buf[6] <= '5' ) ) )
psz_addr = "239.195.255.255";
else
/* assume global scope */
psz_addr = "224.2.127.254";
} }
p_method->psz_address = strdup( psz_addr );
} }
msg_Dbg( p_sap, "using SAP address: %s",p_method->psz_address); else
b_ipv6 == (strchr( p_method->psz_address, ':' ) != NULL);
msg_Dbg( p_sap, "using SAP address: %s", p_method->psz_address);
/* XXX: Check for dupes */ /* XXX: Check for dupes */
p_sap_session = (sap_session_t*)malloc(sizeof(sap_session_t)); p_sap_session = (sap_session_t*)malloc(sizeof(sap_session_t));
...@@ -296,7 +380,6 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap, ...@@ -296,7 +380,6 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap,
return VLC_ENOMEM; return VLC_ENOMEM;
} }
p_address->psz_address = strdup( p_method->psz_address ); p_address->psz_address = strdup( p_method->psz_address );
p_address->i_ip_version = p_method->i_ip_version;
p_address->i_port = 9875; p_address->i_port = 9875;
p_address->i_wfd = net_OpenUDP( p_sap, "", 0, p_address->i_wfd = net_OpenUDP( p_sap, "", 0,
p_address->psz_address, p_address->psz_address,
...@@ -336,7 +419,7 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap, ...@@ -336,7 +419,7 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap,
} }
/* Build the SAP Headers */ /* Build the SAP Headers */
i_header_size = ( p_method->i_ip_version == 6 ? 20 : 8 ) + strlen( psz_type ) + 1; i_header_size = ( b_ipv6 ? 20 : 8 ) + strlen( psz_type ) + 1;
psz_head = (char *) malloc( i_header_size * sizeof( char ) ); psz_head = (char *) malloc( i_header_size * sizeof( char ) );
if( ! psz_head ) if( ! psz_head )
{ {
...@@ -351,7 +434,7 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap, ...@@ -351,7 +434,7 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap,
psz_head[2] = (i_hash & 0xFF00) >> 8; /* Msg id hash */ psz_head[2] = (i_hash & 0xFF00) >> 8; /* Msg id hash */
psz_head[3] = (i_hash & 0xFF); /* Msg id hash 2 */ psz_head[3] = (i_hash & 0xFF); /* Msg id hash 2 */
if( p_method->i_ip_version == 6 ) if( b_ipv6 )
{ {
/* in_addr_t ip_server = inet_addr( ip ); */ /* in_addr_t ip_server = inet_addr( ip ); */
psz_head[0] |= 0x10; /* Set IPv6 */ psz_head[0] |= 0x10; /* Set IPv6 */
...@@ -498,10 +581,13 @@ static int SDPGenerate( sap_handler_t *p_sap, session_descriptor_t *p_session ) ...@@ -498,10 +581,13 @@ static int SDPGenerate( sap_handler_t *p_sap, session_descriptor_t *p_session )
int64_t i_sdp_id = mdate(); int64_t i_sdp_id = mdate();
int i_sdp_version = 1 + p_sap->i_sessions + (rand()&0xfff); int i_sdp_version = 1 + p_sap->i_sessions + (rand()&0xfff);
char *psz_group, *psz_name; char *psz_group, *psz_name;
char ipv;
psz_group = convert_to_utf8( p_sap, p_session->psz_group ); psz_group = convert_to_utf8( p_sap, p_session->psz_group );
psz_name = convert_to_utf8( p_sap, p_session->psz_name ); psz_name = convert_to_utf8( p_sap, p_session->psz_name );
ipv = ( strchr( p_session->psz_uri, ':' ) != NULL) ? '6' : '4';
/* see the lists in modules/stream_out/rtp.c for compliance stuff */ /* see the lists in modules/stream_out/rtp.c for compliance stuff */
p_session->psz_sdp = (char *)malloc( p_session->psz_sdp = (char *)malloc(
sizeof("v=0\r\n" sizeof("v=0\r\n"
...@@ -528,12 +614,12 @@ static int SDPGenerate( sap_handler_t *p_sap, session_descriptor_t *p_session ) ...@@ -528,12 +614,12 @@ static int SDPGenerate( sap_handler_t *p_sap, session_descriptor_t *p_session )
"o=- "I64Fd" %d IN IP4 127.0.0.1\r\n" "o=- "I64Fd" %d IN IP4 127.0.0.1\r\n"
"s=%s\r\n" "s=%s\r\n"
"t=0 0\r\n" "t=0 0\r\n"
"c=IN IP4 %s/%d\r\n" "c=IN IP%c %s/%d\r\n"
"m=video %d udp %d\r\n" "m=video %d udp %d\r\n"
"a=tool:"PACKAGE_STRING"\r\n" "a=tool:"PACKAGE_STRING"\r\n"
"a=type:broadcast\r\n", "a=type:broadcast\r\n",
i_sdp_id, i_sdp_version, i_sdp_id, i_sdp_version,
psz_name, psz_name, ipv,
p_session->psz_uri, p_session->i_ttl, p_session->psz_uri, p_session->i_ttl,
p_session->i_port, p_session->i_payload ); p_session->i_port, p_session->i_payload );
free( psz_name ); free( psz_name );
......
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