X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fstream_output%2Fsap.c;h=2d2f88ad00af9ac34e097f5a4e1ef87664cec971;hb=f06a1f7aedb81379a0458b66714d772d7a461ec9;hp=94facfa352828c8b5c76f0e76adf52119a8f3957;hpb=7ef7ca63118a201c34d2a40b2c5ad968909d6d2e;p=vlc diff --git a/src/stream_output/sap.c b/src/stream_output/sap.c index 94facfa352..2d2f88ad00 100644 --- a/src/stream_output/sap.c +++ b/src/stream_output/sap.c @@ -32,6 +32,7 @@ #include #include +#include "charset.h" #define SAP_IPV4_ADDR "224.2.127.254" /* Standard port and address for SAP */ #define SAP_PORT 9875 @@ -62,6 +63,7 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap, static int announce_SAPAnnounceDel( sap_handler_t *p_sap, session_descriptor_t *p_session ); +static char *convert_to_utf8( struct sap_handler_t *p_this, char *psz_local ); #define FREE( p ) if( p ) { free( p ); (p) = NULL; } @@ -75,6 +77,7 @@ static int announce_SAPAnnounceDel( sap_handler_t *p_sap, sap_handler_t *announce_SAPHandlerCreate( announce_handler_t *p_announce ) { sap_handler_t *p_sap; + char *psz_charset; p_sap = vlc_object_create( p_announce, sizeof( sap_handler_t ) ); @@ -86,6 +89,14 @@ sap_handler_t *announce_SAPHandlerCreate( announce_handler_t *p_announce ) vlc_mutex_init( p_sap, &p_sap->object_lock ); + vlc_current_charset( &psz_charset ); + p_sap->iconvHandle = vlc_iconv_open( "UTF-8", psz_charset ); + free( psz_charset ); + if( p_sap->iconvHandle == (vlc_iconv_t)(-1) ) + { + msg_Warn( p_sap, "Unable to do requested conversion" ); + } + p_sap->pf_add = announce_SAPAnnounceAdd; p_sap->pf_del = announce_SAPAnnounceDel; @@ -144,6 +155,9 @@ void announce_SAPHandlerDestroy( sap_handler_t *p_sap ) FREE( p_address ); } + if( p_sap->iconvHandle != (vlc_iconv_t)(-1) ) + vlc_iconv_close( p_sap->iconvHandle ); + /* Free the structure */ vlc_object_destroy( p_sap ); } @@ -215,6 +229,7 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap, char *psz_head; vlc_bool_t b_found = VLC_FALSE; sap_session_t *p_sap_session; + mtime_t i_hash; vlc_mutex_lock( &p_sap->object_lock ); @@ -233,9 +248,9 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap, if( p_method->i_ip_version == 6 ) { char sz_scope; - if( p_method->psz_ipv6_scope != NULL ) + if( p_method->sz_ipv6_scope ) { - sz_scope = *p_method->psz_ipv6_scope; + sz_scope = p_method->sz_ipv6_scope; } else { @@ -249,7 +264,7 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap, { /* IPv4 */ p_method->psz_address = (char*)malloc( 15*sizeof(char) ); - sprintf(p_method->psz_address, SAP_IPV4_ADDR ); + snprintf(p_method->psz_address, 15, SAP_IPV4_ADDR ); } } msg_Dbg( p_sap, "using SAP address: %s",p_method->psz_address); @@ -281,6 +296,7 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap, return VLC_ENOMEM; } 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_wfd = net_OpenUDP( p_sap, "", 0, p_address->psz_address, @@ -302,6 +318,7 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap, p_address->b_enabled = VLC_TRUE; p_address->b_ready = VLC_TRUE; p_address->i_interval = config_GetInt( p_sap,"sap-interval"); + p_address->i_rfd = -1; } if( p_address->i_wfd == -1 || (p_address->i_rfd == -1 @@ -319,7 +336,7 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap, } /* Build the SAP Headers */ - i_header_size = 8 + strlen( psz_type ) + 1; + i_header_size = ( p_method->i_ip_version == 6 ? 20 : 8 ) + strlen( psz_type ) + 1; psz_head = (char *) malloc( i_header_size * sizeof( char ) ); if( ! psz_head ) { @@ -327,17 +344,52 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap, return VLC_ENOMEM; } - psz_head[0] = 0x20; /* Means IPv4, not encrypted, not compressed */ - psz_head[1] = 0x00; /* No authentification */ - psz_head[2] = 0x42; /* Msg id hash */ - psz_head[3] = 0x12; /* Msg id hash 2 */ + psz_head[0] = 0x20; /* Means SAPv1, IPv4, not encrypted, not compressed */ + psz_head[1] = 0x00; /* No authentification length */ - psz_head[4] = 0x01; /* Source IP FIXME: we should get the real address */ - psz_head[5] = 0x02; /* idem */ - psz_head[6] = 0x03; /* idem */ - psz_head[7] = 0x04; /* idem */ + i_hash = mdate(); + psz_head[2] = (i_hash & 0xFF00) >> 8; /* Msg id hash */ + psz_head[3] = (i_hash & 0xFF); /* Msg id hash 2 */ + + if( p_method->i_ip_version == 6 ) + { + /* in_addr_t ip_server = inet_addr( ip ); */ + psz_head[0] |= 0x10; /* Set IPv6 */ + + psz_head[4] = 0x01; /* Source IP FIXME: we should get the real address */ + psz_head[5] = 0x02; /* idem */ + psz_head[6] = 0x03; /* idem */ + psz_head[7] = 0x04; /* idem */ + + psz_head[8] = 0x01; /* Source IP FIXME: we should get the real address */ + psz_head[9] = 0x02; /* idem */ + psz_head[10] = 0x03; /* idem */ + psz_head[11] = 0x04; /* idem */ + + psz_head[12] = 0x01; /* Source IP FIXME: we should get the real address */ + psz_head[13] = 0x02; /* idem */ + psz_head[14] = 0x03; /* idem */ + psz_head[15] = 0x04; /* idem */ + + psz_head[16] = 0x01; /* Source IP FIXME: we should get the real address */ + psz_head[17] = 0x02; /* idem */ + psz_head[18] = 0x03; /* idem */ + psz_head[19] = 0x04; /* idem */ + + strncpy( psz_head + 20, psz_type, 15 ); + } + else + { + /* in_addr_t ip_server = inet_addr( ip) */ + /* Source IP FIXME: we should get the real address */ + psz_head[4] = 0x01; /* ip_server */ + psz_head[5] = 0x02; /* ip_server>>8 */ + psz_head[6] = 0x03; /* ip_server>>16 */ + psz_head[7] = 0x04; /* ip_server>>24 */ + + strncpy( psz_head + 8, psz_type, 15 ); + } - strncpy( psz_head + 8, psz_type, 15 ); psz_head[ i_header_size-1 ] = '\0'; p_sap_session->i_length = i_header_size + strlen( p_sap_session->psz_sdp); @@ -349,6 +401,8 @@ static int announce_SAPAnnounceAdd( sap_handler_t *p_sap, memcpy( p_sap_session->psz_data+i_header_size, p_sap_session->psz_sdp, strlen( p_sap_session->psz_sdp) ); + free( psz_head ); + /* Enqueue the announce */ INSERT_ELEM( p_sap->pp_sessions, p_sap->i_sessions, @@ -382,12 +436,17 @@ static int announce_SAPAnnounceDel( sap_handler_t *p_sap, REMOVE_ELEM( p_sap->pp_sessions, p_sap->i_sessions, i ); + + FREE( p_session->p_sap->psz_sdp ); + FREE( p_session->p_sap->psz_data ); + free( p_session->p_sap ); break; } } - /* XXX: Dequeue the adress too if it is not used anymore - * TODO: address refcount */ + /* XXX: Dequeue the address too if it is not used anymore + * TODO: - address refcount + - send a SAP deletion packet */ msg_Dbg( p_sap,"%i announces remaining", p_sap->i_sessions ); @@ -414,7 +473,7 @@ static int announce_SendSAPAnnounce( sap_handler_t *p_sap, #ifdef EXTRA_DEBUG msg_Dbg( p_sap, "Sending announce"); #endif - i_ret = net_Write( p_sap, p_session->p_address->i_wfd, + i_ret = net_Write( p_sap, p_session->p_address->i_wfd, NULL, p_session->psz_data, p_session->i_length ); if( i_ret != p_session->i_length ) @@ -438,6 +497,10 @@ static int SDPGenerate( sap_handler_t *p_sap, session_descriptor_t *p_session ) { int64_t i_sdp_id = mdate(); int i_sdp_version = 1 + p_sap->i_sessions + (rand()&0xfff); + char *psz_group, *psz_name; + + psz_group = convert_to_utf8( p_sap, p_session->psz_group ); + psz_name = convert_to_utf8( p_sap, p_session->psz_name ); /* see the lists in modules/stream_out/rtp.c for compliance stuff */ p_session->psz_sdp = (char *)malloc( @@ -449,11 +512,15 @@ static int SDPGenerate( sap_handler_t *p_sap, session_descriptor_t *p_session ) "m=video udp\r\n" "a=tool:"PACKAGE_STRING"\r\n" "a=type:broadcast\r\n") - + strlen( p_session->psz_name ) - + strlen( p_session->psz_uri ) + 300 ); - if( !p_session->psz_sdp ) + + strlen( psz_name ) + + strlen( p_session->psz_uri ) + 300 + + ( psz_group ? strlen( psz_group ) : 0 ) ); + + if( p_session->psz_sdp == NULL || psz_name == NULL ) { msg_Err( p_sap, "out of memory" ); + FREE( psz_name ); + FREE( psz_group ); return VLC_ENOMEM; } sprintf( p_session->psz_sdp, @@ -466,9 +533,18 @@ static int SDPGenerate( sap_handler_t *p_sap, session_descriptor_t *p_session ) "a=tool:"PACKAGE_STRING"\r\n" "a=type:broadcast\r\n", i_sdp_id, i_sdp_version, - p_session->psz_name, + psz_name, p_session->psz_uri, p_session->i_ttl, p_session->i_port, p_session->i_payload ); + free( psz_name ); + + if( psz_group ) + { + sprintf( p_session->psz_sdp, "%sa=x-plgroup:%s\r\n", + p_session->psz_sdp, psz_group ); + free( psz_group ); + } + msg_Dbg( p_sap, "Generated SDP (%i bytes):\n%s", strlen(p_session->psz_sdp), p_session->psz_sdp ); return VLC_SUCCESS; @@ -490,7 +566,7 @@ static int CalculateRate( sap_handler_t *p_sap, sap_address_t *p_address ) do { /* Might be too slow if we have huge data */ - i_read = net_ReadNonBlock( p_sap, p_address->i_rfd, buffer, + i_read = net_ReadNonBlock( p_sap, p_address->i_rfd, NULL, buffer, SAP_MAX_BUFFER, 0 ); i_tot += i_read; } while( i_read > 0 && i_tot < SAP_MAX_BUFFER ); @@ -531,3 +607,34 @@ static int CalculateRate( sap_handler_t *p_sap, sap_address_t *p_address ) return VLC_SUCCESS; } + + +static char *convert_to_utf8( struct sap_handler_t *p_this, char *psz_local ) +{ + char *psz_unicode, *psz_in, *psz_out; + size_t ret, i_in, i_out; + + if( psz_local == NULL ) + return NULL; + if ( p_this->iconvHandle == (vlc_iconv_t)(-1) ) + return strdup( psz_local ); + + psz_in = psz_local; + i_in = strlen( psz_local ); + + i_out = 6 * i_in; + psz_unicode = malloc( i_out + 1 ); + if( psz_unicode == NULL ) + return strdup( psz_local ); + psz_out = psz_unicode; + + ret = vlc_iconv( p_this->iconvHandle, + &psz_in, &i_in, &psz_out, &i_out); + if( ret == (size_t)(-1) || i_in ) + { + msg_Warn( p_this, "Failed to convert \"%s\" to UTF-8", psz_local ); + return strdup( psz_local ); + } + *psz_out = '\0'; + return psz_unicode; +}